Most compilers have front ends and back ends. The front end parses the text
of an input program into some intermediate form like an abstract syntax tree,
and the back end takes the intermediate form and generates an executable from
it.

A library built with Proto is essentially a compiler for a domain-specific
embedded language (DSEL). It also has a front end, an intermediate form, and
a back end. The front end is comprised of the symbols (a.k.a., terminals),
members, operators and functions that make up the user-visible aspects of the
DSEL. The back end is made of evaluation contexts and transforms that give
meaning and behavior to the expression templates generated by the front end.
In between is the intermediate form: the expression template itself, which
is an abstract syntax tree in a very real sense.

To build a library with Proto, you will first decide what your interface will
be; that is, you'll design a programming language for your domain and build
the front end with tools provided by Proto. Then you'll design the back end
by writing evaluation contexts and/or transforms that accept expression templates
and do interesting things with them.

This users' guide is organized as follows. After a Getting
Started guide, we'll cover the tools Proto provides for defining and
manipulating the three major parts of a compiler:

Proto is a header-only template library, which means you don't need to
alter your build scripts or link to any separate lib file to use it. All
you need to do is #include<boost/proto/proto.hpp>. Or, you might decide to just include
the core of Proto (#include<boost/proto/core.hpp>) and whichever contexts and transforms
you happen to use.

All of Proto's functions are defined in the boost::proto
namespace. For example, there is a function called value() defined in boost::proto
that accepts a terminal expression and returns the terminal's value.

Proto defines metafunctions that correspond to each
of Proto's free functions. The metafunctions are used to compute the functions'
return types. All of Proto's metafunctions live in the boost::proto::result_of
namespace and have the same name as the functions to which they correspond.
For instance, there is a class template boost::proto::result_of::value<> that you can use to compute the
return type of the boost::proto::value() function.

Proto defines function object equivalents of all of
its free functions. (A function object is an instance of a class type that
defines an operator()
member function.) All of Proto's function object types are defined in the
boost::proto::functional namespace and have the same
name as their corresponding free functions. For example, boost::proto::functional::value is a class that defines a function
object that does the same thing as the boost::proto::value() free function.

Proto also defines primitive transforms -- class types
that can be used to compose larger transforms for manipulating expression
trees. Many of Proto's free functions have corresponding primitive transforms.
These live in the boost::proto
namespace and their names have a leading underscore. For instance, the
transform corresponding to the value() function is called boost::proto::_value.

This program builds an object representing the output operation and passes
it to an evaluate()
function, which then executes it.

The basic idea of expression templates is to overload all the operators
so that, rather than evaluating the expression immediately, they build
a tree-like representation of the expression so that it can be evaluated
later. For each operator in an expression, at least one operand must be
Protofied in order for Proto's operator overloads to be found. In the expression
...

cout_<<"hello"<<','<<" world"

... the Protofied sub-expression is cout_,
which is the Proto-ification of std::cout.
The presence of cout_ "infects"
the expression, and brings Proto's tree-building operator overloads into
consideration. Any literals in the expression are then Protofied by wrapping
them in a Proto terminal before they are combined into larger Proto expressions.

Once Proto's operator overloads have built the expression tree, the expression
can be lazily evaluated later by walking the tree. That is what proto::eval()
does. It is a general tree-walking expression evaluator, whose behavior
is customizable via a context parameter. The use of
proto::default_context
assigns the standard meanings to the operators in the expression. (By using
a different context, you could give the operators in your expressions different
semantics. By default, Proto makes no assumptions about what operators
actually mean.)

Before we continue, let's use the above example to illustrate an important
design principle of Proto's. The expression template created in the hello
world example is totally general and abstract. It is not tied
in any way to any particular domain or application, nor does it have any
particular meaning or behavior on its own, until it is evaluated in a
context. Expression templates are really just heterogeneous
trees, which might mean something in one domain, and something else entirely
in a different one.

As we'll see later, there is a way to create Proto expression trees that
are not purely abstract, and that have meaning and
behaviors independent of any context. There is also a way to control which
operators are overloaded for your particular domain. But that is not the
default behavior. We'll see later why the default is often a good thing.

"Hello, world" is nice, but it doesn't get you very far. Let's
use Proto to build a DSEL (domain-specific embedded language) for a lazily-evaluated
calculator. We'll see how to define the terminals in your mini-language,
how to compose them into larger expressions, and how to define an evaluation
context so that your expressions can do useful work. When we're done, we'll
have a mini-language that will allow us to declare a lazily-evaluated arithmetic
expression, such as (_2-_1)/_2*100,
where _1 and _2 are placeholders for values to be
passed in when the expression is evaluated.

The initialization may look a little odd at first, but there is a good
reason for doing things this way. The objects _1
and _2 above do not require
run-time construction -- they are statically initialized,
which means they are essentially initialized at compile time. See the
Static
Initialization section in the Rationale
appendix for more information.

Now that we have terminals, we can use Proto's operator overloads to combine
these terminals into larger expressions. So, for instance, we can immediately
say things like:

// This builds an expression template
(_2-_1)/_2*100;

This creates an expression tree with a node for each operator. The type
of the resulting object is large and complex, but we are not terribly interested
in it right now.

So far, the object is just a tree representing the expression. It has no
behavior. In particular, it is not yet a calculator. Below we'll see how
to make it a calculator by defining an evaluation context.

No doubt you want your expression templates to actually do
something. One approach is to define an evaluation context.
The context is like a function object that associates behaviors with the
node types in your expression tree. The following example should make it
clear. It is explained below.

structcalculator_context:proto::callable_context<calculator_contextconst>{// Values to replace the placeholders
std::vector<double>args;// Define the result type of the calculator.
// (This makes the calculator_context "callable".)
typedefdoubleresult_type;// Handle the placeholders:
template<intI>doubleoperator()(proto::tag::terminal,placeholder<I>)const{returnthis->args[I];}};

In calculator_context,
we specify how Proto should evaluate the placeholder terminals by defining
the appropriate overloads of the function call operator. For any other
nodes in the expression tree (e.g., arithmetic operations or non-placeholder
terminals), Proto will evaluate the expression in the "default"
way. For example, a binary plus node is evaluated by first evaluating the
left and right operands and adding the results. Proto's default evaluator
uses the Boost.Typeof
library to compute return types.

Now that we have an evaluation context for our calculator, we can use it
to evaluate our arithmetic expressions, as below:

calculator_contextctx;ctx.args.push_back(45);// the value of _1 is 45
ctx.args.push_back(50);// the value of _2 is 50
// Create an arithmetic expression and immediately evaluate it
doubled=proto::eval((_2-_1)/_2*100,ctx);// This prints "10"
std::cout<<d<<std::endl;

Later, we'll see how to define more interesting evaluation contexts and
expression transforms that give you total control over how your expressions
are evaluated.

Our calculator DSEL is already pretty useful, and for many DSEL scenarios,
no more would be needed. But let's keep going. Imagine how much nicer it
would be if all calculator expressions overloaded operator() so that they could be used as function
objects. We can do that by creating a calculator domain
and telling Proto that all expressions in the calculator domain have extra
members. Here is how to define a calculator domain:

// Forward-declare an expression wrapper
template<typenameExpr>structcalculator;// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
structcalculator_domain:proto::domain<proto::generator<calculator>>{};

The calculator<>
type will be an expression wrapper. It will behave just like the expression
that it wraps, but it will have extra member functions that we will define.
The calculator_domain is
what informs Proto about our wrapper. It is used below in the definition
of calculator<>.
Read on for a description.

// Define a calculator expression wrapper. It behaves just like
// the expression it wraps, but with an extra operator() member
// function that evaluates the expression.
template<typenameExpr>structcalculator:proto::extends<Expr,calculator<Expr>,calculator_domain>{typedefproto::extends<Expr,calculator<Expr>,calculator_domain>base_type;calculator(Exprconst&expr=Expr()):base_type(expr){}typedefdoubleresult_type;// Overload operator() to invoke proto::eval() with
// our calculator_context.
doubleoperator()(doublea1=0,doublea2=0)const{calculator_contextctx;ctx.args.push_back(a1);ctx.args.push_back(a2);returnproto::eval(*this,ctx);}};

The calculator<>
struct is an expression extension. It uses proto::extends<>
to effectively add additional members to an expression type. When composing
larger expressions from smaller ones, Proto notes what domain the smaller
expressions are in. The larger expression is in the same domain and is
automatically wrapped in the domain's extension wrapper.

All that remains to be done is to put our placeholders in the calculator
domain. We do that by wrapping them in our calculator<> wrapper, as below:

Any larger expression that contain these placeholders will automatically
be wrapped in the calculator<> wrapper and have our operator()
overload. That means we can use them as function objects as follows.

Since calculator expressions are now valid function objects, we can use
them with standard algorithms, as shown below:

doublea1[4]={56,84,37,69};doublea2[4]={65,120,60,70};doublea3[4]={0};// Use std::transform() and a calculator expression
// to calculate percentages given two input sequences:
std::transform(a1,a1+4,a2,a3,(_2-_1)/_2*100);

Now, let's use the calculator example to explore some other useful features
of Proto.

You may have noticed that you didn't have to define an overloaded operator-()
or operator/()
-- Proto defined them for you. In fact, Proto overloads all
the operators for you, even though they may not mean anything in your domain-specific
language. That means it may be possible to create expressions that are
invalid in your domain. You can detect invalid expressions with Proto by
defining the grammar of your domain-specific language.

For simplicity, assume that our calculator DSEL should only allow addition,
subtraction, multiplication and division. Any expression involving any
other operator is invalid. Using Proto, we can state this requirement by
defining the grammar of the calculator DSEL. It looks as follows:

You can read the above grammar as follows: an expression tree conforms
to the calculator grammar if it is a binary plus, minus, multiplies or
divides node, where both child nodes also conform to the calculator grammar;
or if it is a terminal. In a Proto grammar, proto::_ is a wildcard that matches
any type, so proto::terminal<proto::_>
matches any terminal, whether it is a placeholder or a literal.

Note

This grammar is actually a little looser than we would like. Only placeholders
and literals that are convertible to doubles are valid terminals. Later
on we'll see how to express things like that in Proto grammars.

Once you have defined the grammar of your DSEL, you can use the proto::matches<> metafunction to check
whether a given expression type conforms to the grammar. For instance,
we might add the following to our calculator::operator() overload:

template<typenameExpr>structcalculator:proto::extends</* ... as before ... */>{/* ... */doubleoperator()(doublea1=0,doublea2=0)const{// Check here that the expression we are about to
// evaluate actually conforms to the calculator grammar.
BOOST_MPL_ASSERT((proto::matches<Expr,calculator_grammar>));/* ... */}};

The addition of the BOOST_MPL_ASSERT() line enforces at compile time that we
only evaluate expressions that conform to the calculator DSEL's grammar.
With Proto grammars, proto::matches<> and BOOST_MPL_ASSERT() it is very easy to give the users of
your DSEL short and readable compile-time errors when they accidentally
misuse your DSEL.

Note

BOOST_MPL_ASSERT()
is part of the Boost Metaprogramming Library. To use it, just #include<boost/mpl/assert.hpp>.

Grammars and proto::matches<>
make it possible to detect when a user has created an invalid expression
and issue a compile-time error. But what if you want to prevent users from
creating invalid expressions in the first place? By using grammars and
domains together, you can disable any of Proto's operator overloads that
would create an invalid expression. It is as simple as specifying the DSEL's
grammar when you define the domain, as shown below:

// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
// NEW: Any operator overloads that would create an
// expression that does not conform to the
// calculator grammar is automatically disabled.
structcalculator_domain:proto::domain<proto::generator<calculator>,calculator_grammar>{};

The only thing we changed is we added calculator_grammar
as the second template parameter to the proto::domain<> template when defining calculator_domain. With this simple addition,
we disable any of Proto's operator overloads that would create an invalid
calculator expression.

Hopefully, this gives you an idea of what sorts of things Proto can do
for you. But this only scratches the surface. The rest of this users' guide
will describe all these features and others in more detail.

Here is the fun part: designing your own mini-programming language. In this
section we'll talk about the nuts and bolts of designing a DSEL interface
using Proto. We'll cover the definition of terminals and lazy functions that
the users of your DSEL will get to program with. We'll also talk about Proto's
expression template-building operator overloads, and about ways to add additional
members to expressions within your domain.

With some terminals and Proto's operator overloads, you can immediately
start creating expression templates.

Defining terminals -- with aggregate initialization -- can be a little
awkward at times. Proto provides an easier-to-use wrapper for literals
that can be used to construct Protofied terminal expressions. It's called
proto::literal<>.

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.

Note

Proto's operator overloads live in the boost::proto
namespace and 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.

Proto also overloads operator=, operator[], and operator(), but these operators are member functions
of the expression template rather than free functions in Proto's namespace.
The following are valid Proto expressions:

For the first two lines, assignment 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 7.

Because these operators can only be defined as member functions, the following
expressions are invalid:

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:

If we limited ourselves to nothing but terminals and operator overloads,
our domain-specific embedded languages wouldn't be very expressive. Imagine
that we wanted to extend our calculator DSEL with a full suite of math
functions like sin()
and pow()
that we could invoke lazily as follows.

// A calculator expression that takes one argument
// and takes the sine of it.
sin(_1);

We would like the above to create an expression template representing a
function invocation. When that expression is evaluated, it should cause
the function to be invoked. (At least, that's the meaning of function invocation
we'd like the calculator DSEL to have.) You can define sin
quite simply as follows.

In the above, we define sin
as a Proto terminal containing a pointer to the std::sin() function. Now we can use sin as a lazy function. The default_context that we saw in the Introduction
knows how to evaluate lazy functions. Consider the following:

It is important to note that there is nothing special about terminals that
contain function pointers. Any Proto expression has
an overloaded function call operator. Consider:

// This compiles!
proto::lit(1)(2)(3,4)(5,6,7,8);

That may look strange at first. It creates an integer terminal with proto::lit(), and then invokes it like
a function again and again. What does it mean? To be sure, the default_context wouldn't know what to
do with it. The default_context
only knows how to evaluate expressions that are sufficiently C++-like.
In the case of function call expressions, the left hand side must evaluate
to something that can be invoked: a pointer to a function, a reference
to a function, or a TR1-style function object. That doesn't stop you from
defining your own evaluation context that gives that expression a meaning.
But more on that later.

Now, what if we wanted to add a pow() function to our calculator DSEL that
users could invoke as follows?

// A calculator expression that takes one argument
// and raises it to the 2nd power
pow<2>(_1);

The simple technique described above of making pow
a terminal containing a function pointer doesn't work here. If pow is an object, then the expression
pow<2>(_1) is
not valid C++. pow needs
to be a real function template. But it must be an unusual function; it
must return an expression template.

Before we can write the pow() function, we need a function object that
wraps an invocation of std::pow().

Now, let's try to define a function template that returns an expression
template. We'll use the proto::function<>
metafunction to calculate the type of a Proto expression that represents
a function call. It is analogous to proto::terminal<>.
(We'll see a couple of different ways to solve this problem, and each will
demonstrate another utility for defining Proto front-ends.)

// Define a lazy pow() function for the calculator DSEL.
// Can be used as: pow< 2 >(_1)
template<intExp,typenameArg>typenameproto::function<typenameproto::terminal<pow_fun<Exp>>::type,Argconst&>::typeconstpow(Argconst&arg){typedeftypenameproto::function<typenameproto::terminal<pow_fun<Exp>>::type,Argconst&>::typeresult_type;result_typeresult={{{}},arg};returnresult;}

In the code above, notice how the proto::function<>
and proto::terminal<> metafunctions are used
to calculate the return type: pow() returns an expression template representing
a function call where the first child is the function to call and the second
is the argument to the function. (Unfortunately, the same type calculation
is repeated in the body of the function so that we can initialize a local
variable of the correct type. We'll see in a moment how to avoid that.)

Note

As with proto::function<>, there are metafunctions
corresponding to all of the overloadable C++ operators for calculating
expression types.

With the above definition of the pow() function, we can create calculator expressions
like the one below and evaluate them using the calculator_context
we implemented in the Introduction.

// Initialize a calculator context
calculator_contextctx;ctx.args.push_back(3);// let _1 be 3
// Create a calculator expression that takes one argument,
// adds one to it, and raises it to the 2nd power; and then
// immediately evaluate it using the calculator_context.
assert(16==proto::eval(pow<2>(_1+1),ctx));

Above, we defined a pow() function template that returns an expression
template representing a lazy function invocation. But if we tried to call
it as below, we'll run into a problem.

// ERROR: pow() as defined above doesn't work when
// called with a non-Proto argument.
pow<2>(4);

Proto expressions can only have other Proto expressions as children. But
if we look at pow()'s
function signature, we can see that if we pass it a non-Proto object, it
will try to make it a child.

template<intExp,typenameArg>typenameproto::function<typenameproto::terminal<pow_fun<Exp>>::type,Argconst&// <=== ERROR! This may not be a Proto type!
>::typeconstpow(Argconst&arg)

What we want is a way to make Arg
into a Proto terminal if it is not a Proto expression already, and leave
it alone if it is. For that, we can use proto::as_child().
The following implementation of the pow() function handles all argument types,
expression templates or otherwise.

// Define a lazy pow() function for the calculator DSEL. Use
// proto::as_child() to Protofy the argument, but only if it
// is not a Proto expression type to begin with!
template<intExp,typenameArg>typenameproto::function<typenameproto::terminal<pow_fun<Exp>>::type,typenameproto::result_of::as_child<Argconst>::type>::typeconstpow(Argconst&arg){typedeftypenameproto::function<typenameproto::terminal<pow_fun<Exp>>::type,typenameproto::result_of::as_child<Argconst>::type>::typeresult_type;result_typeresult={{{}},proto::as_child(arg)};returnresult;}

Notice how we use the proto::result_of::as_child<> metafunction to calculate the return
type, and the proto::as_child()
function to actually normalize the argument.

The versions of the pow() function we've seen above are rather
verbose. In the return type calculation, you have to be very explicit about
wrapping non-Proto types. Worse, you have to restate the return type calculation
in the body of pow()
itself. Proto provides a helper for building expression templates directly
that handles these mundane details for you. It's called proto::make_expr().
We can redefine pow()
with it as below.

There are some things to notice about the above code. We use proto::result_of::make_expr<>
to calculate the return type. The first template parameter is the tag type
for the expression node we're building -- in this case, proto::tag::function,
which is the tag type Proto uses for function call expressions.

Subsequent template parameters to proto::result_of::make_expr<> represent children nodes. If a
child type is not already a Proto expression, it is made into a terminal
with proto::as_child(). A type such as pow_fun<Exp>
results in terminal that is held by value, whereas a type like Argconst& (note the reference) indicates that
the result should be held by reference.

In the function body is the runtime invocation of proto::make_expr().
It closely mirrors the return type calculation. proto::make_expr()
requires you to specify the node's tag type as a template parameter. The
arguments to the function become the node's children. When a child should
be stored by value, nothing special needs to be done. When a child should
be stored by reference, you must use the boost::ref() function to wrap the argument. Without
this extra information, the proto::make_expr()
function couldn't know whether to store a child by value or by reference.

In the Hello
Calculator section, we looked into making calculator expressions
directly usable as lambda expressions in calls to STL algorithms, as
below:

doubledata[]={1.,2.,3.,4.};// Use the calculator DSEL to square each element ... HOW?
std::transform(data,data+4,data,_1*_1);

The difficulty, if you recall, was that by default Proto expressions
don't have interesting behaviors of their own. They're just trees. In
particular, the expression _1*_1
won't have an operator()
that takes a double and returns a double like std::transform() expects -- unless we give it one. To
make this work, we needed to define an expression wrapper type that defined
the operator()
member function, and we needed to associate the wrapper with the calculator
domain.

In Proto, the term domain refers to a type that
associates expressions in that domain to an expression generator.
The generator is just a function object that accepts an expression and
does something to it, like wrapping it in an expression wrapper.

You can also use a domain to associate expressions with a grammar. When
you specify a domain's grammar, Proto ensures that all the expressions
it generates in that domain conform to the domain's grammar. It does
that by disabling any operator overloads that would create invalid expressions.

The first step to giving your calculator expressions extra behaviors
is to define a calculator domain. All expressions within the calculator
domain will be imbued with calculator-ness, as we'll see.

// A type to be used as a domain tag (to be defined below)
structcalculator_domain;

We use this domain type when extending the proto::expr<>
type, which we do with the proto::extends<>
class template. Here is our expression wrapper, which imbues an expression
with calculator-ness. It is described below.

// The calculator<> expression wrapper makes expressions
// function objects.
template<typenameExpr>structcalculator:proto::extends<Expr,calculator<Expr>,calculator_domain>{typedefproto::extends<Expr,calculator<Expr>,calculator_domain>base_type;calculator(Exprconst&expr=Expr()):base_type(expr){}// This is usually needed because by default, the compiler-
// generated assignment operator hides extends<>::operator=
BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator)typedefdoubleresult_type;// Hide base_type::operator() by defining our own which
// evaluates the calculator expression with a calculator context.
result_typeoperator()(doubled1=0.0,doubled2=0.0)const{// As defined in the Hello Calculator section.
calculator_contextctx;// ctx.args is a vector<double> that holds the values
// with which we replace the placeholders (e.g., _1 and _2)
// in the expression.
ctx.args.push_back(d1);// _1 gets the value of d1
ctx.args.push_back(d2);// _2 gets the value of d2
returnproto::eval(*this,ctx);// evaluate the expression
}};

We want calculator expressions to be function objects, so we have to
define an operator()
that takes and returns doubles. The calculator<> wrapper above does that with
the help of the proto::extends<>
template. The first template to proto::extends<>
parameter is the expression type we are extending. The second is the
type of the wrapped expression. The third parameter is the domain that
this wrapper is associated with. A wrapper type like calculator<> that inherits from proto::extends<> behaves just like
the expression type it has extended, with any additional behaviors you
choose to give it.

Note

Why not just inherit from proto::expr<>?

You might be thinking that this expression extension business is unnecessarily
complicated. After all, isn't this why C++ supports inheritance? Why
can't calculator<Expr> just inherit from
Expr directly? The reason is because Expr,
which presumably is an instantiation of proto::expr<>,
has expression template-building operator overloads that will be incorrect
for derived types. They will store *this by reference to proto::expr<>, effectively slicing off any
derived parts. proto::extends<>
gives your derived types operator overloads that don't slice off your
additional members.

Although not strictly necessary in this case, we bring extends<>::operator=
into scope with the BOOST_PROTO_EXTENDS_USING_ASSIGN() macro. This is really only necessary
if you want expressions like _1=3
to create a lazily evaluated assignment. proto::extends<>
defines the appropriate operator= for you, but the compiler-generated
calculator<>::operator=
will hide it unless you make it available with the macro.

Note that in the implementation of calculator<>::operator(), we evaluate the expression with the
calculator_context we
defined earlier. As we saw before, the context is what gives the operators
their meaning. In the case of the calculator, the context is also what
defines the meaning of the placeholder terminals.

Now that we have defined the calculator<> expression wrapper, we need to
wrap the placeholders to imbue them with calculator-ness:

To use proto::extends<>, your extension type
must derive from proto::extends<>.
Unfortunately, that means that your extension type is no longer POD and
its instances cannot be statically initialized.
(See the Static
Initialization section in the Rationale
appendix for why this matters.) In particular, as defined above, the
global placeholder objects _1
and _2 will need to be
initialized at runtime, which could lead to subtle order of initialization
bugs.

There is another way to make an expression extension that doesn't sacrifice
POD-ness : the BOOST_PROTO_EXTENDS()
macro. You can use it much like you use proto::extends<>.
We can use BOOST_PROTO_EXTENDS()
to keep calculator<>
a POD and our placeholders statically initialized.

We need to make one additional small change to accommodate the POD-ness
of our expression extension, which we'll describe below in the section
on expression generators.

What does BOOST_PROTO_EXTENDS()
do? It defines a data member of the expression type being extended; some
nested typedefs that Proto requires; operator=, operator[] and operator() overloads for building expression templates;
and a nested result<>
template for calculating the return type of operator(). In this case, however, the operator()
overloads and the result<> template are not needed because
we are defining our own operator() in the calculator<> type. Proto provides additional
macros for finer control over which member functions are defined. We
could improve our calculator<> type as follows:

Proto's operator overloads are defined in the boost::proto
namespace and are found by argument-dependent lookup (ADL). This usually
just works because expressions are made up of types that live in the
boost::proto namespace. However, sometimes
when you use BOOST_PROTO_EXTENDS()
that is not the case. Consider:

template<classT>structmy_complex{BOOST_PROTO_EXTENDS(typenameproto::terminal<std::complex<T>>::type,my_complex<T>,proto::default_domain)};intmain(){my_complex<int>c0,c1;c0+c1;// ERROR: operator+ not found
}

The problem has to do with how argument-dependent lookup works. The
type my_complex<int>
is not associated in any way with the boost::proto
namespace, so the operators defined there are not considered. (Had
we inherited from proto::extends<>
instead of used BOOST_PROTO_EXTENDS(),
we would have avoided the problem because inheriting from a type in
boost::proto namespace is enough to get
ADL to kick in.)

So what can we do? By adding an extra dummy template parameter that
defaults to a type in the boost::proto
namespace, we can trick ADL into finding the right operator overloads.
The solution looks like this:

The type proto::is_proto_expr is nothing
but an empty struct, but by making it a template parameter we make
boost::proto an associated namespace of
my_complex<int>.
Now ADL can successfully find Proto's operator overloads.

The last thing that remains to be done is to tell Proto that it needs
to wrap all of our calculator expressions in our calculator<> wrapper. We have already wrapped
the placeholders, but we want all expressions that
involve the calculator placeholders to be calculators. We can do that
by specifying an expression generator when we define our calculator_domain, as follows:

// Define the calculator_domain we forward-declared above.
// Specify that all expression in this domain should be wrapped
// in the calculator<> expression wrapper.
structcalculator_domain:proto::domain<proto::generator<calculator>>{};

The first template parameter to proto::domain<> is the generator. "Generator"
is just a fancy name for a function object that accepts an expression
and does something to it. proto::generator<> is a very simple one --- it wraps
an expression in the wrapper you specify. proto::domain<> inherits from its generator parameter,
so all domains are themselves function objects.

If we used BOOST_PROTO_EXTENDS()
to keep our expression extension type POD, then we need to use proto::pod_generator<>
instead of proto::generator<>,
as follows:

After Proto has calculated a new expression type, it checks the domains
of the child expressions. They must match. Assuming they do, Proto creates
the new expression and passes it to Domain::operator() for any additional processing. If we
don't specify a generator, the new expression gets passed through unchanged.
But since we've specified a generator above, calculator_domain::operator() returns calculator<> objects.

Now we can use calculator expressions as function objects to STL algorithms,
as follows:

doubledata[]={1.,2.,3.,4.};// Use the calculator DSEL to square each element ... WORKS! :-)
std::transform(data,data+4,data,_1*_1);

By default, Proto defines every possible operator overload for Protofied
expressions. This makes it simple to bang together a DSEL. In some cases,
however, the presence of Proto's promiscuous overloads can lead to confusion
or worse. When that happens, you'll have to disable some of Proto's overloaded
operators. That is done by defining the grammar for your domain and specifying
it as the second parameter of the proto::domain<>
template.

In the Hello
Calculator section, we saw an example of a Proto grammar, which
is repeated here:

We'll have much more to say about grammars in subsequent sections, but
for now, we'll just say that the calculator_grammar
struct describes a subset of all expression types -- the subset that
comprise valid calculator expressions. We would like to prohibit Proto
from creating a calculator expression that does not conform to this grammar.
We do that by changing the definition of the calculator_domain
struct.

// Define the calculator_domain. Expressions in the calculator
// domain are wrapped in the calculator<> wrapper, and they must
// conform to the calculator_grammar:
structcalculator_domain:proto::domain<proto::generator<calculator>,calculator_grammar>{};

The only new addition is calculator_grammar
as the second template parameter to the proto::domain<>
template. That has the effect of disabling any of Proto's operator overloads
that would create an invalid calculator expression.

Another common use for this feature would be to disable Proto's unary
operator&
overload. It may be surprising for users of your DSEL that they cannot
take the address of their expressions! You can very easily disable Proto's
unary operator&
overload for your domain with a very simple grammar, as below:

// For expressions in my_domain, disable Proto's
// unary address-of operator.
structmy_domain:proto::domain<proto::generator<my_wrapper>// A simple grammar that matches any expression that
// is not a unary address-of expression.
,proto::not_<proto::address_of<_>>>{};

The type proto::not_<proto::address_of<_>> is a very simple grammar
that matches all expressions except unary address-of expressions. In
the section describing Proto's intermediate form, we'll have much more
to say about grammars.

The preceding discussions of defining Proto front ends have all made a
big assumption: that you have the luxury of defining everything from scratch.
What happens if you have existing types, say a matrix type and a vector
type, that you would like to treat as if they were Proto terminals? Proto
usually trades only in its own expression types, but with BOOST_PROTO_DEFINE_OPERATORS(),
it can accomodate your custom terminal types, too.

Let's say, for instance, that you have the following types and that you
can't modify then to make them “native” Proto terminal types.

You can non-intrusively make objects of these types Proto terminals by
defining the proper operator overloads using BOOST_PROTO_DEFINE_OPERATORS().
The basic procedure is as follows:

Define a trait that returns true for your types and false for all others.

Reopen the namespace of your types and use BOOST_PROTO_DEFINE_OPERATORS()
to define a set of operator overloads, passing the name of the trait
as the first macro parameter, and the name of a Proto domain (e.g.,
proto::default_domain)
as the second.

The invocation of the BOOST_PROTO_DEFINE_OPERATORS()
macro defines a complete set of operator overloads that treat matrix and vector
objects as if they were Proto terminals. And since the operators are defined
in the same namespace as the matrix
and vector types, the operators
will be found by argument-dependent lookup. With the code above, we can
now construct expression templates with matrices and vectors, as shown
below.

Sometimes as a DSEL designer, to make the lives of your users easy, you
have to make your own life hard. Giving your users natural and flexible
syntax often involves writing large numbers of repetitive function overloads.
It can be enough to give you repetitive stress injury! Before you hurt
yourself, check out the macros Proto provides for automating many repetitive
code-generation chores.

Imagine that we are writing a lambda DSEL, and we would like to enable
syntax for constructing temporary objects of any type using the following
syntax:

// A lambda expression that takes two arguments and
// uses them to construct a temporary std::complex<>
construct<std::complex<int>>(_1,_2)

For the sake of the discussion, imagine that we already have a function
object template construct_impl<> that accepts arguments and constructs
new objects from them. We would want the above lambda expression to be
equivalent to the following:

// The above lambda expression should be roughly equivalent
// to the following:
proto::make_expr<proto::tag::function>(construct_impl<std::complex<int>>()// The function to invoke lazily
,boost::ref(_1)// The first argument to the function
,boost::ref(_2)// The second argument to the function
);

This works for two arguments, but we would like it to work for any number
of arguments, up to ( BOOST_PROTO_MAX_ARITY
- 1). (Why "- 1"? Because one child is taken up by the construct_impl<T>()
terminal leaving room for only ( BOOST_PROTO_MAX_ARITY
- 1) other children.)

Notice that we turned the function into a macro that takes 5 arguments.
The first is the current iteration number. The rest are the names of other
macros that generate different sequences. For instance, Proto passes as
the second parameter the name of a macro that will expand to typenameA0,typenameA1,....

Now that we have turned our function into a macro, we can pass the macro
to BOOST_PROTO_REPEAT_FROM_TO().
Proto will invoke it iteratively, generating all the function overloads
for us.

By now, you know a bit about how to build a front-end for your DSEL "compiler"
-- you can define terminals and functions that generate expression templates.
But we haven't said anything about the expression templates themselves. What
do they look like? What can you do with them? In this section we'll see.

All Proto expressions are an instantiation of a template called proto::expr<> (or a wrapper around
such an instantiation). When we define a terminal as below, we are really
initializing an instance of the proto::expr<>
template.

The proto::expr<> template is the most
important type in Proto. Although you will rarely need to deal with it directly,
it's always there behind the scenes holding your expression trees together.
In fact, proto::expr<>is
the expression tree -- branches, leaves and all.

The proto::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, or in the case of terminals, the terminal's value type. 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 proto::expr<> struct does not define
a constructor, or anything else that would prevent static initialization.
All proto::expr<> objects are initialized
using aggregate initialization, with curly braces. In
our example, _1 is initialized
with the initializer {{}}. The
outer braces are the initializer for the proto::expr<>
struct, and the inner braces are for the member _1.child0
which is of type placeholder<0>.
Note that we use braces to initialize _1.child0
because placeholder<0> is also
an aggregate.

The _1 node is an instantiation
of proto::expr<>, and expressions containing
_1 are also instantiations
of proto::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
typedefproto::expr<proto::tag::negate,proto::list1<proto::expr<proto::tag::terminal,proto::term<placeholder<0>>,0>const&>,1>negate_placeholder_type;negate_placeholder_typex=-_1;// The type of the expression _1 + 42
typedefproto::expr<proto::tag::plus,proto::list2<proto::expr<proto::tag::terminal,proto::term<placeholder<0>>,0>const&,proto::expr<proto::tag::terminal,proto::term<intconst&>,0>>,2>placeholder_plus_int_type;placeholder_plus_int_typey=_1+42;

There are a few things to note about these types:

Terminals have arity zero, unary expressions have arity one and binary
expressions have arity two.

When one Proto expression is made a child node of another Proto expression,
it is held by reference, even if it is a temporary object.
This last point becomes important later.

Non-Proto expressions, such as the integer literal, are turned into Proto
expressions by wrapping them in new expr<> terminal objects. These new wrappers
are not themselves held by reference, but the object wrapped is.
Notice that the type of the Protofied 42
literal is intconst& -- held by reference.

The types make it clear: everything in a Proto expression tree is held by
reference. That means that building an expression tree is exceptionally cheap.
It involves no copying at all.

Note

An astute reader will notice that the object y
defined above will be left holding a dangling reference to a temporary
int. In the sorts of high-performance applications Proto addresses, it
is typical to build and evaluate an expression tree before any temporary
objects go out of scope, so this dangling reference situation often doesn't
arise, but it is certainly something to be aware of. Proto provides utilities
for deep-copying expression trees so they can be passed around as value
types without concern for dangling references.

After assembling an expression into a tree, you'll naturally want to be
able to do the reverse, and access a node's children. You may even want
to be able to iterate over the children with algorithms from the Boost.Fusion
library. This section shows how.

Every node in an expression tree has both a tag type
that describes the node, and an arity corresponding
to the number of child nodes it has. You can use the proto::tag_of<>
and proto::arity_of<> metafunctions to fetch
them. Consider the following:

template<typenameExpr>voidcheck_plus_node(Exprconst&){// Assert that the tag type is proto::tag::plus
BOOST_STATIC_ASSERT((boost::is_same<typenameproto::tag_of<Expr>::type,proto::tag::plus>::value));// Assert that the arity is 2
BOOST_STATIC_ASSERT(proto::arity_of<Expr>::value==2);}// Create a binary plus node and use check_plus_node()
// to verify its tag type and arity:
check_plus_node(proto::lit(1)+2);

For a given type Expr,
you could access the tag and arity directly as Expr::proto_tag
and Expr::proto_arity, where Expr::proto_arity
is an MPL Integral Constant.

There is no simpler expression than a terminal, and no more basic operation
than extracting its value. As we've already seen, that is what proto::value() is for.

proto::terminal<std::ostream&>::typecout_={std::cout};// Get the value of the cout_ terminal:
std::ostream&sout=proto::value(cout_);// Assert that we got back what we put in:
assert(&sout==&std::cout);

To compute the return type of the proto::value()
function, you can use proto::result_of::value<>.
When the parameter to proto::result_of::value<>
is a non-reference type, the result type of the metafunction is the type
of the value as suitable for storage by value; that is, top-level reference
and qualifiers are stripped from it. But when instantiated with a reference
type, the result type has a reference added to it,
yielding a type suitable for storage by reference. If you want to know
the actual type of the terminal's value including whether it is stored
by value or reference, you can use fusion::result_of::value_at<Expr,0>::type.

Each non-terminal node in an expression tree corresponds to an operator
in an expression, and the children correspond to the operands, or arguments
of the operator. To access them, you can use the proto::child_c()
function template, as demonstrated below:

proto::terminal<int>::typei={42};// Get the 0-th operand of an addition operation:
proto::terminal<int>::type&ri=proto::child_c<0>(i+2);// Assert that we got back what we put in:
assert(&i==&ri);

You can use the proto::result_of::child_c<>
metafunction to get the type of the Nth child of an expression node. Usually
you don't care to know whether a child is stored by value or by reference,
so when you ask for the type of the Nth child of an expression Expr (where Expr
is not a reference type), you get the child's type after references and
cv-qualifiers have been stripped from it.

However, if you ask for the type of the Nth child of Expr& or Exprconst&
(note the reference), the result type will be a reference, regardless of
whether the child is actually stored by reference or not. If you need to
know exactly how the child is stored in the node, whether by reference
or by value, you can use fusion::result_of::value_at<Expr,N>::type. The following table summarizes
the behavior of the proto::result_of::child_c<>
metafunction.

When you build an expression template with Proto, all the intermediate
child nodes are held by reference. The avoids needless
copies, which is crucial if you want your DSEL to perform well at runtime.
Naturally, there is a danger if the temporary objects go out of scope before
you try to evaluate your expression template. This is especially a problem
in C++0x with the new decltype
and auto keywords. Consider:

The problem can happen in today's C++ also if you use BOOST_TYPEOF() or BOOST_AUTO(), or if you try to pass an expression
template outside the scope of its constituents.

In these cases, you want to deep-copy your expression template so that
all intermediate nodes and the terminals are held by value.
That way, you can safely assign the expression template to a local variable
or return it from a function without worrying about dangling references.
You can do this with proto::deep_copy()
as fo llows:

Proto provides a utility for pretty-printing expression trees that comes
in very handy when you're trying to debug your DSEL. It's called proto::display_expr(), and you pass it the expression
to print and optionally, an std::ostream
to which to send the output. Consider:

// Use display_expr() to pretty-print an expression tree
proto::display_expr(proto::lit("hello")+42);

The above code writes this to std::cout:

plus(
terminal(hello)
, terminal(42)
)

In order to call proto::display_expr(),
all the terminals in the expression must be Streamable (that is, they can
be written to a std::ostream). In addition, the tag types
must all be Streamable as well. Here is an example that includes a custom
terminal type and a custom tag:

// A custom tag type that is Streamable
structMyTag{friendstd::ostream&operator<<(std::ostream&s,MyTag){returns<<"MyTag";}};// Some other Streamable type
structMyTerminal{friendstd::ostream&operator<<(std::ostream&s,MyTerminal){returns<<"MyTerminal";}};intmain(){// Display an expression tree that contains a custom
// tag and a user-defined type in a terminal
proto::display_expr(proto::make_expr<MyTag>(MyTerminal())+42);}

The following table lists the overloadable C++ operators, the Proto tag
types for each, and the name of the metafunctions for generating the corresponding
Proto expression types. And as we'll see later, the metafunctions are also
usable as grammars for matching such nodes, as well as pass-through transforms.

Boost.Fusion is a library of iterators, algorithms, containers and adaptors
for manipulating heterogeneous sequences. In essence, a Proto expression
is just a heterogeneous sequence of its child expressions, and so Proto
expressions are valid Fusion random-access sequences. That means you can
apply Fusion algorithms to them, transform them, apply Fusion filters and
views to them, and access their elements using fusion::at(). The things Fusion can do to heterogeneous
sequences are beyond the scope of this users' guide, but below is a simple
example. It takes a lazy function invocation like fun(1,2,3,4)
and uses Fusion to print the function arguments in order.

Recall from the Introduction that types in the proto::functional
namespace define function objects that correspond to Proto's free functions.
So proto::functional::value()
creates a function object that is equivalent to the proto::value() function. The above invocation of fusion::for_each()
displays the following:

1
2
3
4

Terminals are also valid Fusion sequences. They contain exactly one element:
their value.

The reason this doesn't work is because the expression _1+2+3+4 does not describe a flat sequence
of terminals --- it describes a binary tree. We can treat it as a flat
sequence of terminals, however, using Proto's proto::flatten()
function. proto::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 process
is evaluated recursively. So the above can correctly be written as:

Expression trees can have a very rich and complicated structure. Often,
you need to know some things about an expression's structure before you
can process it. This section describes the tools Proto provides for peering
inside an expression tree and discovering its structure. And as you'll
see in later sections, all the really interesting things you can do with
Proto begin right here.

Imagine your DSEL is a miniature I/O facility, with iostream operations
that execute lazily. You might want expressions representing input operations
to be processed by one function, and output operations to be processed
by a different function. How would you do that?

The answer is to write patterns (a.k.a, grammars)
that match the structure of input and output expressions. Proto provides
utilities for defining the grammars, and the proto::matches<>
template for checking whether a given expression type matches the grammar.

First, let's define some terminals we can use in our lazy I/O expressions:

Now, we can use cout_
instead of std::cout, and get I/O expression trees
that we can execute later. To define grammars that match input and output
expressions of the form cin_>>i
and cout_<<1 we do this:

We've seen the template proto::terminal<> before, but here we're using
it without accessing the nested ::type. When used like this, it is a
very simple grammar, as are proto::shift_right<> and proto::shift_left<>. The newcomer here is _ in the proto
namespace. It is a wildcard that matches anything. The Input struct is a grammar that matches
any right-shift expression that has a std::istream
terminal as its left operand.

We can use these grammars together with the proto::matches<>
template to query at compile time whether a given I/O expression type
is an input or output operation. Consider the following:

This works as the previous version did. However, the following does not
compile at all:

input_output(cout_<<1<<2);// oops!

What's wrong? The problem is that this expression does not match our
grammar. The expression groups as if it were written like (cout_<<1)<<2. It will not match the Output grammar, which expects the left
operand to be a terminal, not another left-shift operation. We need to
fix the grammar.

We notice that in order to verify an expression as input or output, we'll
need to recurse down to the bottom-left-most leaf and check that it is
a std::istream or std::ostream.
When we get to the terminal, we must stop recursing. We can express this
in our grammar using proto::or_<>.
Here are the correct Input
and Output grammars:

This may look a little odd at first. We seem to be defining the Input and Output
types in terms of themselves. This is perfectly OK, actually. At the
point in the grammar that the Input
and Output types are
being used, they are incomplete, but by the time
we actually evaluate the grammar with proto::matches<>,
the types will be complete. These are recursive grammars, and rightly
so because they must match a recursive data structure!

Matching an expression such as cout_<<1<<2
against the Output grammar
procedes as follows:

The first alternate of the proto::or_<>
is tried first. It will fail, because the expression cout_<<1<<2 does not match the grammar
proto::shift_left<proto::terminal<std::ostream&>,proto::_>.

Then the second alternate is tried next. We match the expression
against proto::shift_left<Output,proto::_>.
The expression is a left-shift, so we next try to match the operands.

The right operand 2 matches
proto::_ trivially.

To see if the left operand cout_<<1
matches Output, we
must recursively evaluate the Output
grammar. This time we succeed, because cout_<<1
will match the first alternate of the proto::or_<>.

The terminals in an expression tree could be const or non-const references,
or they might not be references at all. When writing grammars, you usually
don't have to worry about it because proto::matches<>
gives you a little wiggle room when matching terminals. A grammar such
as proto::terminal<int>
will match a terminal of type int,
int&,
or intconst&.

You can explicitly specify that you want to match a reference type. If
you do, the type must match exactly. For instance, a grammar such as
proto::terminal<int&>
will only match an int&. It will not match an int or an intconst&.

The table below shows how Proto matches terminals. The simple rule is:
if you want to match only reference types, you must specify the reference
in your grammar. Otherwise, leave it off and Proto will ignore const
and references.

This begs the question: What if you want to match an int,
but not an int&
or an intconst&? For forcing exact matches,
Proto provides the proto::exact<>
template. For instance, proto::terminal<proto::exact<int>>
would only match an int
held by value.

Proto gives you extra wiggle room when matching array types. Array types
match themselves or the pointer types they decay to. This is especially
useful with character arrays. The type returned by proto::as_expr("hello") is proto::terminal<charconst[6]>::type. That's a terminal containing
a 6-element character array. Naturally, you can match this terminal with
the grammar proto::terminal<charconst[6]>,
but the grammar proto::terminal<charconst*>
will match it as well, as the following code fragment illustrates.

Now, CharString does
not match array types, only character string pointers.

The inverse problem is a little trickier: what if you wanted to match
all character arrays, but not character pointers? As mentioned above,
the expression as_expr("hello") has the type proto::terminal<charconst[6]>::type. If you wanted to match character
arrays of arbitrary size, you could use proto::N,
which is an array-size wildcard. The following grammar would match any
string literal: proto::terminal<charconst[proto::N]>.

Sometimes you need even more wiggle room when matching terminals. For
example, maybe you're building a calculator DSEL and you want to allow
any terminals that are convertible to double.
For that, Proto provides the proto::convertible_to<>
template. You can use it as: proto::terminal<proto::convertible_to<double>>.

There is one more way you can perform a fuzzy match on terminals. Consider
the problem of trying to match a std::complex<> terminal. You can easily match
a std::complex<float>
or a std::complex<double>,
but how would you match any instantiation of std::complex<>? You can use proto::_
here to solve this problem. Here is the grammar to match any std::complex<>
instantiation:

structStdComplex:proto::terminal<std::complex<proto::_>>{};

When given a grammar like this, Proto will deconstruct the grammar and
the terminal it is being matched against and see if it can match all
the constituents.

We've already seen how to use expression generators like proto::terminal<>
and proto::shift_right<>
as grammars. We've also seen proto::or_<>,
which we can use to express a set of alternate grammars. There are a
few others of interest; in particular, proto::if_<>,
proto::and_<> and proto::not_<>.

The proto::not_<> template is the simplest.
It takes a grammar as a template parameter and logically negates it;
not_<Grammar>
will match any expression that Grammar
does not match.

The proto::if_<> template is used
together with a Proto transform that is evaluated against expression
types to find matches. (Proto transforms will be described later.)

This says that a CharString
must be a terminal, and its value type must be the
same as charconst*. Notice the template argument
of proto::if_<>: boost::is_same<proto::_value,charconst*>(). This is Proto transform that compares
the value type of a terminal to charconst*.

The proto::if_<> template has a couple
of variants. In addition to if_<Condition> you can also say if_<Condition,ThenGrammar> and if_<Condition,ThenGrammar,ElseGrammar>. These let you select one sub-grammar
or another based on the Condition.

When your Proto grammar gets large, you'll start to run into some scalability
problems with proto::or_<>, the construct you
use to specify alternate sub-grammars. First, due to limitations in C++,
proto::or_<> can only accept up
to a certain number of sub-grammars, controlled by the BOOST_PROTO_MAX_LOGICAL_ARITY macro.
This macro defaults to eight, and you can set it higher, but doing so
will aggravate another scalability problem: long compile times. With
proto::or_<>, alternate sub-grammars
are tried in order -- like a series of cascading if's
-- leading to lots of unnecessary template instantiations. What you would
prefer instead is something like switch
that avoids the expense of cascading if's.
That's the purpose of proto::switch_<>;
although less convenient than proto::or_<>,
it improves compile times for larger grammars and does not have an arbitrary
fixed limit on the number of sub-grammars.

The above might be the grammar to a more elaborate calculator DSEL. Notice
that since there are more than eight sub-grammars, we had to chain the
sub-grammars with a nested proto::or_<>
-- not very nice.

The idea behind proto::switch_<>
is to dispatch based on an expression's tag type to a sub-grammar that
handles expressions of that type. To use proto::switch_<>,
you define a struct with a nested case_<> template, specialized on tag
types. The above grammar can be expressed using proto::switch_<>
as follows. It is described below.

Matching an expression type E
against proto::switch_<C>
is equivalent to matching it against C::case_<E::proto_tag>. By dispatching on the expression's
tag type, we can jump to the sub-grammar that handles expressions of
that type, skipping over all the other sub-grammars that couldn't possibly
match. If there is no specialization of case_<> for a particular tag type, we
select the primary template. In this case, the primary template inherits
from proto::not_<_>
which matches no expressions.

Unfortunately, for arcane reasons, it is not legal to define an explicit
nested specialization in situ like this. It is,
however, perfectly legal to define partial specializations
in situ, so you can add a extra dummy template
parameter that has a default, as follows:

Not all of C++'s overloadable operators are unary or binary. There is
the oddball operator()
-- the function call operator -- which can have any number of arguments.
Likewise, with Proto you may define your own "operators" that
could also take more that two arguments. As a result, there may be nodes
in your Proto expression tree that have an arbitrary number of children
(up to BOOST_PROTO_MAX_ARITY,
which is configurable). How do you write a grammar to match such a node?

For such cases, Proto provides the proto::vararg<>
class template. Its template argument is a grammar, and the proto::vararg<> will match the grammar
zero or more times. Consider a Proto lazy function called fun()
that can take zero or more characters as arguments, as follows:

Here's a hint: the first template parameter to proto::nary_expr<> represents the node type, and
any additional template parameters represent child nodes. The answer
is that this is a degenerate grammar that matches every possible expression
tree, from root to leaves.

In this section we'll see how to use Proto to define a grammar for your
DSEL and use it to validate expression templates, giving short, readable
compile-time errors for invalid expressions.

Tip

You might think that this is a backwards way of doing things. “If
Proto let me select which operators to overload, my users wouldn't
be able to create invalid expressions in the first place, and I wouldn't
need a grammar at all!” That may be true, but there are reasons
for preferring to do things this way.

First, it lets you develop your DSEL rapidly -- all the operators are
there for you already! -- and worry about invalid syntax later.

Second, it might be the case that some operators are only allowed in
certain contexts within your DSEL. This is easy to express with a grammar,
and hard to do with straight operator overloading.

Third, using a DSEL grammar to flag invalid expressions can often yield
better errors than manually selecting the overloaded operators.

Fourth, the grammar can be used for more than just validation. You
can use your grammar to define tree transformations
that convert expression templates into other more useful objects.

If none of the above convinces you, you actually can
use Proto to control which operators are overloaded within your domain.
And to do it, you need to define a grammar!

In a previous section, we used Proto to define a DSEL for a lazily evaluated
calculator that allowed any combination of placeholders, floating-point
literals, addition, subtraction, multiplication, division and grouping.
If we were to write the grammar for this DSEL in EBNF,
it might look like this:

This captures the syntax, associativity and precedence rules of a calculator.
Writing the grammar for our calculator DSEL using Proto is even
simpler. Since we are using C++ as the host language, we are
bound to the associativity and precedence rules for the C++ operators.
Our grammar can assume them. Also, in C++ grouping is already handled
for us with the use of parenthesis, so we don't have to code that into
our grammar.

Let's begin our grammar for forward-declaring it:

structCalculatorGrammar;

It's an incomplete type at this point, but we'll still be able to use
it to define the rules of our grammar. Let's define grammar rules for
the terminals:

Now let's define the rules for addition, subtraction, multiplication
and division. Here, we can ignore issues of associativity and precedence
-- the C++ compiler will enforce that for us. We only must enforce that
the arguments to the operators must themselves conform to the CalculatorGrammar that we forward-declared
above.

That's it! Now we can use CalculatorGrammar
to enforce that an expression template conforms to our grammar. We can
use proto::matches<> and BOOST_MPL_ASSERT()
to issue readable compile-time errors for invalid expressions, as below:

Now that you've written the front end for your DSEL compiler, and you've
learned a bit about the intermediate form it produces, it's time to think
about what to do with the intermediate form. This is
where you put your domain-specific algorithms and optimizations. Proto gives
you two ways to evaluate and manipulate expression templates: contexts and
transforms.

A context is like a function object that you pass
along with an expression to the proto::eval()
function. It associates behaviors with node types. proto::eval()
walks the expression and invokes your context at each node.

A transform is a way to associate behaviors, not
with node types in an expression, but with rules in a Proto grammar.
In this way, they are like semantic actions in other compiler-construction
toolkits.

Two ways to evaluate expressions! How to choose? Since contexts are largely
procedural, they are a bit simpler to understand and debug so they are a
good place to start. But although transforms are more advanced, they are
also more powerful; since they are associated with rules in your grammar,
you can select the proper transform based on the entire structure
of a sub-expression rather than simply on the type of its top-most node.

Also, transforms have a concise and declarative syntax that can be confusing
at first, but highly expressive and fungible once you become accustomed to
it. And -- this is admittedly very subjective -- the author finds programming
with Proto transforms to be an inordinate amount of fun!
Your mileage may vary.

Once you have constructed a Proto expression tree, either by using Proto's
operator overloads or with proto::make_expr()
and friends, you probably want to actually do something
with it. The simplest option is to use proto::eval(), a generic expression evaluator. To use
proto::eval(), you'll need to define
a context that tells proto::eval()
how each node should be evaluated. This section goes through the nuts and
bolts of using proto::eval(), defining evaluation contexts,
and using the contexts that Proto provides.

Note

proto::eval()
is a less powerful but easier-to-use evaluation technique than Proto
transforms, which are covered later. Although very powerful, transforms
have a steep learning curve and can be more difficult to debug. proto::eval()
is a rather weak tree traversal algorithm. Dan Marsden has been working
on a more general and powerful tree traversal library. When it is ready,
I anticipate that it will eliminate the need for proto::eval().

namespaceproto{namespaceresult_of{// A metafunction for calculating the return
// type of proto::eval() given certain Expr
// and Context types.
template<typenameExpr,typenameContext>structeval{typedeftypenameContext::templateeval<Expr>::result_typetype;};}namespacefunctional{// A callable function object type for evaluating
// a Proto expression with a certain context.
structeval:callable{template<typenameSig>structresult;template<typenameExpr,typenameContext>typenameproto::result_of::eval<Expr,Context>::typeoperator()(Expr&expr,Context&context)const;template<typenameExpr,typenameContext>typenameproto::result_of::eval<Expr,Context>::typeoperator()(Expr&expr,Contextconst&context)const;};}template<typenameExpr,typenameContext>typenameproto::result_of::eval<Expr,Context>::typeeval(Expr&expr,Context&context);template<typenameExpr,typenameContext>typenameproto::result_of::eval<Expr,Context>::typeeval(Expr&expr,Contextconst&context);}

Given an expression and an evaluation context, using proto::eval()
is quite simple. Simply pass the expression and the context to proto::eval() and it does the rest
and returns the result. You can use the eval<> metafunction in the proto::result_of namespace to compute the
return type of proto::eval(). The following demonstrates
a use of proto::eval():

template<typenameExpr>typenameproto::result_of::eval<Exprconst,MyContext>::typeMyEvaluate(Exprconst&expr){// Some user-defined context type
MyContextctx;// Evaluate an expression with the context
returnproto::eval(expr,ctx);}

What proto::eval() does is also very simple.
It defers most of the work to the context itself. Here essentially is
the implementation of proto::eval():

Really, proto::eval() is nothing more than
a thin wrapper that dispatches to the appropriate handler within the
context class. In the next section, we'll see how to implement a context
class from scratch.

As we saw in the previous section, there is really not much to the proto::eval() function. Rather, all
the interesting expression evaluation goes on within a context class.
This section shows how to implement one from scratch.

Context classes are nothing more than a collection of specializations
of a nested eval<>
class template. Each specialization handles a different expression type.

In the Hello
Calculator section, we saw an example of a user-defined context
class for evaluating calculator expressions. That context class was implemented
with the help of Proto's proto::callable_context<>.
If we were to implement it from scratch, it would look something like
this:

// The calculator_context from the "Hello Calculator" section,
// implemented from scratch.
structcalculator_context{// The values with which we'll replace the placeholders
std::vector<double>args;template<typenameExpr// defaulted template parameters, so we can
// specialize on the expressions that need
// special handling.
,typenameTag=typenameproto::tag_of<Expr>::type,typenameArg0=typenameproto::child_c<Expr,0>::type>structeval;// Handle placeholder terminals here...
template<typenameExpr,intI>structeval<Expr,proto::tag::terminal,placeholder<I>>{typedefdoubleresult_type;result_typeoperator()(Expr&,MyContext&ctx)const{returnctx.args[I];}};// Handle other terminals here...
template<typenameExpr,typenameArg0>structeval<Expr,proto::tag::terminal,Arg0>{typedefdoubleresult_type;result_typeoperator()(Expr&expr,MyContext&)const{returnproto::child(expr);}};// Handle addition here...
template<typenameExpr,typenameArg0>structeval<Expr,proto::tag::plus,Arg0>{typedefdoubleresult_type;result_typeoperator()(Expr&expr,MyContext&ctx)const{returnproto::eval(proto::left(expr),ctx)+proto::eval(proto::right(expr),ctx);}};// ... other eval<> specializations for other node types ...
};

Now we can use proto::eval() with the context class
above to evaluate calculator expressions as follows:

// Evaluate an expression with a calculator_context
calculator_contextctx;ctx.args.push_back(5);ctx.args.push_back(6);doubled=proto::eval(_1+_2,ctx);assert(11==d);

Defining a context from scratch this way is tedious and verbose, but
it gives you complete control over how the expression is evaluated. The
context class in the Hello
Calculator example was much simpler. In the next section we'll
see the helper class Proto provides to ease the job of implementing context
classes.

An evaluation context that assigns the usual C++ meanings to all
the operators. For example, addition nodes are handled by evaluating
the left and right children and then adding the results. The proto::default_context
uses Boost.Typeof to deduce the types of the expressions it evaluates.

A helper that simplifies the job of writing context classes. Rather
than writing template specializations, with proto::callable_context<>
you write a function object with an overloaded function call operator.
Any expressions not handled by an overload are automatically dispatched
to a default evaluation context that you can specify.

The proto::default_context is an
evaluation context that assigns the usual C++ meanings to all the operators.
For example, addition nodes are handled by evaluating the left and
right children and then adding the results. The proto::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/proto/proto.hpp>#include<boost/proto/context.hpp>#include<boost/typeof/std/ostream.hpp>usingnamespaceboost;proto::terminal<std::ostream&>::typecout_={std::cout};template<typenameExpr>voidevaluate(Exprconst&expr){// Evaluate the expression with default_context,
// to give the operators their C++ meanings:
proto::default_contextctx;proto::eval(expr,ctx);}intmain(){evaluate(cout_<<"hello"<<','<<" world");return0;}

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.

The proto::null_context<>
is a simple context that recursively evaluates children 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.

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:

structincrement_ints{// By default, just evaluate all children by delegating
// to the null_eval<>
template<typenameExpr,typenameArg=proto::result_of::child<Expr>::type>structeval:null_eval<Expr,increment_intsconst>{};// Increment integer terminals
template<typenameExpr>structeval<Expr,int>{typedefvoidresult_type;voidoperator()(Expr&expr,increment_intsconst&)const{++proto::child(expr);}};};

The proto::callable_context<>
is a helper that simplifies the job of writing context classes. Rather
than writing template specializations, with proto::callable_context<>
you write a function object with an overloaded function call operator.
Any expressions not handled by an overload are automatically dispatched
to a default evaluation context that you can specify.

In the 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 proto::callable_context<>:

This program outputs the following, which shows that the integers
i and j have been incremented by 1:

i = 1
j = 11

In the increment_ints
context, we didn't have to define any nested eval<> templates. That's because
proto::callable_context<>
implements them for us. proto::callable_context<>
takes two template parameters: the derived context and a fall-back
context. For each node in the expression tree being evaluated, proto::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:

Using function overloading and metaprogramming tricks, proto::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 proto::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 proto::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.
structcalculator_context:proto::callable_context<calculator_contextconst>{std::vector<double>args;// Define the result type of the calculator.
typedefdoubleresult_type;// Handle the placeholders:
template<intI>doubleoperator()(proto::tag::terminal,placeholder<I>)const{returnthis->args[I];}};

In this case, we didn't specify a fall-back context. In that case,
proto::callable_context<>
uses the proto::default_context. With
the above calculator_context
and a couple of appropriately defined placeholder terminals, we can
evaluate calculator expressions, as demonstrated below:

If you have ever built a parser with the help of a tool like Antlr, yacc
or Boost.Spirit, you might be familiar with semantic actions.
In addition to allowing you to define the grammar of the language recognized
by the parser, these tools let you embed code within your grammar that
executes when parts of the grammar participate in a parse. Proto has the
equivalent of semantic actions. They are called transforms.
This section describes how to embed transforms within your Proto grammars,
turning your grammars into function objects that can manipulate or evaluate
expressions in powerful ways.

Proto transforms are an advanced topic. We'll take it slow, using examples
to illustrate the key concepts, starting simple.

The Proto grammars we've seen so far are static. You can check at compile-time
to see if an expression type matches a grammar, but that's it. Things
get more interesting when you give them runtime behaviors. A grammar
with embedded transforms is more than just a static grammar. It is a
function object that accepts expressions that match the grammar and does
something with them.

Below is a very simple grammar. It matches terminal expressions.

// A simple Proto grammar that matches all terminals
proto::terminal<_>

Here is the same grammar with a transform that extracts the value from
the terminal:

// A simple Proto grammar that matches all terminals
// *and* a function object that extracts the value from
// the terminal
proto::when<proto::terminal<_>,proto::_value// <-- Look, a transform!
>

You can read this as follows: when you match a terminal expression, extract
the value. The type proto::_value
is a so-called transform. Later we'll see what makes it a transform,
but for now just think of it as a kind of function object. Note the use
of proto::when<>: the first template
parameter is the grammar to match and the second is the transform to
execute. The result is both a grammar that matches terminal expressions
and a function object that accepts terminal expressions and extracts
their values.

As with ordinary grammars, we can define an empty struct that inherits
from a grammar+transform to give us an easy way to refer back to the
thing we're defining, as follows:

// A grammar and a function object, as before
structValue:proto::when<proto::terminal<_>,proto::_value>{};// "Value" is a grammar that matches terminal expressions
BOOST_MPL_ASSERT((proto::matches<proto::terminal<int>::type,Value>));// "Value" also defines a function object that accepts terminals
// and extracts their value.
proto::terminal<int>::typeanswer={42};Valueget_value;inti=get_value(answer);

As already mentioned, Value
is a grammar that matches terminal expressions and a function object
that operates on terminal expressions. It would be an error to pass a
non-terminal expression to the Value
function object. This is a general property of grammars with transforms;
when using them as function objects, expressions passed to them must
match the grammar.

Proto grammars are valid TR1-style function objects. That means you can
use boost::result_of<>
to ask a grammar what its return type will be, given a particular expression
type. For instance, we can access the Value
grammar's return type as follows:

// We can use boost::result_of<> to get the return type
// of a Proto grammar.
typedeftypenameboost::result_of<Value(proto::terminal<int>::type)>::typeresult_type;// Check that we got the type we expected
BOOST_MPL_ASSERT((boost::is_same<result_type,int>));

Note

A grammar with embedded transforms is both a grammar and a function
object. Calling these things "grammars with transforms" would
get tedious. We could call them something like "active grammars",
but as we'll see every grammar that you can define
with Proto is "active"; that is, every grammar has some behavior
when used as a function object. So we'll continue calling these things
plain "grammars". The term "transform" is reserved
for the thing that is used as the second parameter to the proto::when<> template.

Most grammars are a little more complicated than the one in the preceding
section. For the sake of illustration, let's define a rather nonsensical
grammar that matches any expression and recurses to the leftmost terminal
and returns its value. It will demonstrate how two key concepts of Proto
grammars -- alternation and recursion -- interact with transforms. The
grammar is described below.

// A grammar that matches any expression, and a function object
// that returns the value of the leftmost terminal.
structLeftmostLeaf:proto::or_<// If the expression is a terminal, return its value
proto::when<proto::terminal<_>,proto::_value>// Otherwise, it is a non-terminal. Return the result
// of invoking LeftmostLeaf on the 0th (leftmost) child.
,proto::when<_,LeftmostLeaf(proto::_child0)>>{};// A Proto terminal wrapping std::cout
proto::terminal<std::ostream&>::typecout_={std::cout};// Create an expression and use LeftmostLeaf to extract the
// value of the leftmost terminal, which will be std::cout.
std::ostream&sout=LeftmostLeaf()(cout_<<"the answer: "<<42<<'\n');

We've seen proto::or_<>
before. Here it is serving two roles. First, it is a grammar that matches
any of its alternate sub-grammars; in this case, either a terminal or
a non-terminal. Second, it is also a function object that accepts an
expression, finds the alternate sub-grammar that matches the expression,
and applies its transform. And since LeftmostLeaf
inherits from proto::or_<>,
LeftmostLeaf is also
both a grammar and a function object.

Note

The second alternate uses proto::_
as its grammar. Recall that proto::_
is the wildcard grammar that matches any expression. Since alternates
in proto::or_<>
are tried in order, and since the first alternate handles all terminals,
the second alternate handles all (and only) non-terminals. Often enough,
proto::when<_,some-transform>
is the last alternate in a grammar, so for improved readability, you
could use the equivalent proto::otherwise<some-transform>.

It has the effect of accepting non-terminal expressions, taking the 0th
(leftmost) child and recursively invoking the LeftmostLeaf
function on it. But LeftmostLeaf(proto::_child0) is actually a function
type. Literally, it is the type of a function that accepts
an object of type proto::_child0
and returns an object of type LeftmostLeaf.
So how do we make sense of this transform? Clearly, there is no function
that actually has this signature, nor would such a function be useful.
The key is in understanding how proto::when<>interprets
its second template parameter.

When the second template parameter to proto::when<>
is a function type, proto::when<>
interprets the function type as a transform. In this case, LeftmostLeaf is treated as the type
of a function object to invoke, and proto::_child0
is treated as a transform. First, proto::_child0
is applied to the current expression (the non-terminal that matched this
alternate sub-grammar), and the result (the 0th child) is passed as an
argument to LeftmostLeaf.

Note

Transforms are a Domain-Specific Language

LeftmostLeaf(proto::_child0)looks like an invocation of the LeftmostLeaf function object, but
it's not, but then it actually is! Why this confusing subterfuge? Function
types give us a natural and concise syntax for composing more complicated
transforms from simpler ones. The fact that the syntax is suggestive
of a function invocation is on purpose. It is a domain-specific embedded
language for defining expression transformations. If the subterfuge
worked, it may have fooled you into thinking the transform is doing
exactly what it actually does! And that's the point.

The type LeftmostLeaf(proto::_child0) is an example of a callable
transform. It is a function type that represents a function
object to call and its arguments. The types proto::_child0
and proto::_value are primitive transforms.
They are plain structs, not unlike function objects, from which callable
transforms can be composed. There is one other type of transform, object
transforms, that we'll encounter next.

The very first transform we looked at simply extracted the value of terminals.
Let's do the same thing, but this time we'll promote all ints to longs
first. (Please forgive the contrived-ness of the examples so far; they
get more interesting later.) Here's the grammar:

// A simple Proto grammar that matches all terminals,
// and a function object that extracts the value from
// the terminal, promoting ints to longs:
structValueWithPomote:proto::or_<proto::when<proto::terminal<int>,long(proto::_value)// <-- an "object" transform
>,proto::when<proto::terminal<_>,proto::_value>>{};

You can read the above grammar as follows: when you match an int terminal,
extract the value from the terminal and use it to initialize a long;
otherwise, when you match another kind of terminal, just extract the
value. The type long(proto::_value)
is a so-called object transform. It looks like the
creation of a temporary long, but it's really a function type. Just as
a callable transform is a function type that represents a function to
call and its arguments, an object transforms is a function type that
represents an object to construct and the arguments to its constructor.

Note

Object Transforms vs. Callable Transforms

When using function types as Proto transforms, they can either represent
an object to construct or a function to call. It is similar to "normal"
C++ where the syntax foo("arg") can either be interpreted as an object
to construct or a function to call, depending on whether foo is a type or a function. But
consider two of the transforms we've seen so far:

Proto can't know in general which is which, so it uses a trait, proto::is_callable<>,
to differentiate. is_callable<long>::value
is false so long(proto::_value)
is an object to construct, but is_callable<LeftmostLeaf>::value
is true so LeftmostLeaf(proto::_child0) is a function to call. Later on, we'll
see how Proto recognizes a type as "callable".

Now that we have the basics of Proto transforms down, let's consider
a slightly more realistic example. We can use transforms to improve the
type-safety of the calculator
DSEL. If you recall, it lets you write infix arithmetic expressions
involving argument placeholders like _1
and _2 and pass them
to STL algorithms as function objects, as follows:

doublea1[4]={56,84,37,69};doublea2[4]={65,120,60,70};doublea3[4]={0};// Use std::transform() and a calculator expression
// to calculate percentages given two input sequences:
std::transform(a1,a1+4,a2,a3,(_2-_1)/_2*100);

This works because we gave calculator expressions an operator() that evaluates the expression, replacing
the placeholders with the arguments to operator(). The overloaded calculator<>::operator() looked like this:

The expression _1*_1 defines a unary calculator
expression; it takes one argument and squares it. If we pass more than
one argument, the extra arguments will be silently ignored, which might
be surprising to users. The next expression, _2*_2
defines a binary calculator expression; it takes two arguments, ignores
the first and squares the second. If we only pass one argument, the code
silently fills in 0.0 for
the second argument, which is also probably not what users expect. What
can be done?

We can say that the arity of a calculator expression
is the number of arguments it expects, and it is equal to the largest
placeholder in the expression. So, the arity of _1*_1
is one, and the arity of _2*_2
is two. We can increase the type-safety of our calculator DSEL by making
sure the arity of an expression equals the actual number of arguments
supplied. Computing the arity of an expression is simple with the help
of Proto transforms.

It's straightforward to describe in words how the arity of an expression
should be calculated. Consider that calculator expressions can be made
of _1, _2, literals, unary expressions and
binary expressions. The following table shows the arities for each of
these 5 constituents.

Table 15.7. Calculator Sub-Expression Arities

Sub-Expression

Arity

Placeholder 1

1

Placeholder 2

2

Literal

0

Unary Expression

arity of the operand

Binary Expression

max arity of the two operands

Using this information, we can write the grammar for calculator expressions
and attach transforms for computing the arity of each constituent. The
code below computes the expression arity as a compile-time integer, using
integral wrappers and metafunctions from the Boost MPL Library. The grammar
is described below.

When we find a placeholder terminal or a literal, we use an object
transform such as mpl::int_<1>()
to create a (default-constructed) compile-time integer representing the
arity of that terminal.

For unary expressions, we use CalcArity(proto::_child) which is a callable transform
that computes the arity of the expression's child.

The transform for binary expressions has a few new tricks. Let's look
more closely:

// Compute the left and right arities and
// take the larger of the two.
mpl::max<CalcArity(proto::_left),CalcArity(proto::_right)>()

This is an object transform; it default-constructs ... what exactly?
The mpl::max<>
template is an MPL metafunction that accepts two compile-time integers.
It has a nested ::type
typedef (not shown) that is the maximum of the two. But here, we appear
to be passing it two things that are not compile-time
integers; they're Proto callable transforms. Proto is smart enough to
recognize that fact. It first evaluates the two nested callable transforms,
computing the arities of the left and right child expressions. Then it
puts the resulting integers into mpl::max<> and evaluates the metafunction
by asking for the nested ::type. That is the type of the object
that gets default-constructed and returned.

More generally, when evaluating object transforms, Proto looks at the
object type and checks whether it is a template specialization, like
mpl::max<>.
If it is, Proto looks for nested transforms that it can evaluate. After
any nested transforms have been evaluated and substituted back into the
template, the new template specialization is the result type, unless
that type has a nested ::type, in which case that becomes the
result.

Now that we can calculate the arity of a calculator expression, let's
redefine the calculator<> expression wrapper we wrote in
the Getting Started guide to use the CalcArity
grammar and some macros from Boost.MPL to issue compile-time errors when
users specify too many or too few arguments.

// The calculator expression wrapper, as defined in the Hello
// Calculator example in the Getting Started guide. It behaves
// just like the expression it wraps, but with extra operator()
// member functions that evaluate the expression.
// NEW: Use the CalcArity grammar to ensure that the correct
// number of arguments are supplied.
template<typenameExpr>structcalculator:proto::extends<Expr,calculator<Expr>,calculator_domain>{typedefproto::extends<Expr,calculator<Expr>,calculator_domain>base_type;calculator(Exprconst&expr=Expr()):base_type(expr){}typedefdoubleresult_type;// Use CalcArity to compute the arity of Expr:
staticintconstarity=boost::result_of<CalcArity(Expr)>::type::value;doubleoperator()()const{BOOST_MPL_ASSERT_RELATION(0,==,arity);calculator_contextctx;returnproto::eval(*this,ctx);}doubleoperator()(doublea1)const{BOOST_MPL_ASSERT_RELATION(1,==,arity);calculator_contextctx;ctx.args.push_back(a1);returnproto::eval(*this,ctx);}doubleoperator()(doublea1,doublea2)const{BOOST_MPL_ASSERT_RELATION(2,==,arity);calculator_contextctx;ctx.args.push_back(a1);ctx.args.push_back(a2);returnproto::eval(*this,ctx);}};

Note the use of boost::result_of<> to access the return type of
the CalcArity function
object. Since we used compile-time integers in our transforms, the arity
of the expression is encoded in the return type of the CalcArity function object. Proto grammars
are valid TR1-style function objects, so you can use boost::result_of<> to figure out their return types.

With our compile-time assertions in place, when users provide too many
or too few arguments to a calculator expression, as in:

(_2*_2)(42);// Oops, too few arguments!

... they will get a compile-time error message on the line with the assertion
that reads something like this[3]:

The point of this exercise was to show that we can write a fairly simple
Proto grammar with embedded transforms that is declarative and readable
and can compute interesting properties of arbitrarily complicated expressions.
But transforms can do more than that. Boost.Xpressive uses transforms
to turn expressions into finite state automata for matching regular expressions,
and Boost.Spirit uses transforms to build recursive descent parser generators.
Proto comes with a collection of built-in transforms that you can use
to perform very sophisticated expression manipulations like these. In
the next few sections we'll see some of them in action.

So far, we've only seen examples of grammars with transforms that accept
one argument: the expression to transform. But consider for a moment
how, in ordinary procedural code, you would turn a binary tree into a
linked list. You would start with an empty list. Then, you would recursively
convert the right branch to a list, and use the result as the initial
state while converting the left branch to a list. That is, you would
need a function that takes two parameters: the current node and the list
so far. These sorts of accumulation problems are
quite common when processing trees. The linked list is an example of
an accumulation variable or state. Each iteration
of the algorithm takes the current element and state, applies some binary
function to the two and creates a new state. In the STL, this algorithm
is called std::accumulate().
In many other languages, it is called fold. Let's
see how to implement a fold algorithm with Proto transforms.

All Proto grammars can optionally accept a state parameter in addition
to the expression to transform. If you want to fold a tree to a list,
you'll need to make use of the state parameter to pass around the list
you've built so far. As for the list, the Boost.Fusion library provides
a fusion::cons<>
type from which you can build heterogeneous lists. The type fusion::nil represents an empty list.

Below is a grammar that recognizes output expressions like cout_<<42<<'\n' and puts the arguments into
a Fusion list. It is explained below.

// Fold the terminals in output statements like
// "cout_ << 42 << '\n'" into a Fusion cons-list.
structFoldToList:proto::or_<// Don't add the ostream terminal to the list
proto::when<proto::terminal<std::ostream&>,proto::_state>// Put all other terminals at the head of the
// list that we're building in the "state" parameter
,proto::when<proto::terminal<_>,fusion::cons<proto::_value,proto::_state>(proto::_value,proto::_state)>// For left-shift operations, first fold the right
// child to a list using the current state. Use
// the result as the state parameter when folding
// the left child to a list.
,proto::when<proto::shift_left<FoldToList,FoldToList>,FoldToList(proto::_left,FoldToList(proto::_right,proto::_state))>>{};

Before reading on, see if you can apply what you know already about object,
callable and primitive transforms to figure out how this grammar works.

When you use the FoldToList
function, you'll need to pass two arguments: the expression to fold,
and the initial state: an empty list. Those two arguments get passed
around to each transform. We learned previously that proto::_value
is a primitive transform that accepts a terminal expression and extracts
its value. What we didn't know until now was that it also accepts the
current state and ignores it. proto::_state
is also a primitive transform. It accepts the current expression, which
it ignores, and the current state, which it returns.

When we find a terminal, we stick it at the head of the cons list, using
the current state as the tail of the list. (The first alternate causes
the ostream to be skipped.
We don't want cout in
the list.) When we find a shift-left node, we apply the following transform:

// Fold the right child and use the result as
// state while folding the right.
FoldToList(proto::_left,FoldToList(proto::_right,proto::_state))

You can read this transform as follows: using the current state, fold
the right child to a list. Use the new list as the state while folding
the left child to a list.

Tip

If your compiler is Microsoft Visual C++, you'll find that the above
transform does not compile. The compiler has bugs with its handling
of nested function types. You can work around the bug by wrapping the
inner transform in proto::call<> as follows:

proto::call<>
turns a callable transform into a primitive transform, but more on
that later.

Now that we have defined the FoldToList
function object, we can use it to turn output expressions into lists
as follows:

proto::terminal<std::ostream&>::typeconstcout_={std::cout};// This is the type of the list we build below
typedeffusion::cons<int,fusion::cons<double,fusion::cons<char,fusion::nil>>>result_type;// Fold an output expression into a Fusion list, using
// fusion::nil as the initial state of the transformation.
FoldToListto_list;result_typeargs=to_list(cout_<<1<<3.14<<'\n',fusion::nil());// Now "args" is the list: {1, 3.14, '\n'}

When writing transforms, "fold" is such a basic operation that
Proto provides a number of built-in fold transforms. We'll get to them
later. For now, rest assured that you won't always have to stretch your
brain so far to do such basic things.

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 tree
traversal technologies known collectively as “Scrap
Your Boilerplate”. In that framework, there are also
three parameters: the term, the accumulator, 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. Consider 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 character buffer, widening each character in turn using the specified
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.
structStringLength: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 proto::fold<>. 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
character 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.
structWidenCopy:proto::callable{typedefwchar_t*result_type;wchar_t*operator()(charconst*str,wchar_t*buf,std::ctype<char>const&ct)const{for(;*str;++str,++buf)*buf=ct.widen(*str);returnbuf;}};

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.
structStringCopy: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:

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<typenameExpr>voidwiden(Exprconst&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
staticstd::size_tconstlength=boost::result_of<StringLength(Expr)>::type::value;wchar_tbuffer[length+1]={L'\0'};// Get the current ctype facet
std::localeloc;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;}intmain(){widen(proto::lit("hello")+" "+"world");}

The above code displays:

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.

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:

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 written more simply as:

StringCopy(proto::_right,StringCopy(proto::_left))

The same is true for any primitive transform. The following are all equivalent:

Table 15.8. Implicit Parameters to Primitive Transforms

Equivalent Transforms

proto::when<_,StringCopy>

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 primitive 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?

For a given callable transform CT,
proto::call<CT> turns the callable transform
into a primitive transform. This is useful for disambiguating callable
transforms from object transforms, and also for working around
compiler bugs with nested function types.

For a given object transform OT,
proto::make<OT> turns the object transform
into a primitive transform. This is useful for disambiguating object
transforms from callable transforms, and also for working around
compiler bugs with nested function types.

Given a grammar G, proto::_default<G> evaluates the current node
according to the standard C++ meaning of the operation the node
represents. For instance, if the current node is a binary plus
node, the two children will both be evaluated according to G
and the results will be added and returned. The return type is
deduced with the help of the Boost.Typeof library.

Given three transforms ET,
ST, and FT,
proto::fold<ET,ST,FT> first evaluates ET
to obtain a Fusion sequence and ST
to obtain an initial state for the fold, and then evaluates FT
for each element in the sequence to generate the next state from
the previous.

Like proto::fold<ET,ST,FT>, except that the result of
the ET transform is treated
as an expression tree that is flattened to
generate the sequence to be folded. Flattening an expression tree
causes child nodes with the same tag type as the parent to be put
into sequence. For instance, a>>b>>c
would be flattened to the sequence [a,
b, c], and this is the sequence
that would be folded.

A combination of proto::make<>
and proto::call<> that is useful
when the nature of the transform depends on the expression, state
and/or data parameters. proto::lazy<R(A0,A1...An)> first evaluates proto::make<R()>
to compute a callable type R2.
Then, it evaluates proto::call<R2(A0,A1...An)>.

A Proto grammar that matches a non-terminal such as proto::plus<G0,G1>, when used as a primitive transform,
creates a new plus node where the left child is transformed according
to G0 and the right child
with G1.

Note the primitive transform associated with grammar elements such as
proto::plus<> described above.
They possess a so-called pass-through transform.
The pass-through transform accepts an expression of a certain tag type
(say, proto::tag::plus) and creates a new expression
of the same tag type, where each child expression is transformed according
to the corresponding child grammar of the pass-through transform. So
for instance this grammar ...

proto::function<X,proto::vararg<Y>>

... matches function expressions where the first child matches the X grammar and the rest match the Y grammar. When used as a transform,
the above grammar will create a new function expression where the first
child is transformed according to X
and the rest are transformed according to Y.

The following class templates in Proto can be used as grammars with pass-through
transforms:

We've seen templates such as proto::terminal<>,
proto::plus<> and proto::nary_expr<>
fill many roles. They are metafunction that generate expression types.
They are grammars that match expression types. And they are primitive
transforms. The following code samples show examples of each.

// A transform that removes all unary_plus nodes in an expression
structRemoveUnaryPlus:proto::or_<proto::when<proto::unary_plus<RemoveUnaryPlus>,RemoveUnaryPlus(proto::_child)>// Use proto::terminal<> and proto::nary_expr<>
// both as grammars and as primitive transforms.
,proto::terminal<_>,proto::nary_expr<_,proto::vararg<RemoveUnaryPlus>>>{};intmain(){proto::literal<int>i(0);proto::display_expr(+i-+(i-+i));proto::display_expr(RemoveUnaryPlus()(+i-+(i-+i)));}

The above code displays the following, which shows that unary plus nodes
have been stripped from the expression:

In previous sections, we've seen how to compose larger transforms out
of smaller transforms using function types. The smaller transforms from
which larger transforms are composed are primitive transforms,
and Proto provides a bunch of common ones such as _child0
and _value. In this section
we'll see how to author your own primitive transforms.

Note

There are a few reasons why you might want to write your own primitive
transforms. For instance, your transform may be complicated, and composing
it out of primitives becomes unwieldy. You might also need to work
around compiler bugs on legacy compilers that make composing transforms
using function types problematic. Finally, you might also decide to
define your own primitive transforms to improve compile times. Since
Proto can simply invoke a primitive transform directly without having
to process arguments or differentiate callable transforms from object
transforms, primitive transforms are more efficient.

Primitive transforms inherit from proto::transform<> and have a nested impl<>
template that inherits from proto::transform_impl<>. For example, this is how Proto
defines the _child_c<N>
transform, which returns the N-th child of
the current expression:

namespaceboost{namespaceproto{// A primitive transform that returns N-th child
// of the current expression.
template<intN>struct_child_c:transform<_child_c<N>>{template<typenameExpr,typenameState,typenameData>structimpl:transform_impl<Expr,State,Data>{typedeftypenameresult_of::child_c<Expr,N>::typeresult_type;result_typeoperator()(typenameimpl::expr_paramexpr,typenameimpl::state_paramstate,typenameimpl::data_paramdata)const{returnproto::child_c<N>(expr);}};};// Note that _child_c<N> is callable, so that
// it can be used in callable transforms, as:
// _child_c<0>(_child_c<1>)
template<intN>structis_callable<_child_c<N>>:mpl::true_{};}}

The proto::transform<>
base class provides the operator() overloads and the nested result<>
template that make your transform a valid function object. These are
implemented in terms of the nested impl<> template you define.

The proto::transform_impl<>
base class is a convenience. It provides some nested typedefs that are
generally useful. They are specified in the table below:

Table 15.11. proto::transform_impl<Expr, State, Data> typedefs

typedef

Equivalent To

expr

typenameremove_reference<Expr>::type

state

typenameremove_reference<State>::type

data

typenameremove_reference<Data>::type

expr_param

typenameadd_reference<typenameadd_const<Expr>::type>::type

state_param

typenameadd_reference<typenameadd_const<State>::type>::type

data_param

typenameadd_reference<typenameadd_const<Data>::type>::type

You'll notice that _child_c::impl::operator() takes arguments of types expr_param, state_param,
and data_param. The typedefs
make it easy to accept arguments by reference or const reference accordingly.

The only other interesting bit is the is_callable<> specialization, which will be
described in the next
section.

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 proto::when<> evaluates the transform.
proto::when<> uses the proto::is_callable<>
trait to disambiguate between the two. Proto does its best to guess whether
a type 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 be more
explicit.

For most types R, proto::is_callable<R>
checks for inheritance from proto::callable.
However, if the type R
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
object:

// Proto can't tell this defines something callable!
template<typenameT>structtimes2:proto::callable{typedefTresult_type;Toperator()(Ti)const{returni*2;}};// ERROR! This is not going to multiply the int by 2:
structIntTimes2:proto::when<proto::terminal<int>,times2<int>(proto::_value)>{};

The problem is that Proto doesn't know that times2<int> is callable, so rather that invoking
the times2<int>
function object, Proto will try to construct a times2<int> object and initialize it will an
int. That will not compile.

Note

Why can't Proto tell that times2<int> is callable? After all, 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)>. std::vector<> will not suffer to be instantiated
with _value(_child1)
as a template parameter. Since merely asking the question will sometimes
result in a hard error, Proto can't ask; it has to assume that X<Y>
represents an object to construct and not a function to call.

There are a couple of solutions to the times2<int> problem. One solution is to wrap
the transform in proto::call<>. This forces Proto to treat
times2<int>
as callable:

This works because now Proto can tell that times2int
inherits (indirectly) from proto::callable.
Any non-template types can be safely checked for inheritance because,
as they are not templates, there is no worry about instantiation errors.

There is one last way to tell Proto that times2<> is callable. You could add an
extra dummy template parameter that defaults to proto::callable:

// Proto will recognize this as callable
template<typenameT,typenameCallable=proto::callable>structtimes2:proto::callable{typedefTresult_type;Toperator()(Ti)const{returni*2;}};// OK, this works!
structIntTimes2:proto::when<proto::terminal<int>,times2<int>(proto::_value)>{};

Note that in addition to the extra template parameter, times2<>
still inherits from proto::callable.
That's not necessary in this example but it is good style because any
types derived from times2<> (as times2int
defined above) will still be considered callable.

An extension of the Calc2 example that uses a Proto transform to calculate
the arity of a calculator expression and statically assert that the correct
number of arguments are passed.

// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example enhances the arithmetic expression evaluator
// in calc2.cpp by using a proto transform to calculate the
// number of arguments an expression requires and using a
// compile-time assert to guarantee that the right number of
// arguments are actually specified.
#include<iostream>#include<boost/mpl/int.hpp>#include<boost/mpl/assert.hpp>#include<boost/mpl/min_max.hpp>#include<boost/proto/core.hpp>#include<boost/proto/context.hpp>#include<boost/proto/transform.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;usingproto::_;// Will be used to define the placeholders _1 and _2
template<typenameI>structplaceholder:I{};// This grammar basically says that a calculator expression is one of:
// - A placeholder terminal
// - Some other terminal
// - Some non-terminal whose children are calculator expressions
// In addition, it has transforms that say how to calculate the
// expression arity for each of the three cases.
structCalculatorGrammar:proto::or_<// placeholders have a non-zero arity ...
proto::when<proto::terminal<placeholder<_>>,proto::_value>// Any other terminals have arity 0 ...
,proto::when<proto::terminal<_>,mpl::int_<0>()>// For any non-terminals, find the arity of the children and
// take the maximum. This is recursive.
,proto::when<proto::nary_expr<_,proto::vararg<_>>,proto::fold<_,mpl::int_<0>(),mpl::max<CalculatorGrammar,proto::_state>()>>>{};// Simple wrapper for calculating a calculator expression's arity.
// It specifies mpl::int_<0> as the initial state. The data, which
// is not used, is mpl::void_.
template<typenameExpr>structcalculator_arity:boost::result_of<CalculatorGrammar(Expr,mpl::int_<0>,mpl::void_)>{};// For expressions in the calculator domain, operator ()
// will be special; it will evaluate the expression.
structcalculator_domain;// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp and calc2.cpp)
structcalculator_context:proto::callable_context<calculator_contextconst>{// The values bound to the placeholders
doubled[2];// The result of evaluating arithmetic expressions
typedefdoubleresult_type;explicitcalculator_context(doubled1=0.,doubled2=0.){d[0]=d1;d[1]=d2;}// Handle the evaluation of the placeholder terminals
template<typenameI>doubleoperator()(proto::tag::terminal,placeholder<I>)const{returnd[I()-1];}};// Wrap all calculator expressions in this type, which defines
// operator () to evaluate the expression.
template<typenameExpr>structcalculator_expression:proto::extends<Expr,calculator_expression<Expr>,calculator_domain>{typedefproto::extends<Expr,calculator_expression<Expr>,calculator_domain>base_type;explicitcalculator_expression(Exprconst&expr=Expr()):base_type(expr){}BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression)// Override operator () to evaluate the expression
doubleoperator()()const{// Assert that the expression has arity 0
BOOST_MPL_ASSERT_RELATION(0,==,calculator_arity<Expr>::type::value);calculator_contextconstctx;returnproto::eval(*this,ctx);}doubleoperator()(doubled1)const{// Assert that the expression has arity 1
BOOST_MPL_ASSERT_RELATION(1,==,calculator_arity<Expr>::type::value);calculator_contextconstctx(d1);returnproto::eval(*this,ctx);}doubleoperator()(doubled1,doubled2)const{// Assert that the expression has arity 2
BOOST_MPL_ASSERT_RELATION(2,==,calculator_arity<Expr>::type::value);calculator_contextconstctx(d1,d2);returnproto::eval(*this,ctx);}};// Tell proto how to generate expressions in the calculator_domain
structcalculator_domain:proto::domain<proto::generator<calculator_expression>>{};// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression<proto::terminal<placeholder<mpl::int_<1>>>::type>const_1;calculator_expression<proto::terminal<placeholder<mpl::int_<2>>>::type>const_2;// Now, our arithmetic expressions are immediately executable function objects:
intmain(){// Displays "5"
std::cout<<(_1+2.0)(3.0)<<std::endl;// Displays "6"
std::cout<<(_1*_2)(3.0,2.0)<<std::endl;// Displays "0.5"
std::cout<<((_1-_2)/_2)(3.0,2.0)<<std::endl;// This won't compile because the arity of the
// expression doesn't match the number of arguments
// ( (_1 - _2) / _2 )( 3.0 );
return0;}

