Keywords: template metaprogramming, generic programming, programming languages, C++, STL, type systems, polymorphism, compile-time

4. Code generation facilities
Prev |  | Next

## 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`.

Prev | Up | Next
3. Lambda facility | Home | 5. Example: a compile-time FSM generator