Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
Expression Generators

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.
struct calculator_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:

// If calculator<> uses BOOST_PROTO_EXTENDS() instead of 
// use proto::extends<>, use proto::pod_generator<> instead
// of proto::generator<>.
struct calculator_domain
  : proto::domain< proto::pod_generator< calculator > >
{};

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:

double data[] = {1., 2., 3., 4.};

// Use the calculator EDSL to square each element ... WORKS! :-)
std::transform( data, data + 4, data, _1 * _1 );

PrevUpHomeNext