Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2008-08-10 12:07:21


Author: eric_niebler
Date: 2008-08-10 12:07:20 EDT (Sun, 10 Aug 2008)
New Revision: 48060
URL: http://svn.boost.org/trac/boost/changeset/48060

Log:
more doc improvements
Text files modified:
   branches/proto/v4/libs/proto/doc/construction.qbk | 288 +++++++++++++++++++++++----------------
   branches/proto/v4/libs/proto/doc/evaluation.qbk | 10
   branches/proto/v4/libs/proto/doc/glossary.qbk | 7
   branches/proto/v4/libs/proto/doc/transforms.qbk | 77 ++++++----
   4 files changed, 229 insertions(+), 153 deletions(-)

Modified: branches/proto/v4/libs/proto/doc/construction.qbk
==============================================================================
--- branches/proto/v4/libs/proto/doc/construction.qbk (original)
+++ branches/proto/v4/libs/proto/doc/construction.qbk 2008-08-10 12:07:20 EDT (Sun, 10 Aug 2008)
@@ -35,9 +35,10 @@
 The _expr_ template makes up the nodes in expression trees. The first template
 parameter is the node type; in this case, `proto::tag::terminal`. That means
 that `_1` is a leaf-node in the expression tree. The second template parameter
-is a list of child types. Terminals will always have only one type in the
-type list. The last parameter is the arity of the expression. Terminals have
-arity 0, unary expressions have arity 1, etc.
+is a list of child types, or in the case of terminals, the type of the terminal's
+value. Terminals will always have only one type in the type list. The last
+parameter is the arity of the expression. Terminals have arity 0, unary
+expressions have arity 1, etc.
 
 The _expr_ struct is defined as follows:
 
@@ -47,7 +48,8 @@
     template< typename Tag, typename Args >
     struct expr< Tag, Args, 1 >
     {
- typename Args::child0 child0;
+ typedef typename Args::child0 proto_child0;
+ proto_child0 child0;
         // ...
     };
 
@@ -65,21 +67,12 @@
 
 Once we have some Proto terminals, expressions involving those terminals build
 expression trees for us. Proto defines overloads for each of C++'s overloadable
-operators in the `boost::proto` namespace. As long
-as one operand is a Proto expression, the result of the operation is a tree
-node representing that operation.[footnote There are a couple of exceptions to
-this rule. In ["`int x; x = _1`], the assignment isn't a Proto expression, even
-though the right hand operand /is/ a Proto expression. That is because in C++,
-the assignment operator must be a member function.
-The same is also true for the subscript operator and the function call
-operator, as in ["`int *x; x[_1];`] and ["`std::sin(_1);`]. C++ also has special
-rules for overloads of `operator->` that make it useless for
-building expression templates, so Proto does not overload it. It does, however,
-overload `operator->*`.]
+operators in the `boost::proto` namespace. As long as one operand is a Proto
+expression, the result of the operation is a tree node representing that operation.
 
 [note The _expr_ struct lives in the `boost::proto` namespace, as do all of
-Proto's operator overloads. The overloads are found via ADL (Argument-Dependent
-Lookup). That is why expressions must be "tainted" with Proto-ness for Proto to
+Proto's operator overloads. The overloads are found via ADL (argument-dependent
+lookup). That is why expressions must be "tainted" with Proto-ness for Proto to
 be able to build trees out of expressions.]
 
 As a result of Proto's operator overloads, we can say:
@@ -87,15 +80,74 @@
     -_1; // OK, build a unary-negate tree node
     _1 + 42; // OK, build a binary-plus tree node
 