This example constructs a mini-library for linear algebra, using expression
templates to eliminate the need for temporaries when adding vectors of
numbers.

This example uses a domain with a grammar to prune the set of overloaded
operators. Only those operators that produce valid lazy vector expressions
are allowed.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example constructs a mini-library for linear algebra, using
// expression templates to eliminate the need for temporaries when
// adding vectors of numbers.
//
// This example uses a domain with a grammar to prune the set
// of overloaded operators. Only those operators that produce
// valid lazy vector expressions are allowed.
#include<vector>#include<iostream>#include<boost/mpl/int.hpp>#include<boost/proto/core.hpp>#include<boost/proto/context.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;usingproto::_;// This grammar describes which lazy vector expressions
// are allowed; namely, vector terminals and addition
// and subtraction of lazy vector expressions.
structLazyVectorGrammar:proto::or_<proto::terminal<std::vector<_>>,proto::plus<LazyVectorGrammar,LazyVectorGrammar>,proto::minus<LazyVectorGrammar,LazyVectorGrammar>>{};// Expressions in the lazy vector domain must conform
// to the lazy vector grammar
structlazy_vector_domain;// Here is an evaluation context that indexes into a lazy vector
// expression, and combines the result.
template<typenameSize=std::size_t>structlazy_subscript_context{lazy_subscript_context(Sizesubscript):subscript_(subscript){}// Use default_eval for all the operations ...
template<typenameExpr,typenameTag=typenameExpr::proto_tag>structeval:proto::default_eval<Expr,lazy_subscript_context>{};// ... except for terminals, which we index with our subscript
template<typenameExpr>structeval<Expr,proto::tag::terminal>{typedeftypenameproto::result_of::value<Expr>::type::value_typeresult_type;result_typeoperator()(Exprconst&expr,lazy_subscript_context&ctx)const{returnproto::value(expr)[ctx.subscript_];}};Sizesubscript_;};// Here is the domain-specific expression wrapper, which overrides
// operator [] to evaluate the expression using the lazy_subscript_context.
template<typenameExpr>structlazy_vector_expr:proto::extends<Expr,lazy_vector_expr<Expr>,lazy_vector_domain>{typedefproto::extends<Expr,lazy_vector_expr<Expr>,lazy_vector_domain>base_type;lazy_vector_expr(Exprconst&expr=Expr()):base_type(expr){}// Use the lazy_subscript_context<> to implement subscripting
// of a lazy vector expression tree.
template<typenameSize>typenameproto::result_of::eval<Expr,lazy_subscript_context<Size>>::typeoperator[](Sizesubscript)const{lazy_subscript_context<Size>ctx(subscript);returnproto::eval(*this,ctx);}};// Here is our lazy_vector terminal, implemented in terms of lazy_vector_expr
template<typenameT>structlazy_vector:lazy_vector_expr<typenameproto::terminal<std::vector<T>>::type>{typedeftypenameproto::terminal<std::vector<T>>::typeexpr_type;lazy_vector(std::size_tsize=0,Tconst&value=T()):lazy_vector_expr<expr_type>(expr_type::make(std::vector<T>(size,value))){}// Here we define a += operator for lazy vector terminals that
// takes a lazy vector expression and indexes it. expr[i] here
// uses lazy_subscript_context<> under the covers.
template<typenameExpr>lazy_vector&operator+=(Exprconst&expr){std::size_tsize=proto::value(*this).size();for(std::size_ti=0;i<size;++i){proto::value(*this)[i]+=expr[i];}return*this;}};// Tell proto that in the lazy_vector_domain, all
// expressions should be wrapped in laxy_vector_expr<>
structlazy_vector_domain:proto::domain<proto::generator<lazy_vector_expr>,LazyVectorGrammar>{};intmain(){// lazy_vectors with 4 elements each.
lazy_vector<double>v1(4,1.0),v2(4,2.0),v3(4,3.0);// Add two vectors lazily and get the 2nd element.
doubled1=(v2+v3)[2];// Look ma, no temporaries!
std::cout<<d1<<std::endl;// Subtract two vectors and add the result to a third vector.
v1+=v2-v3;// Still no temporaries!
std::cout<<'{'<<v1[0]<<','<<v1[1]<<','<<v1[2]<<','<<v1[3]<<'}'<<std::endl;// This expression is disallowed because it does not conform
// to the LazyVectorGrammar
//(v2 + v3) += v1;
return0;}

