Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2008-08-29 22:38:08


Author: eric_niebler
Date: 2008-08-29 22:38:07 EDT (Fri, 29 Aug 2008)
New Revision: 48468
URL: http://svn.boost.org/trac/boost/changeset/48468

Log:
latest doc tweaks
Text files modified:
   trunk/libs/proto/doc/proto.qbk | 154 +++++++++++++++++++++++--------
   trunk/libs/proto/doc/rationale.qbk | 96 +++++---------------
   trunk/libs/proto/doc/transforms.qbk | 191 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/proto/test/examples.cpp | 25 ++--
   4 files changed, 340 insertions(+), 126 deletions(-)

Modified: trunk/libs/proto/doc/proto.qbk
==============================================================================
--- trunk/libs/proto/doc/proto.qbk (original)
+++ trunk/libs/proto/doc/proto.qbk 2008-08-29 22:38:07 EDT (Fri, 29 Aug 2008)
@@ -35,46 +35,120 @@
 
 [/ Links ]
 
-[def _PETE_ [@http://www.codesourcery.com/pooma/download.html PETE]]
-[def _spirit_fx_ [@http://spirit.sourceforge.net Spirit Parser Framework]]
-[def _spirit_ [@http://spirit.sourceforge.net Spirit]]
-[def _xpressive_ [@../../libs/xpressive/index.html Boost.Xpressive]]
-[def _typeof_ [@../../libs/typeof/index.html Boost.Typeof]]
-[def _expr_ [classref boost::proto::expr<Tag,Args,1> `expr<>`]]
-[def _deep_copy_ [funcref boost::proto::deep_copy `deep_copy()`]]
-[def _extends_ [classref boost::proto::extends `extends<>`]]
-[def _as_expr_ [funcref boost::proto::as_expr `as_expr()`]]
-[def _as_child_ [funcref boost::proto::as_child `as_child()`]]
-[def _make_expr_ [funcref boost::proto::make_expr `make_expr()`]]
-[def _unpack_expr_ [funcref boost::proto::unpack_expr `unpack_expr()`]]
-[def _matches_ [classref boost::proto::result_of::matches `matches<>`]]
-[def _or_ [classref boost::proto::control::or_ `or_<>`]]
-[def _and_ [classref boost::proto::control::and_ `and_<>`]]
-[def _if_ [classref boost::proto::control::if_ `if_<>`]]
-[def _not_ [classref boost::proto::control::not_ `not_<>`]]
-[def _exact_ [classref boost::proto::control::exact `exact<>`]]
-[def _convertible_to_ [classref boost::proto::control::convertible_to `convertible_to<>`]]
-[def _is_expr_ [classref boost::proto::result_of::is_expr `is_expr<>`]]
-[def _tag_of_ [classref boost::proto::result_of::tag_of `tag_of<>`]]
-[def _child_ [funcref boost::proto::child `child()`]]
-[def _child_c_ [funcref boost::proto::child_c `child_c()`]]
-[def _eval_ [funcref boost::proto::eval `eval()`]]
-[def _left_ [funcref boost::proto::left `left()`]]
-[def _right_ [funcref boost::proto::right `right()`]]
-[def _value_ [funcref boost::proto::value `value()`]]
-[def _terminal_ [classref boost::proto::op::terminal `terminal<>`]]
-[def _unary_expr_ [classref boost::proto::op::unary_expr `unary_expr<>`]]
-[def _binary_expr_ [classref boost::proto::op::binary_expr `binary_expr<>`]]
-[def _literal_ [classref boost::proto::utility::literal `literal<>`]]
-[def _lit_ [funcref boost::proto::lit `lit()`]]
-[def _vararg_ [classref boost::proto::control::vararg `vararg<>`]]
-[def _default_context_ [classref boost::proto::context::default_context `default_context`]]
-[def _callable_context_ [classref boost::proto::context::callable_context `callable_context<>`]]
-[def _null_context_ [classref boost::proto::context::null_context `null_context<>`]]
-[def _when_ [classref boost::proto::when `when<>`]]
-[def _call_ [classref boost::proto::call `call<>`]]
-[def _make_ [classref boost::proto::make `make<>`]]
-[def _flatten_ [funcref boost::proto::flatten `flatten()`]]
+[def _PETE_
+ [@http://www.codesourcery.com/pooma/download.html PETE]]
+[def _spirit_fx_
+ [@http://spirit.sourceforge.net Spirit Parser Framework]]
+[def _spirit_
+ [@http://spirit.sourceforge.net Spirit]]
+[def _xpressive_
+ [@../../libs/xpressive/index.html Boost.Xpressive]]
+[def _typeof_
+ [@../../libs/typeof/index.html Boost.Typeof]]
+[def _expr_
+ [classref boost::proto::expr<Tag,Args,1> `proto::expr<>`]]
+[def _deep_copy_
+ [funcref boost::proto::deep_copy `proto::deep_copy()`]]
+[def _extends_
+ [classref boost::proto::extends `proto::extends<>`]]
+[def _as_expr_
+ [funcref boost::proto::as_expr `proto::as_expr()`]]
+[def _as_child_
+ [funcref boost::proto::as_child `proto::as_child()`]]
+[def _make_expr_
+ [funcref boost::proto::make_expr `proto::make_expr()`]]
+[def _unpack_expr_
+ [funcref boost::proto::unpack_expr `proto::unpack_expr()`]]
+[def _matches_
+ [classref boost::proto::result_of::matches `proto::matches<>`]]
+[def _or_
+ [classref boost::proto::control::or_ `proto::or_<>`]]
+[def _and_
+ [classref boost::proto::control::and_ `proto::and_<>`]]
+[def _if_
+ [classref boost::proto::control::if_ `proto::if_<>`]]
+[def _not_
+ [classref boost::proto::control::not_ `proto::not_<>`]]
+[def _exact_
+ [classref boost::proto::control::exact `proto::exact<>`]]
+[def _convertible_to_
+ [classref boost::proto::control::convertible_to `proto::convertible_to<>`]]
+[def _is_expr_
+ [classref boost::proto::result_of::is_expr `proto::is_expr<>`]]
+[def _tag_of_
+ [classref boost::proto::result_of::tag_of `proto::tag_of<>`]]
+[def _child_
+ [funcref boost::proto::child `proto::child()`]]
+[def _child_c_
+ [funcref boost::proto::child_c `proto::child_c()`]]
+[def _eval_
+ [funcref boost::proto::eval `proto::eval()`]]
+[def _left_
+ [funcref boost::proto::left `proto::left()`]]
+[def _right_
+ [funcref boost::proto::right `proto::right()`]]
+[def _value_
+ [funcref boost::proto::value `proto::value()`]]
+[def _terminal_
+ [classref boost::proto::op::terminal `proto::terminal<>`]]
+[def _unary_expr_
+ [classref boost::proto::op::unary_expr `proto::unary_expr<>`]]
+[def _binary_expr_
+ [classref boost::proto::op::binary_expr `proto::binary_expr<>`]]
+[def _literal_
+ [classref boost::proto::utility::literal `proto::literal<>`]]
+[def _lit_
+ [funcref boost::proto::lit `proto::lit()`]]
+[def _vararg_
+ [classref boost::proto::control::vararg `proto::vararg<>`]]
+[def _default_context_
+ [classref boost::proto::context::default_context `proto::default_context`]]
+[def _callable_context_
+ [classref boost::proto::context::callable_context `proto::callable_context<>`]]
+[def _null_context_
+ [classref boost::proto::context::null_context `proto::null_context<>`]]
+[def _when_
+ [classref boost::proto::when `proto::when<>`]]
+[def _call_
+ [classref boost::proto::call `proto::call<>`]]
+[def _make_
+ [classref boost::proto::make `proto::make<>`]]
+[def _flatten_
+ [funcref boost::proto::flatten `proto::flatten()`]]
+[def _value_pt_
+ [classref boost::proto::_value [^proto::_value]]]
+[def _child_c_pt_
+ [classref boost::proto::_child_c [^proto::_child_c<>]]]
+[def _child_pt_
+ [classref boost::proto::_child [^proto::_child]]]
+[def _left_pt_
+ [classref boost::proto::_left [^proto::_left]]]
+[def _right_pt_
+ [classref boost::proto::_right [^proto::_right]]]
+[def _wild_pt_
+ [classref boost::proto::_ [^proto::_]]]
+[def _expr_pt_
+ [classref boost::proto::_expr [^proto::_expr]]]
+[def _state_pt_
+ [classref boost::proto::_state [^proto::_state]]]
+[def _data_pt_
+ [classref boost::proto::_data [^proto::_data]]]
+[def _call_pt_
+ [classref boost::proto::call [^proto::call<>]]]
+[def _make_pt_
+ [classref boost::proto::make [^proto::make<>]]]
+[def _default_pt_
+ [classref boost::proto::_default [^proto::_default<>]]]
+[def _fold_pt_
+ [classref boost::proto::fold [^proto::fold<>]]]
+[def _fold_tree_pt_
+ [classref boost::proto::fold_tree [^proto::fold_tree<>]]]
+[def _reverse_fold_pt_
+ [classref boost::proto::reverse_fold [^proto::reverse_fold<>]]]
+[def _reverse_fold_tree_pt_
+ [classref boost::proto::reverse_fold_tree [^proto::reverse_fold_tree<>]]]
+[def _lazy_pt_
+ [classref boost::proto::lazy [^proto::lazy<>]]]
 
 [include preface.qbk]
 

Modified: trunk/libs/proto/doc/rationale.qbk
==============================================================================
--- trunk/libs/proto/doc/rationale.qbk (original)
+++ trunk/libs/proto/doc/rationale.qbk 2008-08-29 22:38:07 EDT (Fri, 29 Aug 2008)
@@ -11,64 +11,17 @@
 [section:static_initialization Static Initialization]
 [/==================================================]
 
-Proto expression types are PODs (Plain Old Data), and do not have constructors.
-They are brace-initialized, as follows:
+Proto expression types are PODs (Plain Old Data), and do not have constructors. They are brace-initialized, as follows:
 
     terminal<int>::type const _i = {1};
 
-The reason is so that expression objects like `_i` above can be ['statically
-initialized]. Why is static initialization important? The terminals of many
-domain-specific embedded languages are likely to be global const objects, like
-`_1` and `_2` from the Boost Lambda Library. Were these object to require
-run-time initialization, it might be possible to use these objects before they
-are initialized. That would be bad. Statically initialized objects cannot be
-misused that way.
-
-[endsect]
-
-[/======================================================================]
-[section:result_of Proto Transforms and the Restricted ResultOf Protocol]
-[/======================================================================]
-
-All Proto primitive transforms make use of a variant of the TR1 ResultOf
-protocol for computing the type of the transform's return value. Such
-transforms must have a nested `result<>` template (not a nested `result_type`
-typedef) which takes exactly three parameter types. That is, it must be
-defined as:
-
- template<typename Sig> struct result {};
-
- template<typename This, typename Expr, typename State, typename Data>
- struct result<This(Expr, State, Data)>
- {
- typedef ... type;
- };
-
-In the above, `Expr`, `State`, and `Data` are assumed by Proto to be
-non-cv-qualified non-reference types. The implication is that for some
-Proto transform `Tr`, some `result_of<>` instantiations work while others
-don't. See below.
-
- // ERROR, doesn't work:
- boost::result_of<Tr(Expr const &, State const &, Data &)>::type
-
- // OK, works:
- boost::result_of<Tr(Expr, State, Data)>::type
-
-It is done this way largely for compile-time performance. Full
-compliance with the TR1 ResultOf protocol incurs a not insignificant penalty
-at compile time. Metaprogramming tricks are needed to first detect a nested
-`result_type` typedef if it exists. And each nested `result<>` template
-would need to be coded specially to handle references and cv-qualifiers, which
-incurs many instantiations of `remove_reference<>` and `remove_cv<>`. In
-private testing, this was found to have a measurable impact on compile-time
-performance in the order of 10-15%, which was deemed unacceptable.
-
-The restricted protocol improves compile times while remaining largely
-compatible with TR1's `result_of<>`. As a side benefit, it makes
-Proto's primitive transforms easier to implement, since the user need not
-worry about stripping references and cv-qualification in their nested
-`result<>` templates.
+The reason is so that expression objects like `_i` above can be ['statically
+initialized]. Why is static initialization important? The terminals of many domain-
+specific embedded languages are likely to be global const objects, like `_1` and
+`_2` from the Boost Lambda Library. Were these object to require run-time
+initialization, it might be possible to use these objects before they are
+initialized. That would be bad. Statically initialized objects cannot be misused
+that way.
 
 [endsect]
 
@@ -76,23 +29,22 @@
 [section:preprocessor Why Not Reuse MPL, Fusion, et cetera?]
 [/=========================================================]
 
-Anyone who has peeked at Proto's source code has probably wondered,
-"Why all the dirty preprocessor gunk? Couldn't this have been all
-implemented cleanly on top of libraries like MPL and Fusion?" The
-answer is that Proto could have been implemented this way, and in fact
-was at one point. The problem is that template metaprogramming (TMP)
-makes for very long compile times. As a foundation upon which other
-TMP-heavy libraries will be built, Proto itself should be as lightweight
-as possible. That is achieved by prefering preprocessor metaprogramming
-to template metaprogramming. Expanding a macro is far more efficient
-than instantiating a template. In some cases, the "clean" version takes
-10x longer to compile than the "dirty" version.
-
-The "clean and slow" version of Proto can still be found at
-http://svn.boost.org/svn/boost/branches/proto/v3. Anyone who is interested
-can download it and verify that it is, in fact, unusably slow to compile.
-Note that this branch's development was abandoned, and it does not
-conform exactly with Proto's current interface.
+Anyone who has peeked at Proto's source code has probably wondered, "Why all the
+dirty preprocessor gunk? Couldn't this have been all implemented cleanly on top of
+libraries like MPL and Fusion?" The answer is that Proto could have been
+implemented this way, and in fact was at one point. The problem is that template
+metaprogramming (TMP) makes for longer compile times. As a foundation upon which
+other TMP-heavy libraries will be built, Proto itself should be as lightweight as
+possible. That is achieved by prefering preprocessor metaprogramming to template
+metaprogramming. Expanding a macro is far more efficient than instantiating a
+template. In some cases, the "clean" version takes 10x longer to compile than the
+"dirty" version.
+
+The "clean and slow" version of Proto can still be found at
+http://svn.boost.org/svn/boost/branches/proto/v3. Anyone who is interested can
+download it and verify that it is, in fact, unusably slow to compile. Note that
+this branch's development was abandoned, and it does not conform exactly with
+Proto's current interface.
 
 [endsect]
 

Modified: trunk/libs/proto/doc/transforms.qbk
==============================================================================
--- trunk/libs/proto/doc/transforms.qbk (original)
+++ trunk/libs/proto/doc/transforms.qbk 2008-08-29 22:38:07 EDT (Fri, 29 Aug 2008)
@@ -418,7 +418,173 @@
 [section:data Passing Auxiliary Data To Transforms]
 [/================================================]
 
-TODO
+In the last section, we saw that we can pass a second parameter to grammars with transforms: an accumulation variable or /state/ that gets updated as your transform executes. There are times when your transforms will need to access auxiliary data that does /not/ accumulate, so bundling it with the state parameter is impractical. Instead, you can pass auxiliary data as a third parameter, known as the /data/ parameter. Below we show an example involving string processing where the data parameter is essential.
+
+[note All Proto grammars are function objects that take one, two or three arguments: the expression, the state, and the data. There are no additional arguments to know about, we promise. In Haskell, there is set of a tree traversal technologies known collectively as "Scrap Your Boilerplate". In that framework, there are also three parameters: the tree, the accumulation, and the context. These are Proto's expression, state and data parameters under different names.]
+
+Expression templates are often used as an optimization to eliminate temporary objects. Condsier the problem of string concatenation: a series of concatenations would result in the needless creation of temporary strings. We can use Proto to make string concatenation very efficient. To make the problem more interesting, we can apply a locale-sensitive transformation to each character during the concatenation. The locale information will be passed as the data parameter.
+
+Consider the following expression template:
+
+ proto::lit("hello") + " " + "world";
+
+We would like to concatenate this string into a statically allocated wide buffer, widening each charater in turn using the current locale. The first step is to write a grammar that describes this expression, with transforms that calculate the total string length. Here it is:
+
+ // A grammar that matches string concatenation expressions, and
+ // a transform that calculates the total string length.
+ struct StringLength
+ : proto::or_<
+ proto::when<
+ // When you find a character array ...
+ proto::terminal<char[proto::N]>
+ // ... the length is the size of the array minus 1.
+ , mpl::prior<mpl::sizeof_<proto::_value> >()
+ >
+ , proto::when<
+ // The length of a concatenated string is ...
+ proto::plus<StringLength, StringLength>
+ // ... the sum of the lengths of each sub-string.
+ , proto::fold<
+ _
+ , mpl::size_t<0>()
+ , mpl::plus<StringLength, proto::_state>()
+ >
+ >
+ >
+ {};
+
+Notice the use of _fold_pt_. It is a primitive transform that takes a sequence, a state, and function, just like `std::accumulate()`. The three template parameters are transforms. The first yields the sequence of expressions over which to fold, the second yields the initial state of the fold, and the third is the function to apply at each iteration. The use of `proto::_` as the first parameter might have you confused. In addition to being Proto's wildcard, `proto::_` is also a primitive transform that returns the current expression, which (if it is a non-terminal) is a sequence of its child expressions.
+
+Next, we need a function object that accepts a narrow string, a wide buffer, and a `std::ctype<>` facet for doing the locale-specific stuff. It's fairly straightforward.
+
+ // A function object that writes a narrow string
+ // into a wide buffer.
+ struct WidenCopy : proto::callable
+ {
+ typedef wchar_t *result_type;
+
+ wchar_t *
+ operator()(char const *str, wchar_t *buf, std::ctype<char> const &ct) const
+ {
+ for(; *str; ++str, ++buf)
+ *buf = ct.widen(*str);
+ return buf;
+ }
+ };
+
+Finally, we need some transforms that actually walk the concatenated string expression, widens the characters and writes them to a buffer. We will pass a `wchar_t*` as the state parameter and update it as we go. We'll also pass the `std::ctype<>` facet as the data parameter. It looks like this:
+
+ // Write concatenated strings into a buffer, widening
+ // them as we go.
+ struct StringCopy
+ : proto::or_<
+ proto::when<
+ proto::terminal<char[proto::N]>
+ , WidenCopy(proto::_value, proto::_state, proto::_data)
+ >
+ , proto::when<
+ proto::plus<StringCopy, StringCopy>
+ , StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+ >
+ >
+ {};
+
+Let's look more closely at the transform associated with non-terminals:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+
+This bears a resemblance to the transform in the previous section that folded an expression tree into a list. First we recurse on the left child, writing its strings into the `wchar_t*` passed in as the state parameter. That returns the new value of the `wchar_t*`, which is passed as state while transforming the right child. Both invocations receive the same `std::ctype<>`, which is passed in as the data parameter.
+
+With these pieces in our pocket, we can implement our concatenate-and-widen function as follows:
+
+ template<typename Expr>
+ void widen( Expr const &expr )
+ {
+ // Make sure the expression conforms to our grammar
+ BOOST_MPL_ASSERT(( proto::matches<Expr, StringLength> ));
+
+ // Calculate the length of the string and allocate a buffer statically
+ static std::size_t const length =
+ boost::result_of<StringLength(Expr)>::type::value;
+ wchar_t buffer[ length + 1 ] = {L'\0'};
+
+ // Get the current ctype facet
+ std::locale loc;
+ std::ctype<char> const &ct(std::use_facet<std::ctype<char> >(loc));
+
+ // Concatenate and widen the string expression
+ StringCopy()(expr, &buffer[0], ct);
+
+ // Write out the buffer.
+ std::wcout << buffer << std::endl;
+ }
+
+ int main()
+ {
+ widen( proto::lit("hello") + " " + "world" );
+ }
+
+The above code displays:
+
+[pre
+hello world
+]
+
+This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and (unlike the state parameter) Proto will never mess with it.
+
+[heading Implicit Parameters to Primitive Transforms]
+
+Let's use the above example to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals above:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+
+Here we specify all three parameters to both invocations of the `StringCopy` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been writen more simply as:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left)
+ )
+
+The same is true for any primitive transform. The following are all equivalent:
+
+[table Implicit Parameters to Primitive Transforms
+ [[Equivalent Transforms]]
+ [[`proto::when<_, StringCopy>`]]
+ [[`proto::when<_, StringCopy(_)>`]]
+ [[`proto::when<_, StringCopy(_, proto::_state)>`]]
+ [[`proto::when<_, StringCopy(_, proto::_state, proto::_data)>`]]
+]
+
+[note *Grammars Are Primitive Transforms Are Function Objects*
+
+So far, we've said that all Proto grammars are function objects. But it's more accurate to say that Proto grammars are primitive transforms -- a special kind of function object that takes between 1 and 3 arguments, and that Proto knows to treat specially when used in a callable transform, as in the table above.]
+
+[note *Not All Function Objects Are Primitive Transforms*
+
+You might be tempted now to drop the `_state` and `_data` parameters to `WidenCopy(proto::_value, proto::_state, proto::_data)`. That would be an error. `WidenCopy` is just a plain function object, not a primimtive transform, so you must specify all its arguments. We'll see later how to write your own primitive transforms.]
+
+Once you know that primitive transforms will always receive all three parameters -- expression, state, and data -- it makes things possible that wouldn't be otherwise. For instance, consider that for binary expressions, these two transforms are equivalent. Can you see why?
+
+[table Two Equivalent Transforms
+ [[Without [^proto::fold<>]][With [^proto::fold<>]]]
+ [[``StringCopy(
+ proto::_right
+ , StringCopy(proto::_left)
+)``
+][``proto::fold<_, proto::_state, StringCopy>``]]
+]
 
 [endsect]
 
@@ -426,7 +592,28 @@
 [section:built_in Proto's Built-In Transforms]
 [/===========================================]
 
-TODO
+Primitive transforms are the building blocks for more interesting composite transforms. Proto defines a bunch of generally useful primitive transforms. The following table summarizes them.
+
+[table Built-In Primitive Transforms
+ [[Primitive Transform] [Description]]
+ [[_value_pt_] [Blah]]
+ [[_child_c_pt_] [Blah]]
+ [[_child_pt_] [Blah]]
+ [[_left_pt_] [Blah]]
+ [[_right_pt_] [Blah]]
+ [[_wild_pt_] [Blah]]
+ [[_expr_pt_] [Blah]]
+ [[_state_pt_] [Blah]]
+ [[_data_pt_] [Blah]]
+ [[_call_pt_] [Blah]]
+ [[_make_pt_] [Blah]]
+ [[_default_pt_] [Blah]]
+ [[_fold_pt_] [Blah]]
+ [[_reverse_fold_pt_] [Blah]]
+ [[_fold_tree_pt_] [Blah]]
+ [[_reverse_fold_tree_pt_] [Blah]]
+ [[_lazy_pt_] [Blah]]
+]
 
 [endsect]
 

Modified: trunk/libs/proto/test/examples.cpp
==============================================================================
--- trunk/libs/proto/test/examples.cpp (original)
+++ trunk/libs/proto/test/examples.cpp 2008-08-29 22:38:07 EDT (Fri, 29 Aug 2008)
@@ -26,8 +26,9 @@
 namespace fusion = boost::fusion;
 using proto::_;
 
-struct placeholder1 {};
-struct placeholder2 {};
+template<int I>
+struct placeholder
+{};
 
 namespace test1
 {
@@ -38,10 +39,10 @@
     /*<< A Calculator expression is ... >>*/
     struct CalcArity
       : proto::or_<
- /*<< placeholder1, or ... >>*/
- proto::terminal< placeholder1 >
- /*<< placeholder2, or ... >>*/
- , proto::terminal< placeholder2 >
+ /*<< _1, or ... >>*/
+ proto::terminal< placeholder<0> >
+ /*<< _2, or ... >>*/
+ , proto::terminal< placeholder<1> >
           /*<< some other terminal, or ... >>*/
           , proto::terminal< _ >
           /*<< a unary expression where the operand is a calculator expression, or ... >>*/
@@ -130,14 +131,14 @@
 };
 //]
 
-proto::terminal< placeholder1 >::type const _1 = {{}};
-proto::terminal< placeholder2 >::type const _2 = {{}};
+proto::terminal< placeholder<0> >::type const _1 = {{}};
+proto::terminal< placeholder<1> >::type const _2 = {{}};
 
 //[ CalculatorArityGrammar
 struct CalculatorArity
   : proto::or_<
- proto::when< proto::terminal< placeholder1 >, mpl::int_<1>() >
- , proto::when< proto::terminal< placeholder2 >, mpl::int_<2>() >
+ proto::when< proto::terminal< placeholder<0> >, mpl::int_<1>() >
+ , proto::when< proto::terminal< placeholder<1> >, mpl::int_<2>() >
       , proto::when< proto::terminal<_>, mpl::int_<0>() >
       , proto::when< proto::unary_expr<_, _>, unary_arity >
       , proto::when< proto::binary_expr<_, _, _>, binary_arity >
@@ -148,10 +149,10 @@
 //[ CalcArity
 struct CalcArity
   : proto::or_<
- proto::when< proto::terminal< placeholder1 >,
+ proto::when< proto::terminal< placeholder<0> >,
             mpl::int_<1>()
>
- , proto::when< proto::terminal< placeholder2 >,
+ , proto::when< proto::terminal< placeholder<1> >,
             mpl::int_<2>()
>
       , proto::when< proto::terminal<_>,


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