Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2008-02-06 19:05:02


Author: eric_niebler
Date: 2008-02-06 19:05:01 EST (Wed, 06 Feb 2008)
New Revision: 43136
URL: http://svn.boost.org/trac/boost/changeset/43136

Log:
reasonably complete user docs for expression evaluation
Text files modified:
   trunk/libs/xpressive/proto/doc/evaluation.qbk | 258 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/xpressive/proto/doc/protodoc.xml | 6
   trunk/libs/xpressive/proto/doc/transforms.qbk | 17 ++
   3 files changed, 277 insertions(+), 4 deletions(-)

Modified: trunk/libs/xpressive/proto/doc/evaluation.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/evaluation.qbk (original)
+++ trunk/libs/xpressive/proto/doc/evaluation.qbk 2008-02-06 19:05:01 EST (Wed, 06 Feb 2008)
@@ -275,6 +275,84 @@
 _default_context_ uses Boost.Typeof to deduce the types of the expressions it
 evaluates.
 
+For example, consider the following "Hello World" example:
+
+ #include <iostream>
+ #include <boost/xpressive/proto/proto.hpp>
+ #include <boost/xpressive/proto/context.hpp>
+ #include <boost/typeof/std/ostream.hpp>
+ using namespace boost;
+
+ proto::terminal< std::ostream & >::type cout_ = { std::cout };
+
+ template< typename Expr >
+ void evaluate( Expr const & expr )
+ {
+ // Evaluate the expression with default_context,
+ // to give the operators their C++ meanings:
+ proto::default_context ctx;
+ proto::eval(expr, ctx);
+ }
+
+ int main()
+ {
+ evaluate( cout_ << "hello" << ',' << " world" );
+ return 0;
+ }
+
+This program outputs the following:
+
+[pre
+hello, world
+]
+
+_default_context_ is trivially defined in terms of a `default_eval<>`
+template, as follows:
+
+ // Definition of default_context
+ struct default_context
+ {
+ template<typename Expr>
+ struct eval
+ : default_eval<Expr, default_context const, typename Expr::proto_tag>
+ {};
+ };
+
+There are a bunch of `default_eval<>` specializations, each of which handles
+a different C++ operator. Here, for instance, is the specialization for binary
+addition:
+
+ // A default expression evaluator for binary addition
+ template<typename Expr, typename Context>
+ struct default_eval<Expr, Context, proto::tag::plus>
+ {
+ private:
+ static Expr & s_expr;
+ static Context & s_ctx;
+
+ public:
+ typedef
+ decltype(
+ proto::eval(proto::arg_c<0>(s_expr), s_ctx)
+ + proto::eval(proto::arg_c<1>(s_expr), s_ctx)
+ )
+ result_type;
+
+ result_type operator ()(Expr &expr, Context &ctx) const
+ {
+ return proto::eval(proto::arg_c<0>(expr), ctx)
+ + proto::eval(proto::arg_c<1>(expr), ctx);
+ }
+ };
+
+The above code uses `decltype` to calculate the return type of the function
+call operator. `decltype` is a new keyword in the next version of C++ that gets
+the type of any expression. Most compilers do not yet support `decltype`
+directly, so `default_eval<>` uses the Boost.Typeof library to emulate it. On
+some compilers, that may mean that `default_context` either doesn't work or
+that it requires you to register your types with the Boost.Typeof library.
+Check the documentation for Boost.Typeof to see.
+
 [endsect]
 
 [/===================================]
@@ -282,7 +360,66 @@
 [/===================================]
 
 The _null_context_ is a simple context that recursively evaluates children
-but does not combine the results in any way and returns void.
+but does not combine the results in any way and returns void. It is useful
+in conjunction with `callable_context<>`, or when defining your own contexts
+which mutate an expression tree in-place rather than accumulate a result, as
+we'll see below.
+
+_null_context_ is trivially implemented in terms of `null_eval<>` as follows:
+
+ // Definition of null_context
+ struct null_context
+ {
+ template<typename Expr>
+ struct eval
+ : null_eval<Expr, null_context const, Expr::proto_arity::value>
+ {};
+ };
+
+And `null_eval<>` is also trivially implemented. Here, for instance is
+a binary `null_eval<>`:
+
+ // Binary null_eval<>
+ template<typename Expr, typename Context>
+ struct null_eval<Expr, Context, 2>
+ {
+ typedef void result_type;
+
+ void operator()(Expr &expr, Context &ctx) const
+ {
+ proto::eval(proto::arg_c<0>(expr), ctx);
+ proto::eval(proto::arg_c<1>(expr), ctx);
+ }
+ };
+
+When would such classes be useful? Imagine you have an expression tree with
+integer terminals, and you would like to increment each integer in-place. You
+might define an evaluation context as follows:
+
+ struct increment_ints
+ {
+ // By default, just evaluate all children by defering
+ // to the null_eval<>
+ template<typename Expr, typename Arg = proto::result_of::arg<Expr>::type>
+ struct eval
+ : null_eval<Expr, increment_ints const>
+ {};
+
+ // Increment integer terminals
+ template<typename Expr>
+ struct eval<Expr, int>
+ {
+ typedef void result_type;
+
+ void operator()(Expr &expr, increment_ints const &) const
+ {
+ ++proto::arg(expr);
+ }
+ };
+ };
+
+In the next section on _callable_context_, we'll see an even simpler way to
+achieve the same thing.
 
 [endsect]
 