This is a simple example of doing arbitrary type manipulations with Proto
transforms. It takes some expression involving primary colors and combines
the colors according to arbitrary rules. It is a port of the RGB example
from PETE.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is a simple example of doing arbitrary type manipulations with proto
// transforms. It takes some expression involving primary colors and combines
// the colors according to arbitrary rules. It is a port of the RGB example
// from PETE (http://www.codesourcery.com/pooma/download.html).
#include<iostream>#include<boost/proto/core.hpp>#include<boost/proto/transform.hpp>namespaceproto=boost::proto;structRedTag{friendstd::ostream&operator<<(std::ostream&sout,RedTag){returnsout<<"This expression is red.";}};structBlueTag{friendstd::ostream&operator<<(std::ostream&sout,BlueTag){returnsout<<"This expression is blue.";}};structGreenTag{friendstd::ostream&operator<<(std::ostream&sout,GreenTag){returnsout<<"This expression is green.";}};typedefproto::terminal<RedTag>::typeRedT;typedefproto::terminal<BlueTag>::typeBlueT;typedefproto::terminal<GreenTag>::typeGreenT;structRed;structBlue;structGreen;///////////////////////////////////////////////////////////////////////////////
// A transform that produces new colors according to some arbitrary rules:
// red & green give blue, red & blue give green, blue and green give red.
structRed:proto::or_<proto::plus<Green,Blue>,proto::plus<Blue,Green>,proto::plus<Red,Red>,proto::terminal<RedTag>>{};structGreen:proto::or_<proto::plus<Red,Blue>,proto::plus<Blue,Red>,proto::plus<Green,Green>,proto::terminal<GreenTag>>{};structBlue:proto::or_<proto::plus<Red,Green>,proto::plus<Green,Red>,proto::plus<Blue,Blue>,proto::terminal<BlueTag>>{};structRGB:proto::or_<proto::when<Red,RedTag()>,proto::when<Blue,BlueTag()>,proto::when<Green,GreenTag()>>{};template<typenameExpr>voidprintColor(Exprconst&expr){inti=0;// dummy state and data parameter, not used
std::cout<<RGB()(expr,i,i)<<std::endl;}intmain(){printColor(RedT()+GreenT());printColor(RedT()+GreenT()+BlueT());printColor(RedT()+(GreenT()+BlueT()));return0;}

