blob: e050de767bc3dcff03f6d38de33920c2bcde35b9 [file] [log] [blame]
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:release_notes Appendix A: Release Notes]
[/=================]
[heading Boost 1.44]
[/=================]
[*Behavior Change: proto::and_<>]
In Boost 1.44, the behavior of _and_ as a transform changed. Previously, it only
applied the transform associated with the last grammar in the set. Now, it applies
all the transforms but only returns the result of the last. That makes it behave
like C++'s comma operator. For example, a grammar such as:
proto::and_< G0, G1, G2 >
when evaluated with an expression `e` now behaves like this:
(G0()(e), G1()(e), G2()(e))
[*Behavior Change: proto::as_expr() and proto::as_child()]
The functions _as_expr_ and _as_child_ are used to guarantee that an
object is a Proto expression by turning it into one if it is not already,
using an optionally specified domain. In previous releases, when these
functions were passed a Proto expression in a domain different to the one
specified, they would apply the specified domain's generator, resulting in
a twice-wrapped expression. This behavior was surprising to some users.
The new behavior of these two functions is to always leave Proto expressions
alone, regardless of the expressions' domains.
[*Behavior Change: proto::(pod_)generator<> and proto::basic_expr<>]
Users familiar with Proto's extension mechanism have probably used either
_generator_ or _pod_generator_ with a wrapper template when defining their
domain. In the past, Proto would instantiate your wrapper template with
instances of _expr_. In Boost 1.44, Proto now instantiates your wrapper
template with instances of a new type: _basic_expr_.
For instance:
// An expression wrapper
template<class Expr>
struct my_expr_wrapper;
// A domain
struct my_domain
: proto::domain< proto::generator< my_expr_wrapper > >
{};
template<class Expr>
struct my_expr_wrapper
: proto::extends<Expr, my_expr_wrapper<Expr>, my_domain>
{
// Before 1.44, Expr was an instance of proto::expr<>
// In 1.44, Expr is an instance of proto::basic_expr<>
};
The motivation for this change was to improve compile times. _expr_ is an
expensive type to instantiate because it defines a host of member functions.
When defining your own expression wrapper, the instance of _expr_ sits as a
hidden data member function in your wrapper and the members of _expr_ go
unused. Therefore, the cost of those member functions is wasted. In contrast,
_basic_expr_ is a very lightweight type with no member functions at all.
The vast majority of programs should recompile without any source changes.
However, if somewhere you are assuming that you will be given instances
specifically of _expr_, your code will break.
[*New Feature: Sub-domains]
In Boost 1.44, Proto introduces an important new feature called
"sub-domains". This gives you a way to spcify that one domain is
compatible with another such that expressions in one domain can
be freely mixed with expressions in another. You can define one
domain to be the sub-domain of another by using the third template
parameter of _domain_.
For instance:
// Not shown: define some expression
// generators genA and genB
struct A
: proto::domain< genA, proto::_ >
{};
// Define a domain B that is the sub-domain
// of domain A.
struct B
: proto::domain< genB, proto::_, A >
{};
Expressions in domains `A` and `B` can have different wrappers
(hence, different interfaces), but they can be combined into larger
expressions. Without a sub-domain relationship, this would have
been an error. The domain of the resulting expression in this case
would be `A`.
The complete description of sub-domains can be found in the reference
sections for _domain_ and _deduce_domain_.
[*New Feature: Domain-specific as_expr() and as_child()]
Proto has always allowed users to customize expressions post-hoc by
specifying a Generator when defining their domain. But it has never
allowed users to control how Proto assembles sub-expressions in the
first place. As of Boost 1.44, users now have this power.
Users defining their own domain can now specify how _as_expr_ and
_as_child_ work in their domain. They can do this easily by defining
nested class templates named `as_expr` and/or `as_child` within their
domain class.
For example:
struct my_domain
: proto::domain< my_generator >
{
typedef
proto::domain< my_generator >
base_domain;
// For my_domain, as_child does the same as
// what as_expr does by default.
template<class T>
struct as_child
: base_domain::as_expr<T>
{};
};
In the above example, `my_domain::as_child<>` simply defers to
`proto::domain::as_expr<>`. This has the nice effect of causing
all terminals to be captured by value instead of by reference,
and to likewise store child expressions by value. The result is
that expressions in `my_domain` are safe to store in `auto`
variables because they will not have dangling references to
intermediate temporary expressions. (Naturally, it also means that
expression construction has extra runtime overhead of copying that
the compiler may or may not be able to optimize away.)
[/=================]
[heading Boost 1.43]
[/=================]
In Boost 1.43, the recommended usage of _extends_ changed slightly. The new
usage looks like this:
// my_expr is an expression extension of the Expr parameter
template<typename Expr>
struct my_expr
: proto::extends<Expr, my_expr<Expr>, my_domain>
{
my_expr(Expr const &expr = Expr())
: proto::extends<Expr, my_expr, my_domain>(expr)
{}
// NEW: use the following macro to bring
// proto::extends::operator= into scope.
BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr)
};
The new thing is the use of the [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()] macro.
To allow assignment operators to build expression trees, _extends_ overloads the
assignment operator. However, for the `my_expr` template, the compiler generates
a default copy assignment operator that hides the ones in _extends_. This is often
not desired (although it depends on the syntax you want to allow).
Previously, the recommended usage was to do this:
// my_expr is an expression extension of the Expr parameter
template<typename Expr>
struct my_expr
: proto::extends<Expr, my_expr<Expr>, my_domain>
{
my_expr(Expr const &expr = Expr())
: proto::extends<Expr, my_expr, my_domain>(expr)
{}
// OLD: don't do it like this anymore.
using proto::extends<Expr, my_expr, my_domain>::operator=;
};
While this works in the majority of cases, it still doesn't suppress the
implicit generation of the default assignment operator. As a result, expressions
of the form `a = b` could either build an expression template or do a copy
assignment depending on whether the types of `a` and `b` happen to be the
same. That can lead to subtle bugs, so the behavior was changed.
The [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()] brings into scope the
assignment operators defined in _extends_ as well as suppresses the generation
of the copy assignment operator.
Also note that the _literal_ class template, which uses _extends_, has been chaged
to use [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()]. The implications are
highlighted in the sample code below:
proto::literal<int> a(1), b(2); // two non-const proto literals
proto::literal<int> const c(3); // a const proto literal
a = b; // No-op. Builds an expression tree and discards it.
// Same behavior in 1.42 and 1.43.
a = c; // CHANGE! In 1.42, this performed copy assignment, causing
// a's value to change to 3. In 1.43, the behavior is now
// the same as above: build and discard an expression tree.
[endsect]