@@ -296,6 +433,125 @@
 expressions not handled by an overload are automatically dispatched to a
 default evaluation context that you can specify.
 
+Rather than an evaluation context in its own right, _callable_context_ is more
+properly thought of as a context adaptor. To use it, you must define your own
+context that inherits from _callable_context_.
+
+In the [link boost_proto.users_guide.expression_evaluation.canned_contexts.null_context [^null_context]]
+section, we saw how to implement an evaluation context that increments all the
+integers within an expression tree. Here is how to do the same thing with the
+_callable_context_:
+
+ // An evaluation context that increments all
+ // integer terminals in-place.
+ struct increment_ints
+ : callable_context<
+ increment_ints const // derived context
+ , null_context const // fall-back context
+ >
+ {
+ typedef void result_type;
+
+ // Handle int terminals here:
+ void operator()(proto::tag::terminal, int &i) const
+ {
+ ++i;
+ }
+ };
+
+With such a context, we can do the following:
+
+ literal<int> i = 0, j = 10;
+ proto::eval( i - j * 3.14, increment_ints() );
+
+ std::cout << "i = " << i.get() << std::endl;
+ std::cout << "j = " << j.get() << std::endl;
+
+This program outputs the following, which shows that the integers `i` and `j`
+have been incremented by `1`:
+
+[pre
+i = 1
+j = 11
+]
+
+In the `increment_ints` context, we didn't have to define any nested `eval<>`
+templates. That's because _callable_context_ implements them for us.
+_callable_context_ takes two template parameters: the derived context and a
+fall-back context. For each node in the expression tree being evaluated,
+_callable_context_ checks to see if there is an overloaded `operator()` in the
+derived context that accepts it. Given some expression `expr` of type `Expr`,
+and a context `ctx`, it attempts to call:
+
+ ctx(
+ typename Expr::proto_tag()
+ , proto::arg_c<0>(expr)
+ , proto::arg_c<1>(expr)
+ ...
+ );
+
+Using function overloading and metaprogramming tricks, _callable_context_ can
+detect at compile-time whether such a function exists or not. If so, that
+function is called. If not, the current expression is passed to the fall-back
+evaluation context to be processed.
+
+We saw another example of the _callable_context_ when we looked at the simple
+calculator expression evaluator. There, we wanted to customize the evaluation
+of placeholder terminals, and delegate the handling of all other nodes to the
+_default_context_. We did that as follows:
+
+ // An evaluation context for calculator expressions that
+ // explicitly handles placeholder terminals, but defers the
+ // processing of all other nodes to the default_context.
+ struct calculator_context
+ : proto::callable_context< calculator_context const >
+ {
+ calculator_context(double d1, double d2)
+ : d1_(d1), d2_(d2)
+ {}
+
+ // Define the result type of the calculator.
+ typedef double result_type;
+
+ // Handle the placeholders:
+ double operator()(proto::tag::terminal, placeholder1) const
+ {
+ return this->d1_;
+ }
+
+ double operator()(proto::tag::terminal, placeholder2) const
+ {
+ return this->d2_;
+ }
+
+ private:
+ double d1_, d2_;
+ };
+
+In this case, we didn't specify a fall-back context. In that case,
+_callable_context_ uses the _default_context_. With the above
+`calculator_context` and a couple of appropriately defined placeholder
+terminals, we can evaluate calculator expressions, as demonstrated
+below:
+
+ struct placeholder1 {};
+ struct placeholder2 {};
+ terminal<placeholder1>::type const _1 = {{}};
+ terminal<placeholder2>::type const _2 = {{}};
+ // ...
+
+ double j = proto::eval(
+ (_2 - _1) / _2 * 100
+ , calculator_context(4, 5)
+ );
+ std::cout << "j = " << j << std::endl;
+
+The above code displays the following:
+
+[pre
+j = 20
+]
+
 [endsect]
 
 [endsect]