This example constructs a mini-library for linear algebra, using expression
templates to eliminate the need for temporaries when adding arrays of numbers.
It duplicates the TArray example from PETE.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example constructs a mini-library for linear algebra, using
// expression templates to eliminate the need for temporaries when
// adding arrays of numbers. It duplicates the TArray example from
// PETE (http://www.codesourcery.com/pooma/download.html)
#include<iostream>#include<boost/mpl/int.hpp>#include<boost/proto/core.hpp>#include<boost/proto/context.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;usingproto::_;// This grammar describes which TArray expressions
// are allowed; namely, int and array terminals
// plus, minus, multiplies and divides of TArray expressions.
structTArrayGrammar:proto::or_<proto::terminal<int>,proto::terminal<int[3]>,proto::plus<TArrayGrammar,TArrayGrammar>,proto::minus<TArrayGrammar,TArrayGrammar>,proto::multiplies<TArrayGrammar,TArrayGrammar>,proto::divides<TArrayGrammar,TArrayGrammar>>{};template<typenameExpr>structTArrayExpr;// Tell proto that in the TArrayDomain, all
// expressions should be wrapped in TArrayExpr<> and
// must conform to the TArrayGrammar
structTArrayDomain:proto::domain<proto::generator<TArrayExpr>,TArrayGrammar>{};// Here is an evaluation context that indexes into a TArray
// expression, and combines the result.
structTArraySubscriptCtx:proto::callable_context<TArraySubscriptCtxconst>{typedefintresult_type;TArraySubscriptCtx(std::ptrdiff_ti):i_(i){}// Index array terminals with our subscript. Everything
// else will be handled by the default evaluation context.
intoperator()(proto::tag::terminal,intconst(&data)[3])const{returndata[this->i_];}std::ptrdiff_ti_;};// Here is an evaluation context that prints a TArray expression.
structTArrayPrintCtx:proto::callable_context<TArrayPrintCtxconst>{typedefstd::ostream&result_type;TArrayPrintCtx(){}std::ostream&operator()(proto::tag::terminal,inti)const{returnstd::cout<<i;}std::ostream&operator()(proto::tag::terminal,intconst(&arr)[3])const{returnstd::cout<<'{'<<arr[0]<<", "<<arr[1]<<", "<<arr[2]<<'}';}template<typenameL,typenameR>std::ostream&operator()(proto::tag::plus,Lconst&l,Rconst&r)const{returnstd::cout<<'('<<l<<" + "<<r<<')';}template<typenameL,typenameR>std::ostream&operator()(proto::tag::minus,Lconst&l,Rconst&r)const{returnstd::cout<<'('<<l<<" - "<<r<<')';}template<typenameL,typenameR>std::ostream&operator()(proto::tag::multiplies,Lconst&l,Rconst&r)const{returnstd::cout<<l<<" * "<<r;}template<typenameL,typenameR>std::ostream&operator()(proto::tag::divides,Lconst&l,Rconst&r)const{returnstd::cout<<l<<" / "<<r;}};// Here is the domain-specific expression wrapper, which overrides
// operator [] to evaluate the expression using the TArraySubscriptCtx.
template<typenameExpr>structTArrayExpr:proto::extends<Expr,TArrayExpr<Expr>,TArrayDomain>{typedefproto::extends<Expr,TArrayExpr<Expr>,TArrayDomain>base_type;TArrayExpr(Exprconst&expr=Expr()):base_type(expr){}// Use the TArraySubscriptCtx to implement subscripting
// of a TArray expression tree.
intoperator[](std::ptrdiff_ti)const{TArraySubscriptCtxconstctx(i);returnproto::eval(*this,ctx);}// Use the TArrayPrintCtx to display a TArray expression tree.
friendstd::ostream&operator<<(std::ostream&sout,TArrayExpr<Expr>const&expr){TArrayPrintCtxconstctx;returnproto::eval(expr,ctx);}};// Here is our TArray terminal, implemented in terms of TArrayExpr
// It is basically just an array of 3 integers.
structTArray:TArrayExpr<proto::terminal<int[3]>::type>{explicitTArray(inti=0,intj=0,intk=0){(*this)[0]=i;(*this)[1]=j;(*this)[2]=k;}// Here we override operator [] to give read/write access to
// the elements of the array. (We could use the TArrayExpr
// operator [] if we made the subscript context smarter about
// returning non-const reference when appropriate.)
int&operator[](std::ptrdiff_ti){returnproto::value(*this)[i];}intconst&operator[](std::ptrdiff_ti)const{returnproto::value(*this)[i];}// Here we define a operator = for TArray terminals that
// takes a TArray expression.
template<typenameExpr>TArray&operator=(Exprconst&expr){// proto::as_expr<TArrayDomain>(expr) is the same as
// expr unless expr is an integer, in which case it
// is made into a TArrayExpr terminal first.
returnthis->assign(proto::as_expr<TArrayDomain>(expr));}template<typenameExpr>TArray&printAssign(Exprconst&expr){*this=expr;std::cout<<*this<<" = "<<expr<<std::endl;return*this;}private:template<typenameExpr>TArray&assign(Exprconst&expr){// expr[i] here uses TArraySubscriptCtx under the covers.
(*this)[0]=expr[0];(*this)[1]=expr[1];(*this)[2]=expr[2];return*this;}};intmain(){TArraya(3,1,2);TArrayb;std::cout<<a<<std::endl;std::cout<<b<<std::endl;b[0]=7;b[1]=33;b[2]=-99;TArrayc(a);std::cout<<c<<std::endl;a=0;std::cout<<a<<std::endl;std::cout<<b<<std::endl;std::cout<<c<<std::endl;a=b+c;std::cout<<a<<std::endl;a.printAssign(b+c*(b+3*c));return0;}

