# Boost.Flyweight Tutorial Annex: MPL lambda expressions

Technical issues
Boost.Flyweight tutorial
Boost.Flyweight reference

This short introduction to lambda expressions is meant for readers unfamiliar with the Boost MPL Library who want to rapidly acquire a working knowledge of the basic concepts for the purposes of using them in Boost.Flyweight. Please refer to the Boost.MPL documentation for further information beyond these introductory notes.

The specifiers defined by Boost.Flyweight rely heavily on the `Lambda Expression` concept defined by the Boost MPL Library. A lambda expression can be thought of as a compile-time "type function", an entity (a concrete type, actually) that can be invoked with a list of types and returns some associated type in its turn. Consider for instance an arbitrary class template:

>     template<typename T,typename Q>
>     class foo
>     {
>       ...
>     };

and suppose we want to have a lambda expression that, when invoked with some generic types `Arg1` and `Arg2`, returns `foo<Arg1,Arg2>`. Such a lambda expression can be implemented in two ways

1. As a `MPL Metafunction Class`, a type with a special nested class template named `apply`:

   >     struct foo_specifier
   >     {
   >       template<typename Arg1,typename Arg2>
   >       struct apply
   >       {
   >         // this is the "return type" of foo_specifier
   >         typedef foo<Arg1,Arg2> type;
   >       };
   >     };

2. As a `MPL Placeholder Expression`, a class template instantiated with one or more placeholders:

   >     typedef foo<boost::mpl::_1,boost::mpl::_2> foo_specifier;

   Note that, in this case, `foo_specifier` is a concrete type, much as `int` or `std::set<std::string>` are; yet, MPL internal mechanisms are able to detect that this type has been gotten from instantiating a class template with placeholders `boost::mpl::_1` and `boost::mpl::_2` and take these placeholders as slots to be substituted for actual types (the first and second type supplied, respectively) when `foo_specifier` is invoked. So, an instantiation of `foo` can be used to refer back to the `foo` class template itself! The net effect is the same as with metafunctions, but placeholder expressions spare us the need to write boilerplate metafunction classes --and the kind of metaprogramming magic they depend on has an undeniable beauty to it.

So far the examples shown just forward the arguments `Arg1` and `Arg2` directly to a class template without further elaboration, but there is nothing preventing us from doing some argument manipulation, like, for instance, switching their places:

>     struct foo_specifier
>     {
>       template<typename Arg1,typename Arg2>
>       struct apply{typedef foo<Arg2,Arg1> type;};
>     };

>     typedef foo<boost::mpl::_2,boost::mpl::_1> foo_specifier;

passing placeholder subexpressions as arguments to the overall expression:

>     struct foo_specifier
>     {
>       template<typename Arg1,typename Arg2>
>       struct apply{typedef foo<boost::shared_ptr<Arg1>,std::less<Arg2> > type;};
>     };

>     typedef foo<
>       boost::shared_ptr<boost::mpl::_1>,
>       std::less<boost::mpl::_2>
>     > foo_specifier;

or accepting less or more arguments than the class template itself (the number of parameters of a lambda expression is called its arity):

>     struct foo_specifier
>     {
>       template<typename Arg1>
>       struct apply{typedef foo<Arg1,std::less<Arg1> type;};
>     };

>     typedef foo<boost::mpl::_1,std::less<boost::mpl::_1> > foo_specifier;

>     struct foo_specifier
>     {
>       template<typename Arg1,typename Arg2,typename Arg3>
>       struct apply{typedef foo<Arg1,foo<Arg2,Arg3> > type;};
>     };

>     typedef foo<boost::mpl::_1,foo<boost::mpl::_2,boost::mpl::_3> > foo_specifier;

Technical issues
Boost.Flyweight tutorial
Boost.Flyweight reference

Revised August 13th 2008

© Copyright 2006-2008 Joaquín M López Muñoz. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)