+[/=========================================================]
+[heading Assignment, Subscript, and Function Call Operators]
+[/=========================================================]
+
+The _expr_ type defines overloads of `operator=`, `operator[]`, and `operator()`
+as member functions. That's because these operators cannot be overloaded at
+namespace scope. Because _expr_ defines them as member functions, the following
+are valid Proto expressions:
+
+ _1 = 5; // OK, builds a binary assign tree node
+ _1[6]; // OK, builds a binary subscript tree node
+ _1(); // OK, builds a unary function tree node
+ _1(7); // OK, builds a binary function tree node
+ _1(8,9); // OK, builds a ternary function tree node
+ // ... etc.
+
+For the first two lines, assigment and subscript, it should be fairly unsurprising
+that the resulting expression node should be binary. After all, there are
+two operands in each expression. It may be surprising at first that what appears
+to be a function call with no arguments, `_1()`, actually creates an expression
+node with one child. The child is `_1` itself. Likewise, the expression `_1(7)`
+has two children: `_1` and `2`.
+
+Because these operators can only be defined as member functions of _expr_, the
+following expressions are invalid:
+
+ int i;
+ i = _1; // ERROR: cannot assign _1 to an int
+
+ int *p;
+ p[_1]; // ERROR: cannot use _1 as an index
+
+ std::sin(_1); // ERROR: cannot call std::sin() with _1
+
+Also, C++ has special rules for overloads of `operator->` that make it useless
+for building expression templates, so Proto does not overload it.
+
+[/==============================]
+[heading The Address-Of Operator]
+[/==============================]
+
+Proto overloads the address-of operator for expression types, so that the
+following code creates a new unary address-of tree node:
+
+ &_1; // OK, creates a unary address-of tree node
+
+It does /not/ return the address of the `_1` object. However, there is
+special code in Proto such that a unary address-of node is implicitly
+convertible to a pointer to its child. In other words, the following
+code works and does what you might expect, but not in the obvious way:
+
+ typedef
+ proto::terminal< placeholder1 >::type
+ placeholder1_type;
+
+ placeholder1_type const _1 = {{}};
+ placeholder1_type const * p = &_1; // OK, &_1 implicitly converted
+
 [/================================]
 [heading Building Expression Trees]
 [/================================]
 
-The `_1` node is an _expr_ type, and new nodes created with this type are
-also _expr_ types. To use Proto effectively, you won't have to bother yourself with the
-actual types that Proto generates. These are details, but you're likely to
-encounter these types in compiler error messages, so it's helpful to be familiar
-with them. The types look like this:
+The `_1` node is an instantiation of _expr_, and expressions containing
+`_1` are also instantiations of _expr_. To use Proto effectively, you
+won't have to bother yourself with the actual types that Proto generates.
+These are details, but you're likely to encounter these types in compiler
+error messages, so it's helpful to be familiar with them. The types look
+like this:
 
     // The type of the expression -_1
     typedef
@@ -336,7 +388,7 @@
 can treat it as a flat sequence of terminals, however, using Proto's _flatten_
 function. _flatten_ returns a view which makes a tree appear as a flat Fusion
 sequence. If the top-most node has a tag type `T`, then the elements of the
-flattened sequence are the child nodes that do *not* have tag type `T`. This
+flattened sequence are the child nodes that do /not/ have tag type `T`. This
 process is evaluated recursively. So the above can correctly be written as:
 
     proto::terminal<int>::type const _1 = {1};
@@ -361,196 +413,196 @@
 
 [endsect]
 
-[/===============================================================]
-[section:tags_and_meta_functions Operator Tags and Meta-Functions]
-[/===============================================================]
+[/=============================================================]
+[section:tags_and_metafunctions Operator Tags and Metafunctions]
+[/=============================================================]
 
 The following table lists the overloadable C++ operators, the Proto tag types
-for each, and the name of the Proto meta-function for generating the
-corresponding Proto expression nodes. The meta-functions are also usable as
+for each, and the name of the Proto metafunction for generating the
+corresponding Proto expression types. The metafunctions are also usable as
 grammars for matching such nodes, as well as pass-through transforms, as
 explained in later sections.
 
