$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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< Tag, Args, 0 > const &</paramtype></parameter></method><method name="operator()" cv="const"><type>void</type><template>
           <template-type-parameter name="T"/>
         </template><parameter name="t"><paramtype>T const &</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 &</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 &</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 &</paramtype><description><para>The Proto expression tree to pretty-print </para></description></parameter><parameter name="sout"><paramtype>std::ostream &</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>< typename remove_reference< Expr >::type, typename remove_reference< Context >::type >::type</type></typedef></struct-specialization><method-group name="public member functions"><method name="operator()" cv="const"><type><classname>proto::result_of::eval</classname>< Expr, Context >::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>< typename remove_reference< Expr >::type, typename remove_reference< Context >::type >::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>< Expr, Context >::type</type><template>
           <template-type-parameter name="Expr"/>
           <template-type-parameter name="Context"/>
         </template><parameter name="expr"><paramtype>Expr &</paramtype></parameter><parameter name="context"><paramtype>Context &</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<> terminal wrapper, and the proto::lit() function for creating literal<> 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<X> l(x);</computeroutput> is equivalent to <computeroutput>terminal<X>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<X> l(x);</computeroutput> is equivalent to <computeroutput>terminal<X>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>< terminal_type >::type</type></typedef><typedef name="reference"><type><classname>proto::result_of::arg</classname>< terminal_type >::reference</type></typedef><typedef name="const_reference"><type><classname>proto::result_of::arg</classname>< terminal_type >::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 &</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<>]]