Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of boost. Click here for the latest Boost documentation.

4. Code generation facilities

There are cases, especially in the domain of numeric computation, when one wants to perform some part of the calculations at compile-time, and then pass the results to a run-time part of the program for further processing. For example, suppose one has implemented a complex compile-time algorithm that works with fixed-point arithmetic:

// fixed-point algorithm input
typedef mpl::vector<
      mpl::fixed_c<-1,2345678>
    , mpl::fixed_c<9,0001>
    // ..
    , mpl::fixed_c<3,14159>
    > input_data;

/*
  complex compile-time algorithm 
*/
typedef /*...*/ result_data;

Suppose the result_data here is a sequence of mpl::fixed_c types that keeps the results of the algorithm, and now one wishes to feed that result to the run-time part of the algorithm. With MPL she can do this:

double my_algorithm()
{
    // passing the results to the run-time part of the program
    std::vector<double> results;
    results.reserve(mpl::size<result_data>::value);
    mpl::for_each<numbers,_>(
          boost::bind(&std::vector<double>::push_back, &results, _1)
        );
    // ...
}

The for_each<numbers,_>(...) call is what actually transfers the compile-time result_data into run-time results. for_each is a function template declared as:

template<
      typename Seq
    , typename TransformOp
    , typename F
    >
void for_each(F f)
{
    // ...
}

To call the function, one is required to explicitly provide two actual template parameters, a compile-time sequence Seq and a unary transformation metafunction TransformOp, plus a run-time function argument f (in our example, numbers, _, and boost::bind(...) correspondingly). f is a function object which operator() is called for every element in the Seq tranfromed by TransformOp.

Applying this to our example, the

mpl::for_each<numbers,_>(
      boost::bind(&std::vector<double>::push_back, &results, _1)
    );

call is roughly equivalent to this:

f(mpl::apply< _,mpl::at_c<result_data,0>::type >::type());
f(mpl::apply< _,mpl::at_c<result_data,1>::type >::type());
// ...
f(mpl::apply< _,mpl::at_c<result_data,n>::type >::type());

where n == mpl::size<result_data>::type::value.