-[table Operators, Tags and Meta-Functions
+[table Operators, Tags and Metafunctions
     [[Operator]
     [Proto Tag]
- [Proto Meta-Function]]
+ [Proto Metafunction]]
 
     [[unary `+`]
- [`tag::unary_plus`]
- [`unary_plus<>`]]
+ [`proto::tag::unary_plus`]
+ [`proto::unary_plus<>`]]
 
     [[unary `-`]
- [`tag::negate`]
- [`negate<>`]]
+ [`proto::tag::negate`]
+ [`proto::negate<>`]]
 
     [[unary `*`]
- [`tag::dereference`]
- [`dereference<>`]]
+ [`proto::tag::dereference`]
+ [`proto::dereference<>`]]
 
     [[unary `~`]
- [`tag::complement`]
- [`complement<>`]]
+ [`proto::tag::complement`]
+ [`proto::complement<>`]]
 
     [[unary `&`]
- [`tag::address_of`]
- [`address_of<>`]]
+ [`proto::tag::address_of`]
+ [`proto::address_of<>`]]
 
     [[unary `!`]
- [`tag::logical_not`]
- [`logical_not<>`]]
+ [`proto::tag::logical_not`]
+ [`proto::logical_not<>`]]
 
     [[unary prefix `++`]
- [`tag::pre_inc`]
- [`pre_inc<>`]]
+ [`proto::tag::pre_inc`]
+ [`proto::pre_inc<>`]]
 
     [[unary prefix `--`]
- [`tag::pre_dec`]
- [`pre_dec<>`]]
+ [`proto::tag::pre_dec`]
+ [`proto::pre_dec<>`]]
 
     [[unary postfix `++`]
- [`tag::post_inc`]
- [`post_inc<>`]]
+ [`proto::tag::post_inc`]
+ [`proto::post_inc<>`]]
 
     [[unary postfix `--`]
- [`tag::post_dec`]
- [`post_dec<>`]]
+ [`proto::tag::post_dec`]
+ [`proto::post_dec<>`]]
 
     [[binary `<<`]
- [`tag::shift_left`]
- [`shift_left<>`]]
+ [`proto::tag::shift_left`]
+ [`proto::shift_left<>`]]
 
     [[binary `>>`]
- [`tag::shift_right`]
- [`shift_right<>`]]
+ [`proto::tag::shift_right`]
+ [`proto::shift_right<>`]]
 
     [[binary `*`]
- [`tag::multiplies`]
- [`multiplies<>`]]
+ [`proto::tag::multiplies`]
+ [`proto::multiplies<>`]]
 
     [[binary `/`]
- [`tag::divides`]
- [`divides<>`]]
+ [`proto::tag::divides`]
+ [`proto::divides<>`]]
 
     [[binary `%`]
- [`tag::modulus`]
- [`modulus<>`]]
+ [`proto::tag::modulus`]
+ [`proto::modulus<>`]]
 
     [[binary `+`]
- [`tag::plus`]
- [`plus<>`]]
+ [`proto::tag::plus`]
+ [`proto::plus<>`]]
 
     [[binary `-`]
- [`tag::minus`]
- [`minus<>`]]
+ [`proto::tag::minus`]
+ [`proto::minus<>`]]
 
     [[binary `<`]
- [`tag::less`]
- [`less<>`]]
+ [`proto::tag::less`]
+ [`proto::less<>`]]
 
     [[binary `>`]
- [`tag::greater`]
- [`greater<>`]]
+ [`proto::tag::greater`]
+ [`proto::greater<>`]]
 
     [[binary `<=`]
- [`tag::less_equal`]
- [`less_equal<>`]]
+ [`proto::tag::less_equal`]
+ [`proto::less_equal<>`]]
 
     [[binary `>=`]
- [`tag::greater_equal`]
- [`greater_equal<>`]]
+ [`proto::tag::greater_equal`]
+ [`proto::greater_equal<>`]]
 
     [[binary `==`]
- [`tag::equal_to`]
- [`equal_to<>`]]
+ [`proto::tag::equal_to`]
+ [`proto::equal_to<>`]]
 
     [[binary `!=`]
- [`tag::not_equal_to`]
- [`not_equal_to<>`]]
+ [`proto::tag::not_equal_to`]
+ [`proto::not_equal_to<>`]]
 
     [[binary `||`]
- [`tag::logical_or`]
- [`logical_or<>`]]
+ [`proto::tag::logical_or`]
+ [`proto::logical_or<>`]]
 
     [[binary `&&`]
- [`tag::logical_and`]
- [`logical_and<>`]]
+ [`proto::tag::logical_and`]
+ [`proto::logical_and<>`]]
 
     [[binary `&`]
- [`tag::bitwise_and`]
- [`bitwise_and<>`]]
+ [`proto::tag::bitwise_and`]
+ [`proto::bitwise_and<>`]]
 
     [[binary `|`]
- [`tag::bitwise_or`]
- [`bitwise_or<>`]]
+ [`proto::tag::bitwise_or`]
+ [`proto::bitwise_or<>`]]
 
     [[binary `^`]
- [`tag::bitwise_xor`]
- [`bitwise_xor<>`]]
+ [`proto::tag::bitwise_xor`]
+ [`proto::bitwise_xor<>`]]
 
     [[binary `,`]
- [`tag::comma`]
- [`comma<>`]]
+ [`proto::tag::comma`]
+ [`proto::comma<>`]]
 
     [[binary `->*`]
- [`tag::mem_ptr`]
- [`mem_ptr<>`]]
+ [`proto::tag::mem_ptr`]
+ [`proto::mem_ptr<>`]]
 
     [[binary `=`]
- [`tag::assign`]
- [`assign<>`]]
+ [`proto::tag::assign`]
+ [`proto::assign<>`]]
 
     [[binary `<<=`]
- [`tag::shift_left_assign`]
- [`shift_left_assign<>`]]
+ [`proto::tag::shift_left_assign`]
+ [`proto::shift_left_assign<>`]]
 
     [[binary `>>=`]
- [`tag::shift_right_assign`]
- [`shift_right_assign<>`]]
+ [`proto::tag::shift_right_assign`]
+ [`proto::shift_right_assign<>`]]
 
     [[binary `*=`]
- [`tag::multiplies_assign`]
- [`multiplies_assign<>`]]
+ [`proto::tag::multiplies_assign`]
+ [`proto::multiplies_assign<>`]]
 
     [[binary `/=`]
- [`tag::divides_assign`]
- [`divides_assign<>`]]
+ [`proto::tag::divides_assign`]
+ [`proto::divides_assign<>`]]
 
     [[binary `%=`]
- [`tag::modulus_assign`]
- [`modulus_assign<>`]]
+ [`proto::tag::modulus_assign`]
+ [`proto::modulus_assign<>`]]
 
     [[binary `+=`]
- [`tag::plus_assign`]
- [`plus_assign<>`]]
+ [`proto::tag::plus_assign`]
+ [`proto::plus_assign<>`]]
 
     [[binary `-=`]
- [`tag::minus_assign`]
- [`minus_assign<>`]]
+ [`proto::tag::minus_assign`]
+ [`proto::minus_assign<>`]]
 
     [[binary `&=`]
- [`tag::bitwise_and_assign`]
- [`bitwise_and_assign<>`]]
+ [`proto::tag::bitwise_and_assign`]
+ [`proto::bitwise_and_assign<>`]]
 
     [[binary `|=`]
- [`tag::bitwise_or_assign`]
- [`bitwise_or_assign<>`]]
+ [`proto::tag::bitwise_or_assign`]
+ [`proto::bitwise_or_assign<>`]]
 
     [[binary `^=`]
- [`tag::bitwise_xor_assign`]
- [`bitwise_xor_assign<>`]]
+ [`proto::tag::bitwise_xor_assign`]
+ [`proto::bitwise_xor_assign<>`]]
 
     [[binary subscript]
- [`tag::subscript`]
- [`subscript<>`]]
+ [`proto::tag::subscript`]
+ [`proto::subscript<>`]]
 
     [[ternary `?:`]
- [`tag::if_else_`]
- [`if_else_<>`]]
+ [`proto::tag::if_else_`]
+ [`proto::if_else_<>`]]
 
     [[n-ary function call]
- [`tag::function`]
- [`function<>`]]
+ [`proto::tag::function`]
+ [`proto::function<>`]]
 ]
 
 [endsect]

