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<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;
          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:

      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

      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.