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

Click here to view the latest version of this page.
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;