Modified: branches/proto/v4/libs/proto/doc/evaluation.qbk
==============================================================================
--- branches/proto/v4/libs/proto/doc/evaluation.qbk (original)
+++ branches/proto/v4/libs/proto/doc/evaluation.qbk 2008-08-10 12:07:20 EDT (Sun, 10 Aug 2008)
@@ -5,7 +5,7 @@
  / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  /]
 
-[section:expression_evaluation Expression Evaluation: Imparting Behaviors Within A Context]
+[section:expression_evaluation Expression Evaluation: Imparting Behaviors With A Context]
 
 Once you have constructed a Proto expression tree, either by using Proto's
 operator overloads or with _make_expr_ and friends, you probably want to
@@ -124,7 +124,7 @@
         // A nested eval<> class template
         template<
             typename Expr
- , typename Tag = typename Expr::proto_tag
+ , typename Tag = typename tag_of<Expr>::type
>
         struct eval;
 
@@ -320,7 +320,11 @@
     {
         template<typename Expr>
         struct eval
- : default_eval<Expr, default_context const, typename Expr::proto_tag>
+ : default_eval<
+ Expr
+ , default_context const
+ , typename tag_of<Expr>::type
+ >
         {};
     };
 

Modified: branches/proto/v4/libs/proto/doc/glossary.qbk
==============================================================================
--- branches/proto/v4/libs/proto/doc/glossary.qbk (original)
+++ branches/proto/v4/libs/proto/doc/glossary.qbk 2008-08-10 12:07:20 EDT (Sun, 10 Aug 2008)
@@ -18,13 +18,18 @@
        `R` is treated as a polymorphic function object and the
        arguments are treated as transforms that yield the
        arguments to the function object.] ]
