1[/ 2 / Copyright (c) 2008-2012 Eric Niebler 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:release_notes Appendix A: Release Notes] 9 10[/=================] 11[heading Boost 1.51] 12[/=================] 13 14[*Unpacking Expressions] 15 16In Boost 1.51, Proto got simple unpacking patterns. When working with Proto transforms, unpacking expressions are useful for unpacking the children of an expression into a function call or an object constructor, while optionally applying some transformations to each child in turn. 17 18See the [link boost_proto.users_guide.back_end.expression_transformation.unpacking_expressions Unpacking Expressions] section for more information. 19 20[/=================] 21[heading Boost 1.44] 22[/=================] 23 24[*Behavior Change: proto::and_<>] 25 26In 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: 27 28 proto::and_< G0, G1, G2 > 29 30when evaluated with an expression `e` now behaves like this: 31 32 ((void)G0()(e), (void)G1()(e), G2()(e)) 33 34[note Why the void casts? It's to avoid argument-dependent lookup, which might find an overloaded comma operator.] 35 36[*Behavior Change: proto::as_expr() and proto::as_child()] 37 38The 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. 39 40The new behavior of these two functions is to always leave Proto expressions alone, regardless of the expressions' domains. 41 42[*Behavior Change: proto::(pod_)generator<> and proto::basic_expr<>] 43 44Users 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_. 45 46For instance: 47 48 // An expression wrapper 49 template<class Expr> 50 struct my_expr_wrapper; 51 52 // A domain 53 struct my_domain 54 : proto::domain< proto::generator< my_expr_wrapper > > 55 {}; 56 57 template<class Expr> 58 struct my_expr_wrapper 59 : proto::extends<Expr, my_expr_wrapper<Expr>, my_domain> 60 { 61 // Before 1.44, Expr was an instance of proto::expr<> 62 // In 1.44, Expr is an instance of proto::basic_expr<> 63 }; 64 65The 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. 66 67The 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. 68 69[*New Feature: Sub-domains] 70 71In 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_. 72 73For instance: 74 75 // Not shown: define some expression 76 // generators genA and genB 77 78 struct A 79 : proto::domain< genA, proto::_ > 80 {}; 81 82 // Define a domain B that is the sub-domain 83 // of domain A. 84 struct B 85 : proto::domain< genB, proto::_, A > 86 {}; 87 88Expressions 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`. 89 90The complete description of sub-domains can be found in the reference 91sections for _domain_ and _deduce_domain_. 92 93[*New Feature: Domain-specific as_expr() and as_child()] 94 95Proto 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. 96 97Users 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. 98 99For example: 100 101 struct my_domain 102 : proto::domain< my_generator > 103 { 104 typedef 105 proto::domain< my_generator > 106 base_domain; 107 108 // For my_domain, as_child does the same as 109 // what as_expr does by default. 110 template<class T> 111 struct as_child 112 : base_domain::as_expr<T> 113 {}; 114 }; 115 116In 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.) 117 118[/=================] 119[heading Boost 1.43] 120[/=================] 121 122In Boost 1.43, the recommended usage of _extends_ changed slightly. The new 123usage looks like this: 124 125 // my_expr is an expression extension of the Expr parameter 126 template<typename Expr> 127 struct my_expr 128 : proto::extends<Expr, my_expr<Expr>, my_domain> 129 { 130 my_expr(Expr const &expr = Expr()) 131 : proto::extends<Expr, my_expr, my_domain>(expr) 132 {} 133 134 // NEW: use the following macro to bring 135 // proto::extends::operator= into scope. 136 BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr) 137 }; 138 139The 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). 140 141Previously, the recommended usage was to do this: 142 143 // my_expr is an expression extension of the Expr parameter 144 template<typename Expr> 145 struct my_expr 146 : proto::extends<Expr, my_expr<Expr>, my_domain> 147 { 148 my_expr(Expr const &expr = Expr()) 149 : proto::extends<Expr, my_expr, my_domain>(expr) 150 {} 151 152 // OLD: don't do it like this anymore. 153 using proto::extends<Expr, my_expr, my_domain>::operator=; 154 }; 155 156While 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. 157 158The [^[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. 159 160Also 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: 161 162 proto::literal<int> a(1), b(2); // two non-const proto literals 163 proto::literal<int> const c(3); // a const proto literal 164 165 a = b; // No-op. Builds an expression tree and discards it. 166 // Same behavior in 1.42 and 1.43. 167 168 a = c; // CHANGE! In 1.42, this performed copy assignment, causing 169 // a's value to change to 3. In 1.43, the behavior is now 170 // the same as above: build and discard an expression tree. 171 172[endsect] 173