This is a simple example using proto::extends<> to extend a terminal type with
additional behaviors, and using custom contexts and proto::eval() for evaluating expressions. It is a port
of the Vec3 example from PETE.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is a simple example using proto::extends to extend a terminal type with
// additional behaviors, and using custom contexts and proto::eval for
// evaluating expressions. It is a port of the Vec3 example
// from PETE (http://www.codesourcery.com/pooma/download.html).
#include<iostream>#include<functional>#include<boost/assert.hpp>#include<boost/mpl/int.hpp>#include<boost/proto/core.hpp>#include<boost/proto/context.hpp>#include<boost/proto/proto_typeof.hpp>#include<boost/proto/transform.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;usingproto::_;// Here is an evaluation context that indexes into a Vec3
// expression, and combines the result.
structVec3SubscriptCtx:proto::callable_context<Vec3SubscriptCtxconst>{typedefintresult_type;Vec3SubscriptCtx(inti):i_(i){}// Index array terminals with our subscript. Everything
// else will be handled by the default evaluation context.
intoperator()(proto::tag::terminal,intconst(&arr)[3])const{returnarr[this->i_];}inti_;};// Here is an evaluation context that counts the number
// of Vec3 terminals in an expression.
structCountLeavesCtx:proto::callable_context<CountLeavesCtx,proto::null_context>{CountLeavesCtx():count(0){}typedefvoidresult_type;voidoperator()(proto::tag::terminal,intconst(&)[3]){++this->count;}intcount;};structiplus:std::plus<int>,proto::callable{};// Here is a transform that does the same thing as the above context.
// It demonstrates the use of the std::plus<> function object
// with the fold transform. With minor modifications, this
// transform could be used to calculate the leaf count at compile
// time, rather than at runtime.
structCountLeaves:proto::or_<// match a Vec3 terminal, return 1
proto::when<proto::terminal<int[3]>,mpl::int_<1>()>// match a terminal, return int() (which is 0)
,proto::when<proto::terminal<_>,int()>// fold everything else, using std::plus<> to add
// the leaf count of each child to the accumulated state.
,proto::otherwise<proto::fold<_,int(),iplus(CountLeaves,proto::_state)>>>{};// Here is the Vec3 struct, which is a vector of 3 integers.
structVec3:proto::extends<proto::terminal<int[3]>::type,Vec3>{explicitVec3(inti=0,intj=0,intk=0){(*this)[0]=i;(*this)[1]=j;(*this)[2]=k;}int&operator[](inti){returnproto::value(*this)[i];}intconst&operator[](inti)const{returnproto::value(*this)[i];}// Here we define a operator = for Vec3 terminals that
// takes a Vec3 expression.
template<typenameExpr>Vec3&operator=(Exprconst&expr){typedefVec3SubscriptCtxconstCVec3SubscriptCtx;(*this)[0]=proto::eval(proto::as_expr(expr),CVec3SubscriptCtx(0));(*this)[1]=proto::eval(proto::as_expr(expr),CVec3SubscriptCtx(1));(*this)[2]=proto::eval(proto::as_expr(expr),CVec3SubscriptCtx(2));return*this;}voidprint()const{std::cout<<'{'<<(*this)[0]<<", "<<(*this)[1]<<", "<<(*this)[2]<<'}'<<std::endl;}};// The count_leaves() function uses the CountLeaves transform and
// to count the number of leaves in an expression.
template<typenameExpr>intcount_leaves(Exprconst&expr){// Count the number of Vec3 terminals using the
// CountLeavesCtx evaluation context.
CountLeavesCtxctx;proto::eval(expr,ctx);// This is another way to count the leaves using a transform.
inti=0;BOOST_ASSERT(CountLeaves()(expr,i,i)==ctx.count);returnctx.count;}intmain(){Vec3a,b,c;c=4;b[0]=-1;b[1]=-2;b[2]=-3;a=b+c;a.print();Vec3d;BOOST_PROTO_AUTO(expr1,b+c);d=expr1;d.print();intnum=count_leaves(expr1);std::cout<<num<<std::endl;BOOST_PROTO_AUTO(expr2,b+3*c);num=count_leaves(expr2);std::cout<<num<<std::endl;BOOST_PROTO_AUTO(expr3,b+c*d);num=count_leaves(expr3);std::cout<<num<<std::endl;return0;}