+ [ [domain-specific language]
+ [A programming language that targets a particular problem
+ space by providing programming idioms, abstractions and
+ constructs that match the constructs within that problem
+ space.]]
   [ [expression]
       [A heterogeneous tree where each node is either an
        instantiation of `boost::proto::expr<>` or some type
        that is an extension (via `boost::proto::extends<>`
        or `BOOST_PROTO_EXTENDS()`) of such an instantiation.]]
   [ [grammar]
- [A grammar is a type that describes a subset of all
+ [A grammar is a type that describes a subset of
        expression types. Expressions in a domain must conform
        to that domain's grammar. The `proto::matches<>`
        metafunction evaluates whether an expression type matches

Modified: branches/proto/v4/libs/proto/doc/transforms.qbk
==============================================================================
--- branches/proto/v4/libs/proto/doc/transforms.qbk (original)
+++ branches/proto/v4/libs/proto/doc/transforms.qbk 2008-08-10 12:07:20 EDT (Sun, 10 Aug 2008)
@@ -256,7 +256,7 @@
     [note You may have noticed that Proto types like `unary_expr<>` serve several
     different but related roles. In particular, `unary_expr<>` is ...
 
- ... [*a meta-function]: `unary_expr<T, X>::type` is a typedef for
+ ... [*a metafunction]: `unary_expr<T, X>::type` is a typedef for
     `expr<T, list1<X> >`.
 
     ... [*a grammar]: `unary_expr<U, Y>` is a simle grammar that matches
@@ -1218,7 +1218,7 @@
 As a side-effect, `pass_through<>` transforms all sub-expressions held by
 reference into ones held by value.
 
-Note that all expression generator meta-functions (Eg., `unary_plus<>`,
+Note that all expression generator metafunctions (Eg., `unary_plus<>`,
 `shift_right<>`, `function<>`, `nary_expr<>`, etc.) have a pass-through
 transform by default, so there is rarely any need to use the `pass_through<>`
 transform explicitly.
@@ -1353,22 +1353,24 @@
 [section:is_callable Making Your Transform Callable]
 [/=================================================]
 
-Transforms are typically of the form `when< Something, R(A0,A1,...) >`. The
+Transforms are typically of the form `proto::when< Something, R(A0,A1,...) >`. The
 question is whether `R` represents a function to call or an object to
-construct, and the answer determines how `when<>` evaluates the transform.
-`when<>` uses the `is_callable<>` trait to disambiguate between the two.
+construct, and the answer determines how _when_ evaluates the transform.
+_when_ uses the `proto::is_callable<>` trait to disambiguate between the two.
 Proto does its best to guess whether a transform is callable or not, but
 it doesn't always get it right. It's best to know the rules Proto uses,
-so that you know when you need to specialize `is_callable<>`.
+so that you know when you need to be more explicit.
 
-The first thing to know is that templates are not considered callable
-by default. This is true ['even if the template inherits from
-`proto::callable`]. Consider the following erroneous callable transform:
+For most types `T`, `proto::is_callable<T>` checks for inheritence from
+`proto::callable`. However, if the type `T` is a template specialization,
+Proto assumes that it is /not/ callable ['even if the template inherits from
+`proto::callable`]. We'll see why in a minute. Consider the following erroneous
+callable transform:
 
     // Proto can't tell this defines a
     // callable transform!
     template<typename T>
- struct times2 : callable
+ struct times2 : proto::callable
     {
         typedef T result_type;
 
@@ -1381,11 +1383,14 @@
     // ERROR! This is not going to
     // multiply the int by 2.
     struct IntTimes2
- : when< terminal<int>, times2<int>(_value) >
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
     {};
 
 The problem is that Proto doesn't know that `times2<int>` is a callable
-transform. Instead, it assumes it's an object transform and will try to
+transform. Instead, it assumes it is an object transform and will try to
 construct a `times2<int>` object and initialize it will an `int`. That
 will not compile.
 
@@ -1393,20 +1398,21 @@
 it inherits from `proto::callable`, and that is detectable, right?
 The problem is that merely asking whether some type `X<Y>` inherits from
 `callable` will cause the template `X<Y>` to be instantiated. That's a
-problem for a type like `std::vector<_value(_child1)>()`, which is a valid
-(object) transform that default-constructs a particular instantiation of
-`std::vector<>`. But `std::vector<>` will not suffer to be instantiated
-with `_value(_child1)` as a template parameter! As a result, Proto has
-to assume that a type `X<Y>` represents an object transform and not
-a callable transform.]
+problem for a type like `std::vector<_value(_child1)>`. `std::vector<>`
+will not suffer to be instantiated with `_value(_child1)` as a template
+parameter. As a result, Proto has to assume that a type `X<Y>` represents
+an object transform and not a callable transform.]
 
 There are a couple of solutions to the `times2<int>` problem. One
-solution is to wrap the transform in `call<>`. This forces Proto to
-treat `times2<int>` as callable:
+solution is to wrap the transform in `proto::call<>`. This forces Proto
+to treat `times2<int>` as callable:
 
     // OK, calls times2<int>
     struct IntTimes2
- : when< terminal<int>, call<times2<int>(_value)> >
+ : proto::when<
+ proto::terminal<int>
+ , proto::call<times2<int>(proto::_value)>
+ >
     {};
 
 This can be a bit of a pain, because we need to wrap every use of
@@ -1426,21 +1432,27 @@
 
     // OK, times2<> is callable
     struct IntTimes2
- : when< terminal<int>, times2<int>(_value) >
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
     {};
 
 This is better, but still a pain because of the need to open
 Proto's namespace.
 
 You could simply make sure that the transform is not
-a template. Consider the following:
+a template specialization. Consider the following:
 
- // No longer a template!
+ // No longer a template specialization!
     struct times2int : times2<int> {};
 
     // OK, times2int is callable
     struct IntTimes2
- : when< terminal<int>, times2int(_value) >
+ : proto::when<
+ proto::terminal<int>
+ , times2int(proto::_value)
+ >
     {};
 
 This works because now Proto can tell that `times2int` inherits
@@ -1453,8 +1465,8 @@
 to `proto::callable`:
 
     // Proto will recognize this as callable
- template<typename T, typename Dummy = proto::callable>
- struct times2 : callable
+ template<typename T, typename Callable = proto::callable>
+ struct times2 : proto::callable
     {
         typedef T result_type;
 
@@ -1466,13 +1478,16 @@
 
     // OK, this works!
     struct IntTimes2
- : when< terminal<int>, times2<int>(_value) >
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
     {};
 
 Note that in addition to the extra template parameter, `times2<>`
-still inherits from `callable`. That's not necessary in this example
-but it's good style because any types derived from `times2<>` (as
-`times2int` defined above) will still be considered callable.
+still inherits from `proto::callable`. That's not necessary in this
+example but it's good style because any types derived from `times2<>`
+(as `times2int` defined above) will still be considered callable.
 
 [endsect]
 


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