Modified: trunk/libs/xpressive/proto/doc/protodoc.xml
==============================================================================
--- trunk/libs/xpressive/proto/doc/protodoc.xml (original)
+++ trunk/libs/xpressive/proto/doc/protodoc.xml 2008-02-06 19:05:01 EST (Wed, 06 Feb 2008)
@@ -243,7 +243,7 @@
         </template><parameter name="expr"><paramtype>proto::expr&lt; Tag, Args, 0 &gt; const &amp;</paramtype></parameter></method><method name="operator()" cv="const"><type>void</type><template>
           <template-type-parameter name="T"/>
         </template><parameter name="t"><paramtype>T const &amp;</paramtype></parameter><description><para>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </para></description></method></method-group><constructor><parameter name="depth"><paramtype>int</paramtype><default>0</default><description><para>The starting indentation depth for this node. Children nodes will be displayed at a starting depth of <computeroutput>depth+4</computeroutput>. </para></description></parameter><parameter name="sout"><paramtype>std::ostream &amp;</paramtype><default>std::cout</default><description><para>The <computeroutput>ostream</computeroutput> to which the expression tree will be written. </para></description></parameter><description><para>
-</para></description></constructor></struct></namespace><namespace name="tag"><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::posit</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::negate</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::dereference</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::complement</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::address_of</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_not</classname></paramtype></parameter></
function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::pre_inc</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::pre_dec</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::post_inc</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::post_dec</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_left</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_right</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><param
eter name=""><paramtype><classname>tag::multiplies</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::divides</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::modulus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::plus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::minus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::less</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::greater</classname></paramtype></parameter></f
unction><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::less_equal</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::greater_equal</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::equal_to</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::not_equal_to</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_or</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_and</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *<
/type><parameter name=""><paramtype><classname>tag::bitwise_and</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_or</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_xor</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::comma</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::mem_ptr</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_left_assign</cl
assname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_right_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::multiplies_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::divides_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::modulus_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::plus_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::minus_assign</classname></paramtype></parameter></fun
ction><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_and_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_or_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_xor_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::subscript</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::if_else_</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::function</classname></paramtype></parameter></function></namespace><overloaded-function name="
display_expr"><signature><type>void</type><template>
+</para></description></constructor><method-group name="private member functions"/><copy-assignment><parameter name=""><paramtype><classname>display_expr</classname> const &amp;</paramtype></parameter></copy-assignment></struct></namespace><namespace name="tag"><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::posit</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::negate</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::dereference</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::complement</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::address_of</classname></pa
ramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_not</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::pre_inc</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::pre_dec</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::post_inc</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::post_dec</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_left</classname></paramtype></parameter></function><function name="proto_tag_name"><type>cha
r const *</type><parameter name=""><paramtype><classname>tag::shift_right</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::multiplies</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::divides</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::modulus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::plus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::minus</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::less</classname><
/paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::greater</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::less_equal</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::greater_equal</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::equal_to</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::not_equal_to</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_or</classname></paramtype></parameter></function><function name="proto_tag_nam
e"><type>char const *</type><parameter name=""><paramtype><classname>tag::logical_and</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_and</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_or</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_xor</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::comma</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::mem_ptr</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname
>tag::assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_left_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::shift_right_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::multiplies_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::divides_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::modulus_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::plus_assign</classname></paramt
ype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::minus_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_and_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_or_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::bitwise_xor_assign</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::subscript</classname></paramtype></parameter></function><function name="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::if_else_</classname></paramtype></parameter></function><function name
="proto_tag_name"><type>char const *</type><parameter name=""><paramtype><classname>tag::function</classname></paramtype></parameter></function></namespace><overloaded-function name="display_expr"><signature><type>void</type><template>
           <template-type-parameter name="Expr"/>
         </template><parameter name="expr"><paramtype>Expr const &amp;</paramtype><description><para>The Proto expression tree to pretty-print </para></description></parameter><parameter name="sout"><paramtype>std::ostream &amp;</paramtype><description><para>The <computeroutput>ostream</computeroutput> to which the output should be written. </para></description></parameter></signature><signature><type>void</type><template>
           <template-type-parameter name="Expr"/>
