THE BOOST MPL LIBRARY: The lambda Metafunction

Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Handling Placeholders / The lambda Metafunction

# The `lambda` Metafunction

We can generate a metafunction class from `boost::add_pointer<_1>`, using MPL's `lambda` metafunction:

    template <class X>
    struct two_pointers
      : twice<typename mpl::lambda<boost::add_pointer<_1> >::type, X>
    {};

    BOOST_STATIC_ASSERT((
        boost::is_same<
            two_pointers<int>::type
          , int**
        >::value
    ));

We'll refer to metafunction classes like `add_pointer_f` and placeholder expressions like `boost::add_pointer<_1>` as lambda expressions. The term, meaning "unnamed function object," was introduced in the 1930s by the logician Alonzo Church as part of a fundamental theory of computation he called the lambda-calculus. [4] MPL uses the somewhat obscure word `lambda` because of its well-established precedent in functional programming languages.

[4] | See http://en.wikipedia.org/wiki/Lambda_calculus for an in-depth treatment, including a reference to Church's paper proving that the equivalence of lambda expressions is in general not decidable.

Although its primary purpose is to turn placeholder expressions into metafunction classes, `mpl::lambda` can accept any lambda expression, even if it's already a metafunction class. In that case, `lambda` returns its argument unchanged. MPL algorithms like `transform` call `lambda` internally, before invoking the resulting metafunction class, so that they work equally well with either kind of lambda expression. We can apply the same strategy to `twice`:

    template <class F, class X>
    struct twice
       : apply1<
             typename mpl::lambda<F>::type
           , typename apply1<
                 typename mpl::lambda<F>::type
               , X
             >::type
         >
    {};

Now we can use `twice` with metafunction classes and placeholder expressions:

    int* x;

    twice<add_pointer_f, int>::type           p = &x;
    twice<boost::add_pointer<_1>, int>::type q = &x;