- Dimensional Analysis
- Higher-Order Metafunctions
- Handling Placeholders
- More Lambda Capabilities
- Lambda Details
- Details
- Exercises

## 3.3 Handling Placeholders

Our implementation of `twice` already works with metafunction classes. Ideally, we would like it to work with placeholder expressions, too, much the same as `mpl::transform` allows us to pass either form. For example, we would like to be able to write:

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

But when we look at the implementation of `boost::add_pointer`, it becomes clear that the current definition of `twice` can't work that way.

template <class T> struct add_pointer { typedef T* type; };

To be invokable by `twice`, `boost::add_pointer<_1>` would have to be a metafunction class, along the lines of `add_pointer_f`. Instead, it's just a nullary metafunction returning the almost senseless type `_1*`. Any attempt to use `two_pointers` will fail when `apply1` reaches for a nested `::apply` metafunction in `boost::add_pointer<_1>` and finds that it doesn't exist.

We've determined that we don't get the behavior we want automatically, so what next? Since `mpl::transform` can do this sort of thing, there ought to be a way for us to do it too—and so there is.

#### 3.3.1 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< typename 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.

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;

#### 3.3.2 The `apply` Metafunction

Invoking the result of `lambda` is such a common pattern that *MPL* provides an `apply` metafunction to do just that. Using `mpl::apply`, our flexible version of `twice` becomes:

#include <boost/mpl/apply.hpp> template <class F, class X> struct twice : mpl::apply<F, typename mpl::apply<F,X>::type> {};

You can think of `mpl::apply` as being just like the `apply1` template that we wrote, with two additional features:

- While
`apply1`operates only on metafunction classes, the first argument to`mpl::apply`can be any lambda expression (including those built with placeholders). - While
`apply1`accepts only one additional argument to which the metafunction class will be applied,`mpl::apply`can invoke its first argument on any number from zero to five additional arguments.^{ [5] }For example:

// binary lambda expression applied to 2 additional arguments mpl::apply< mpl::plus<_1,_2> ,mpl::int_<6>,mpl::int_<7>>::type::value // == 13