This is an example of using BOOST_PROTO_DEFINE_OPERATORS() to Protofy expressions using std::vector<>,
a non-Proto type. It is a port of the Vector example from PETE.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
// expressions using std::vector<>, a non-proto type. It is a port of the
// Vector example from PETE (http://www.codesourcery.com/pooma/download.html).
#include<vector>#include<iostream>#include<stdexcept>#include<boost/mpl/bool.hpp>#include<boost/proto/core.hpp>#include<boost/proto/debug.hpp>#include<boost/proto/context.hpp>#include<boost/utility/enable_if.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;usingproto::_;template<typenameExpr>structVectorExpr;// Here is an evaluation context that indexes into a std::vector
// expression and combines the result.
structVectorSubscriptCtx{VectorSubscriptCtx(std::size_ti):i_(i){}// Unless this is a vector terminal, use the
// default evaluation context
template<typenameExpr,typenameEnableIf=void>structeval:proto::default_eval<Expr,VectorSubscriptCtxconst>{};// Index vector terminals with our subscript.
template<typenameExpr>structeval<Expr,typenameboost::enable_if<proto::matches<Expr,proto::terminal<std::vector<_,_>>>>::type>{typedeftypenameproto::result_of::value<Expr>::type::value_typeresult_type;result_typeoperator()(Expr&expr,VectorSubscriptCtxconst&ctx)const{returnproto::value(expr)[ctx.i_];}};std::size_ti_;};// Here is an evaluation context that verifies that all the
// vectors in an expression have the same size.
structVectorSizeCtx{VectorSizeCtx(std::size_tsize):size_(size){}// Unless this is a vector terminal, use the
// null evaluation context
template<typenameExpr,typenameEnableIf=void>structeval:proto::null_eval<Expr,VectorSizeCtxconst>{};// Index array terminals with our subscript. Everything
// else will be handled by the default evaluation context.
template<typenameExpr>structeval<Expr,typenameboost::enable_if<proto::matches<Expr,proto::terminal<std::vector<_,_>>>>::type>{typedefvoidresult_type;result_typeoperator()(Expr&expr,VectorSizeCtxconst&ctx)const{if(ctx.size_!=proto::value(expr).size()){throwstd::runtime_error("LHS and RHS are not compatible");}}};std::size_tsize_;};// A grammar which matches all the assignment operators,
// so we can easily disable them.
structAssignOps:proto::switch_<structAssignOpsCases>{};// Here are the cases used by the switch_ above.
structAssignOpsCases{template<typenameTag,intD=0>structcase_:proto::not_<_>{};template<intD>structcase_<proto::tag::plus_assign,D>:_{};template<intD>structcase_<proto::tag::minus_assign,D>:_{};template<intD>structcase_<proto::tag::multiplies_assign,D>:_{};template<intD>structcase_<proto::tag::divides_assign,D>:_{};template<intD>structcase_<proto::tag::modulus_assign,D>:_{};template<intD>structcase_<proto::tag::shift_left_assign,D>:_{};template<intD>structcase_<proto::tag::shift_right_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_and_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_or_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_xor_assign,D>:_{};};// A vector grammar is a terminal or some op that is not an
// assignment op. (Assignment will be handled specially.)
structVectorGrammar:proto::or_<proto::terminal<_>,proto::and_<proto::nary_expr<_,proto::vararg<VectorGrammar>>,proto::not_<AssignOps>>>{};// Expressions in the vector domain will be wrapped in VectorExpr<>
// and must conform to the VectorGrammar
structVectorDomain:proto::domain<proto::generator<VectorExpr>,VectorGrammar>{};// Here is VectorExpr, which extends a proto expr type by
// giving it an operator [] which uses the VectorSubscriptCtx
// to evaluate an expression with a given index.
template<typenameExpr>structVectorExpr:proto::extends<Expr,VectorExpr<Expr>,VectorDomain>{explicitVectorExpr(Exprconst&expr):proto::extends<Expr,VectorExpr<Expr>,VectorDomain>(expr){}// Use the VectorSubscriptCtx to implement subscripting
// of a Vector expression tree.
typenameproto::result_of::eval<Exprconst,VectorSubscriptCtxconst>::typeoperator[](std::size_ti)const{VectorSubscriptCtxconstctx(i);returnproto::eval(*this,ctx);}};// Define a trait type for detecting vector terminals, to
// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
template<typenameT>structIsVector:mpl::false_{};template<typenameT,typenameA>structIsVector<std::vector<T,A>>:mpl::true_{};namespaceVectorOps{// This defines all the overloads to make expressions involving
// std::vector to build expression templates.
BOOST_PROTO_DEFINE_OPERATORS(IsVector,VectorDomain)typedefVectorSubscriptCtxconstCVectorSubscriptCtx;// Assign to a vector from some expression.
template<typenameT,typenameA,typenameExpr>std::vector<T,A>&assign(std::vector<T,A>&arr,Exprconst&expr){VectorSizeCtxconstsize(arr.size());proto::eval(proto::as_expr<VectorDomain>(expr),size);// will throw if the sizes don't match
for(std::size_ti=0;i<arr.size();++i){arr[i]=proto::as_expr<VectorDomain>(expr)[i];}returnarr;}// Add-assign to a vector from some expression.
template<typenameT,typenameA,typenameExpr>std::vector<T,A>&operator+=(std::vector<T,A>&arr,Exprconst&expr){VectorSizeCtxconstsize(arr.size());proto::eval(proto::as_expr<VectorDomain>(expr),size);// will throw if the sizes don't match
for(std::size_ti=0;i<arr.size();++i){arr[i]+=proto::as_expr<VectorDomain>(expr)[i];}returnarr;}}intmain(){usingnamespaceVectorOps;inti;constintn=10;std::vector<int>a,b,c,d;std::vector<double>e(n);for(i=0;i<n;++i){a.push_back(i);b.push_back(2*i);c.push_back(3*i);d.push_back(i);}VectorOps::assign(b,2);VectorOps::assign(d,a+b*c);a+=if_else(d<30,b,c);VectorOps::assign(e,c);e+=e-4/(c+1);for(i=0;i<n;++i){std::cout<<" a("<<i<<") = "<<a[i]<<" b("<<i<<") = "<<b[i]<<" c("<<i<<") = "<<c[i]<<" d("<<i<<") = "<<d[i]<<" e("<<i<<") = "<<e[i]<<std::endl;}}