@@ -298,7 +298,7 @@
       <template-type-parameter name="This"/>
       <template-type-parameter name="Expr"/>
       <template-type-parameter name="Context"/>
- </template><specialization><template-arg>This(Expr</template-arg><template-arg>Context)</template-arg></specialization><typedef name="type"><type><classname>proto::result_of::eval</classname>&lt; typename remove_reference&lt; Expr &gt;::type, typename remove_reference&lt; Context &gt;::type &gt;::type</type></typedef></struct-specialization><method-group name="public member functions"><method name="operator()" cv="const"><type><classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type><template>
+ </template><specialization><template-arg>This(Expr</template-arg><template-arg>Context)</template-arg></specialization><typedef name="type"><type><classname>proto::result_of::eval</classname>&lt; typename remove_reference&lt; Expr &gt;::type, typename remove_reference&lt; Context &gt;::type &gt;::type</type></typedef></struct-specialization><typedef name="proto_is_callable_"><type>void</type></typedef><method-group name="public member functions"><method name="operator()" cv="const"><type><classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type><template>
           <template-type-parameter name="Expr"/>
           <template-type-parameter name="Context"/>
         </template><parameter name="expr"><paramtype>Expr &amp;</paramtype></parameter><parameter name="context"><paramtype>Context &amp;</paramtype></parameter><purpose>Evaluate a given Proto expression with a given context. </purpose><description><para>
@@ -775,7 +775,7 @@
 </para></description><returns><para>Generator::make(deep_copy(expr)) </para></returns></method></method-group></struct></namespace></namespace></namespace></header><header name="boost/xpressive/proto/literal.hpp"><para>The literal&lt;&gt; terminal wrapper, and the proto::lit() function for creating literal&lt;&gt; wrappers. </para><namespace name="boost"><namespace name="proto"><namespace name="utility"><struct name="literal"><template>
       <template-type-parameter name="T"/>
       <template-type-parameter name="Domain"/>
- </template><purpose>A simple wrapper for a terminal, provided for ease of use. </purpose><description><para>A simple wrapper for a terminal, provided for ease of use. In all cases, <computeroutput>literal&lt;X&gt; l(x);</computeroutput> is equivalent to <computeroutput>terminal&lt;X&gt;type l = {x};</computeroutput>.</para><para>The <computeroutput>Domain</computeroutput> template parameter defaults to <computeroutput>proto::default_domain</computeroutput>. </para></description><method-group name="public member functions"/><constructor><template>
+ </template><purpose>A simple wrapper for a terminal, provided for ease of use. </purpose><description><para>A simple wrapper for a terminal, provided for ease of use. In all cases, <computeroutput>literal&lt;X&gt; l(x);</computeroutput> is equivalent to <computeroutput>terminal&lt;X&gt;type l = {x};</computeroutput>.</para><para>The <computeroutput>Domain</computeroutput> template parameter defaults to <computeroutput>proto::default_domain</computeroutput>. </para></description><typedef name="value_type"><type><classname>proto::result_of::arg</classname>&lt; terminal_type &gt;::type</type></typedef><typedef name="reference"><type><classname>proto::result_of::arg</classname>&lt; terminal_type &gt;::reference</type></typedef><typedef name="const_reference"><type><classname>proto::result_of::arg</classname>&lt; terminal_type &gt;::const_reference</type></typedef><method-group name="public member functions"><method name="get" cv=""><type>reference</type></method><method name="get" cv="const"><type>const_ref
erence</type></method></method-group><constructor><template>
           <template-type-parameter name="U"/>
         </template><parameter name="u"><paramtype>U &amp;</paramtype></parameter></constructor><constructor><template>
           <template-type-parameter name="U"/>

Modified: trunk/libs/xpressive/proto/doc/transforms.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/transforms.qbk (original)
+++ trunk/libs/xpressive/proto/doc/transforms.qbk 2008-02-06 19:05:01 EST (Wed, 06 Feb 2008)
@@ -628,6 +628,23 @@
>
     {};
 
+The above transform serves to illustrate the behaviors of the _and_,
+_or_, and _not_ transforms, but it is admittedly contrived. The
+transform is more easily written as follows:
+
+ // Functionally identical to the UnwrapReference
+ // transform above:
+ struct UnwrapReference
+ : or_<
+ when<
+ terminal<reference_wrapper<_> >
+ , terminal<unwrap_reference<_arg> >(_arg)
+ >
+ , terminal<_>
+ , nary_expr<_, vararg<UnwrapReference> >
+ >
+ {};
+
 [endsect]
 
 [section:call [^call<>]]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk