| Home | Libraries | People | FAQ | More

##### 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 );