This is an example of using BOOST_PROTO_DEFINE_OPERATORS() to Protofy expressions using std::vector<>
and std::list<>,
non-Proto types. It is a port of the Mixed example from PETE.

///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
// expressions using std::vector<> and std::list, non-proto types. It is a port
// of the Mixed example from PETE.
// (http://www.codesourcery.com/pooma/download.html).
#include<list>#include<cmath>#include<vector>#include<complex>#include<iostream>#include<stdexcept>#include<boost/proto/core.hpp>#include<boost/proto/debug.hpp>#include<boost/proto/context.hpp>#include<boost/proto/transform.hpp>#include<boost/utility/enable_if.hpp>#include<boost/typeof/std/list.hpp>#include<boost/typeof/std/vector.hpp>#include<boost/typeof/std/complex.hpp>#include<boost/type_traits/remove_reference.hpp>namespaceproto=boost::proto;namespacempl=boost::mpl;usingproto::_;template<typenameExpr>structMixedExpr;template<typenameIter>structiterator_wrapper{typedefIteriterator;explicititerator_wrapper(Iteriter):it(iter){}Iterit;};structbegin:proto::callable{template<classSig>structresult;template<classThis,classCont>structresult<This(Cont)>:proto::result_of::as_expr<iterator_wrapper<typenameboost::remove_reference<Cont>::type::const_iterator>>{};template<typenameCont>typenameresult<begin(Contconst&)>::typeoperator()(Contconst&cont)const{iterator_wrapper<typenameCont::const_iterator>it(cont.begin());returnproto::as_expr(it);}};// Here is a grammar that replaces vector and list terminals with their
// begin iterators
structBegin:proto::or_<proto::when<proto::terminal<std::vector<_,_>>,begin(proto::_value)>,proto::when<proto::terminal<std::list<_,_>>,begin(proto::_value)>,proto::when<proto::terminal<_>>,proto::when<proto::nary_expr<_,proto::vararg<Begin>>>>{};// Here is an evaluation context that dereferences iterator
// terminals.
structDereferenceCtx{// Unless this is an iterator terminal, use the
// default evaluation context
template<typenameExpr,typenameEnableIf=void>structeval:proto::default_eval<Expr,DereferenceCtxconst>{};// Dereference iterator terminals.
template<typenameExpr>structeval<Expr,typenameboost::enable_if<proto::matches<Expr,proto::terminal<iterator_wrapper<_>>>>::type>{typedeftypenameproto::result_of::value<Expr>::typeIteratorWrapper;typedeftypenameIteratorWrapper::iteratoriterator;typedeftypenamestd::iterator_traits<iterator>::referenceresult_type;result_typeoperator()(Expr&expr,DereferenceCtxconst&)const{return*proto::value(expr).it;}};};// Here is an evaluation context that increments iterator
// terminals.
structIncrementCtx{// Unless this is an iterator terminal, use the
// default evaluation context
template<typenameExpr,typenameEnableIf=void>structeval:proto::null_eval<Expr,IncrementCtxconst>{};// advance iterator terminals.
template<typenameExpr>structeval<Expr,typenameboost::enable_if<proto::matches<Expr,proto::terminal<iterator_wrapper<_>>>>::type>{typedefvoidresult_type;result_typeoperator()(Expr&expr,IncrementCtxconst&)const{++proto::value(expr).it;}};};// A grammar which matches all the assignment operators,
// so we can easily disable them.
structAssignOps:proto::switch_<structAssignOpsCases>{};// Here are the cases used by the switch_ above.
structAssignOpsCases{template<typenameTag,intD=0>structcase_:proto::not_<_>{};template<intD>structcase_<proto::tag::plus_assign,D>:_{};template<intD>structcase_<proto::tag::minus_assign,D>:_{};template<intD>structcase_<proto::tag::multiplies_assign,D>:_{};template<intD>structcase_<proto::tag::divides_assign,D>:_{};template<intD>structcase_<proto::tag::modulus_assign,D>:_{};template<intD>structcase_<proto::tag::shift_left_assign,D>:_{};template<intD>structcase_<proto::tag::shift_right_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_and_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_or_assign,D>:_{};template<intD>structcase_<proto::tag::bitwise_xor_assign,D>:_{};};// An expression conforms to the MixedGrammar if it is a terminal or some
// op that is not an assignment op. (Assignment will be handled specially.)
structMixedGrammar:proto::or_<proto::terminal<_>,proto::and_<proto::nary_expr<_,proto::vararg<MixedGrammar>>,proto::not_<AssignOps>>>{};// Expressions in the MixedDomain will be wrapped in MixedExpr<>
// and must conform to the MixedGrammar
structMixedDomain:proto::domain<proto::generator<MixedExpr>,MixedGrammar>{};// Here is MixedExpr, a wrapper for expression types in the MixedDomain.
template<typenameExpr>structMixedExpr:proto::extends<Expr,MixedExpr<Expr>,MixedDomain>{explicitMixedExpr(Exprconst&expr):proto::extends<Expr,MixedExpr<Expr>,MixedDomain>(expr){}private:// hide this:
usingproto::extends<Expr,MixedExpr<Expr>,MixedDomain>::operator[];};// Define a trait type for detecting vector and list terminals, to
// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
template<typenameT>structIsMixed:mpl::false_{};template<typenameT,typenameA>structIsMixed<std::list<T,A>>:mpl::true_{};template<typenameT,typenameA>structIsMixed<std::vector<T,A>>:mpl::true_{};namespaceMixedOps{// This defines all the overloads to make expressions involving
// std::vector to build expression templates.
BOOST_PROTO_DEFINE_OPERATORS(IsMixed,MixedDomain)structassign_op{template<typenameT,typenameU>voidoperator()(T&t,Uconst&u)const{t=u;}};structplus_assign_op{template<typenameT,typenameU>voidoperator()(T&t,Uconst&u)const{t+=u;}};structminus_assign_op{template<typenameT,typenameU>voidoperator()(T&t,Uconst&u)const{t-=u;}};structsin_{template<typenameSig>structresult;template<typenameThis,typenameArg>structresult<This(Arg)>:boost::remove_const<typenameboost::remove_reference<Arg>::type>{};template<typenameArg>Argoperator()(Argconst&a)const{returnstd::sin(a);}};template<typenameA>typenameproto::result_of::make_expr<proto::tag::function,MixedDomain,sin_const,Aconst&>::typesin(Aconst&a){returnproto::make_expr<proto::tag::function,MixedDomain>(sin_(),boost::ref(a));}template<typenameFwdIter,typenameExpr,typenameOp>voidevaluate(FwdIterbegin,FwdIterend,Exprconst&expr,Opop){IncrementCtxconstinc={};DereferenceCtxconstderef={};typenameboost::result_of<Begin(Exprconst&)>::typeexpr2=Begin()(expr);for(;begin!=end;++begin){op(*begin,proto::eval(expr2,deref));proto::eval(expr2,inc);}}// Add-assign to a vector from some expression.
template<typenameT,typenameA,typenameExpr>std::vector<T,A>&assign(std::vector<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),assign_op());returnarr;}// Add-assign to a list from some expression.
template<typenameT,typenameA,typenameExpr>std::list<T,A>&assign(std::list<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),assign_op());returnarr;}// Add-assign to a vector from some expression.
template<typenameT,typenameA,typenameExpr>std::vector<T,A>&operator+=(std::vector<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),plus_assign_op());returnarr;}// Add-assign to a list from some expression.
template<typenameT,typenameA,typenameExpr>std::list<T,A>&operator+=(std::list<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),plus_assign_op());returnarr;}// Minus-assign to a vector from some expression.
template<typenameT,typenameA,typenameExpr>std::vector<T,A>&operator-=(std::vector<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),minus_assign_op());returnarr;}// Minus-assign to a list from some expression.
template<typenameT,typenameA,typenameExpr>std::list<T,A>&operator-=(std::list<T,A>&arr,Exprconst&expr){evaluate(arr.begin(),arr.end(),proto::as_expr<MixedDomain>(expr),minus_assign_op());returnarr;}}intmain(){usingnamespaceMixedOps;intn=10;std::vector<int>a,b,c,d;std::list<double>e;std::list<std::complex<double>>f;inti;for(i=0;i<n;++i){a.push_back(i);b.push_back(2*i);c.push_back(3*i);d.push_back(i);e.push_back(0.0);f.push_back(std::complex<double>(1.0,1.0));}MixedOps::assign(b,2);MixedOps::assign(d,a+b*c);a+=if_else(d<30,b,c);MixedOps::assign(e,c);e+=e-4/(c+1);f-=sin(0.1*e*std::complex<double>(0.2,1.2));std::list<double>::const_iteratorei=e.begin();std::list<std::complex<double>>::const_iteratorfi=f.begin();for(i=0;i<n;++i){std::cout<<"a("<<i<<") = "<<a[i]<<" b("<<i<<") = "<<b[i]<<" c("<<i<<") = "<<c[i]<<" d("<<i<<") = "<<d[i]<<" e("<<i<<") = "<<*ei++<<" f("<<i<<") = "<<*fi++<<std::endl;}}

