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

3. Lambda facility
Prev |  | Next

## 3. Lambda facility

The MPL's lambda facility allows the inline composition of class templates into ‘lambda expressions’, which are classes and can therefore be passed around as ordinary metafunction classes, or transformed into metafunction classes before application using the expression:

    typedef mpl::lambda<expr>::type func;

For example, `boost::remove_const` traits template from Boost `type_traits` library [TTL] is a class template (obviously), or a metafunction in MPL terminology. The simplest example of an ‘inline composition’ of it would be something like:

    typedef boost::remove_const<_1> expr;

This forms a so called ‘lambda expression’, which is neither a metafunction class, nor a metafunction, yet can be passed around everywhere because it's an ordinary C++ class, because all MPL facilities are polymorphic with respect to their arguments. Now, that lambda expression can be transformed into a metafunction class using the MPL's `lambda` facility:

    typedef boost::remove_const<_1> expr;
    typedef mpl::lambda<expr>::type func;

The `func` is a unary metafunction class and can be used as such. In particular, it can be pass around or invoked (applied):

    typedef mpl::apply<func,int const>::type res;
    BOOST_MPL_ASSERT_IS_SAME(res, int);

or even

    typedef func::apply<int const>::type res;
    BOOST_MPL_ASSERT_IS_SAME(res, int);

Inline composition is very appealing syntactically when one deals with metafunctions, because it makes the expression obvious:

    typedef mpl::logical_or<
          mpl::less< mpl::size_of<_1>, mpl::int_c<16> >
        , boost::is_same<_1,_2>
        > expr;

    typedef mpl::lambda<expr>::type func;

And one does not have to specify the last part (`typedef lambda<expr>::type func`), because all the algorithms do this to any of their metafunction class operands internally (a `lambda<T>::type` expression applied to a metafunction class gives back the same metafunction class, so it's safe to apply the expression unconditionally).

The alternative way to write an equivalent of the above metafunction class would be:

    typedef bind<
          mpl::meta_fun2<mpl::logical_or>
        , mpl::bind< mpl::meta_fun2<mpl::less>
            , mpl::bind< mpl::meta_fun1<mpl::size_of>,_1 >
            , mpl::int_c<16>
            >
        , mpl::bind< mpl::meta_fun2<boost::is_same>,_1,_2 >
        > func;

Or to use `mpl::compose_` family of templates in a similar way. Here, we use `mpl::meta_fun` templates to convert metafunctions into metafunction classes and then combine them using `mpl::bind`. The transformation from this form to the above inline lambda expression and vice-versa is mechanical, and that is essentially what the `typedef mpl::lambda<expr>::type` expression does.

For its own metafunctions (algorithms, primitives, etc.), MPL enables one to write the above in a less cumbersome way:

    typedef mpl::bind<
          mpl::logical_or<>
        , mpl::bind< mpl::less<>, mpl::bind<mpl::size_of<>,_1>, mpl::int_c<16> >
        , mpl::bind< mpl::make_f2<boost::is_same>, _1,_2 >
        > func;

Note that we still have to wrap `is_same` into `make_f2`, because it's a foreign template.

Now, about combining class template metafunctions and metafunction classes in the single lambda expression - it can be done like this:

    struct my_predicate
    {
        template< typename T1, typename T2 > struct apply
        {
            //...
        };
    };

    typedef mpl::logical_or<
          mpl::less< mpl::size_of<_>,mpl::int_c<16> >
        , mpl::bind< my_predicate,_,_ > // here
        > expr;

To bind something to one of its arguments (or change the order of parameters), then use either:

    typedef mpl::logical_or<
          mpl::less< mpl::size_of<_>,mpl::int_c<16> >
        , mpl::bind<my_predicate,int,_>::type // here
        > expr;

or

    typedef mpl::logical_or<
          mpl::less< mpl::size_of<_>,mpl::int_c<16> >
        , my_predicate::apply<int,_> // here
        > expr;

Prev | Up | Next
2. Basic usage | Home | 4. Code generation facilities