A demonstration of how to implement map_list_of() from the Boost.Assign library using Proto.
map_list_assign()
is used to conveniently initialize a std::map<>. By using Proto, we can avoid any
dynamic allocation while building the intermediate representation.

// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is a port of map_list_of() from the Boost.Assign library.
// It has the advantage of being more efficient at runtime by not
// building any temporary container that requires dynamic allocation.
#include<map>#include<string>#include<iostream>#include<boost/proto/core.hpp>#include<boost/proto/transform.hpp>#include<boost/type_traits/add_reference.hpp>namespaceproto=boost::proto;usingproto::_;structmap_list_of_tag{};// A simple callable function object that inserts a
// (key,value) pair into a map.
structinsert:proto::callable{template<typenameSig>structresult;template<typenameThis,typenameMap,typenameKey,typenameValue>structresult<This(Map,Key,Value)>:boost::add_reference<Map>{};template<typenameMap,typenameKey,typenameValue>Map&operator()(Map&map,Keyconst&key,Valueconst&value)const{map.insert(typenameMap::value_type(key,value));returnmap;}};// Work-arounds for Microsoft Visual C++ 7.1
#ifBOOST_WORKAROUND(BOOST_MSVC,==1310)#defineMapListOf(x)proto::call<MapListOf(x)>#define_value(x)call<proto::_value(x)>#endif// The grammar for valid map-list expressions, and a
// transform that populates the map.
structMapListOf:proto::or_<proto::when<proto::function<proto::terminal<map_list_of_tag>,proto::terminal<_>,proto::terminal<_>>,insert(proto::_data,proto::_value(proto::_child1),proto::_value(proto::_child2))>,proto::when<proto::function<MapListOf,proto::terminal<_>,proto::terminal<_>>,insert(MapListOf(proto::_child0),proto::_value(proto::_child1),proto::_value(proto::_child2))>>{};#ifBOOST_WORKAROUND(BOOST_MSVC,==1310)#undefMapListOf#undef_value#endiftemplate<typenameExpr>structmap_list_of_expr;structmap_list_of_dom:proto::domain<proto::pod_generator<map_list_of_expr>,MapListOf>{};// An expression wrapper that provides a conversion to a
// map that uses the MapListOf
template<typenameExpr>structmap_list_of_expr{BOOST_PROTO_BASIC_EXTENDS(Expr,map_list_of_expr,map_list_of_dom)BOOST_PROTO_EXTENDS_FUNCTION()template<typenameKey,typenameValue,typenameCmp,typenameAl>operatorstd::map<Key,Value,Cmp,Al>()const{BOOST_MPL_ASSERT((proto::matches<Expr,MapListOf>));std::map<Key,Value,Cmp,Al>map;returnMapListOf()(*this,0,map);}};map_list_of_expr<proto::terminal<map_list_of_tag>::type>constmap_list_of={{{}}};intmain(){// Initialize a map:
std::map<std::string,int>op=map_list_of("<",1)("<=",2)(">",3)(">=",4)("=",5)("<>",6);std::cout<<"\"<\" --> "<<op["<"]<<std::endl;std::cout<<"\"<=\" --> "<<op["<="]<<std::endl;std::cout<<"\">\" --> "<<op[">"]<<std::endl;std::cout<<"\">=\" --> "<<op[">="]<<std::endl;std::cout<<"\"=\" --> "<<op["="]<<std::endl;std::cout<<"\"<>\" --> "<<op["<>"]<<std::endl;return0;}

An advanced example of a Proto transform that implements Howard Hinnant's
design for future groups that block for all or some
asynchronous operations to complete and returns their results in a tuple
of the appropriate type.

// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is an example of using Proto transforms to implement
// Howard Hinnant's future group proposal.
#include<boost/fusion/include/vector.hpp>#include<boost/fusion/include/as_vector.hpp>#include<boost/fusion/include/joint_view.hpp>#include<boost/fusion/include/single_view.hpp>#include<boost/proto/core.hpp>#include<boost/proto/transform.hpp>namespacempl=boost::mpl;namespaceproto=boost::proto;namespacefusion=boost::fusion;usingproto::_;template<classL,classR>structpick_left{BOOST_MPL_ASSERT((boost::is_same<L,R>));typedefLtype;};// Work-arounds for Microsoft Visual C++ 7.1
#ifBOOST_WORKAROUND(BOOST_MSVC,==1310)#defineFutureGroup(x)proto::call<FutureGroup(x)>#endif// Define the grammar of future group expression, as well as a
// transform to turn them into a Fusion sequence of the correct
// type.
structFutureGroup:proto::or_<// terminals become a single-element Fusion sequence
proto::when<proto::terminal<_>,fusion::single_view<proto::_value>(proto::_value)>// (a && b) becomes a concatenation of the sequence
// from 'a' and the one from 'b':
,proto::when<proto::logical_and<FutureGroup,FutureGroup>,fusion::joint_view<boost::add_const<FutureGroup(proto::_left)>,boost::add_const<FutureGroup(proto::_right)>>(FutureGroup(proto::_left),FutureGroup(proto::_right))>// (a || b) becomes the sequence for 'a', so long
// as it is the same as the sequence for 'b'.
,proto::when<proto::logical_or<FutureGroup,FutureGroup>,pick_left<FutureGroup(proto::_left),FutureGroup(proto::_right)>(FutureGroup(proto::_left))>>{};#ifBOOST_WORKAROUND(BOOST_MSVC,==1310)#undefFutureGroup#endiftemplate<classE>structfuture_expr;structfuture_dom:proto::domain<proto::generator<future_expr>,FutureGroup>{};// Expressions in the future group domain have a .get()
// member function that (ostensibly) blocks for the futures
// to complete and returns the results in an appropriate
// tuple.
template<classE>structfuture_expr:proto::extends<E,future_expr<E>,future_dom>{explicitfuture_expr(Econst&e):proto::extends<E,future_expr<E>,future_dom>(e){}typenamefusion::result_of::as_vector<typenameboost::result_of<FutureGroup(E,int,int)>::type>::typeget()const{inti=0;returnfusion::as_vector(FutureGroup()(*this,i,i));}};// The future<> type has an even simpler .get()
// member function.
template<classT>structfuture:future_expr<typenameproto::terminal<T>::type>{future(Tconst&t=T()):future_expr<typenameproto::terminal<T>::type>(proto::terminal<T>::type::make(t)){}Tget()const{returnproto::value(*this);}};// TEST CASES
structA{};structB{};structC{};intmain(){usingfusion::vector;future<A>a;future<B>b;future<C>c;future<vector<A,B>>ab;// Verify that various future groups have the
// correct return types.
At0=a.get();vector<A,B,C>t1=(a&&b&&c).get();vector<A,C>t2=((a||a)&&c).get();vector<A,B,C>t3=((a&&b||a&&b)&&c).get();vector<vector<A,B>,C>t4=((ab||ab)&&c).get();return0;}

Proto was initially developed as part of Boost.Xpressive
to simplify the job of transforming an expression template into an executable
finite state machine capable of matching a regular expression. Since then,
Proto has found application in the redesigned and improved Spirit-2 and the
related Karma library. As a result of these efforts, Proto evolved into a
generic and abstract grammar and tree transformation framework applicable
in a wide variety of DSEL scenarios.

The grammar and tree transformation framework is modeled on Spirit's grammar
and semantic action framework. The expression tree data structure is similar
to Fusion data structures in many respects, and is interoperable with Fusion's
iterators and algorithms.

The syntax for the grammar-matching features of proto::matches<> is inspired by MPL's lambda expressions.

The idea for using function types for Proto's composite transforms is inspired
by Aleksey Gurtovoy's "round"
lambda notation.

A transform of the form R(A0,A1,...) (i.e., a function type) where
proto::is_callable<R>::value is true.
R is treated as a polymorphic
function object and the arguments are treated as transforms that yield
the arguments to the function object.

context

In Proto, the term context refers to an object
that can be passed, along with an expression to evaluate, to the proto::eval()
function. The context determines how the expression is evaluated. All
context structs define a nested eval<> template that, when instantiated
with a node tag type (e.g., proto::tag::plus),
is a binary polymorphic function object that accepts an expression
of that type and the context object. In this way, contexts associate
behaviors with expression nodes.

domain

In Proto, the term domain refers to a type that
associates expressions within that domain with a generator
for that domain and optionally a grammar for the
domain. Domains are used primarily to imbue expressions within that
domain with additional members and to restrict Proto's operator overloads
such that expressions not conforming to the domain's grammar are never
created. Domains are empty structs that inherit from proto::domain<>.

domain-specific embedded language

A domain-specific language implemented as a library. The language in
which the library is written is called the "host" language,
and the language implemented by the library is called the "embedded"
language.

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

In Proto, an expression is a heterogeneous tree
where each node is either an instantiation of boost::proto::expr<>, boost::proto::basic_expr<> or some type that is an extension
(via boost::proto::extends<>
or BOOST_PROTO_EXTENDS()) of such an instantiation.

expression template

A C++ technique using templates and operator overloading to cause expressions
to build trees that represent the expression for lazy evaluation later,
rather than evaluating the expression eagerly. Some C++ libraries use
expression templates to build domain-specific embedded languages.

generator

In Proto, a generator is a unary polymorphic function
object that you specify when defining a domain.
After constructing a new expression, Proto passes the expression to
your domain's generator for further processing. Often, the generator
wraps the expression in an extension wrapper that adds additional members
to it.

grammar

In Proto, a grammar is a type that describes a
subset of Proto expression types. Expressions in a domain must conform
to that domain's grammar. The proto::matches<> metafunction evaluates whether
an expression type matches a grammar. Grammars are either primitives
such as proto::_, composites such as proto::plus<>,
control structures such as proto::or_<>, or some type derived from
a grammar.

object transform

A transform of the form R(A0,A1,...) (i.e., a function type) where
proto::is_callable<R>::value is false.
R is treated as the
type of an object to construct and the arguments are treated as transforms
that yield the parameters to the constructor.

polymorphic function object

An instance of a class type with an overloaded function call operator
and a nested result_type
typedef or result<>
template for calculating the return type of the function call operator.

primitive transform

A type that defines a kind of polymorphic function object that takes
three arguments: expression, state, and data. Primitive transforms
can be used to compose callable transforms and object transforms.