mirror of
https://github.com/boostorg/mpl.git
synced 2026-01-27 01:12:19 +01:00
166 lines
6.8 KiB
HTML
166 lines
6.8 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
|
|
<title>3. Lambda facility</title>
|
|
<link rel="stylesheet" href="article.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.50.0">
|
|
<meta name="keywords" content="template metaprogramming, generic programming, programming languages, C++, STL, type systems, polymorphism, compile-time">
|
|
<link rel="home" href="index.html" title="the boost c++ metaprogramming library">
|
|
<link rel="up" href="index.html" title="the boost c++ metaprogramming library">
|
|
<link rel="previous" href="usage.html" title="2. basic usage">
|
|
<link rel="next" href="codegeneration.html" title="4. code generation facilities">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<div class="navheader">
|
|
<table width="100%" summary="Navigation header">
|
|
<tr>
|
|
<th colspan="3" align="center">3. Lambda facility</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td width="20%" align="left"><a accesskey="p" href="usage.html">Prev</a> </td>
|
|
<th width="60%" align="center"> </th>
|
|
<td width="20%" align="right"> <a accesskey="n" href="codegeneration.html">Next</a></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<hr>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<div class="titlepage">
|
|
<div>
|
|
<h2 class="title" style="clear: both"><a name="lambda"></a>3. Lambda facility</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<p>The MPL's lambda facility allows the <i>inline composition</i> 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:</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef mpl::lambda<expr>::type func;
|
|
</pre>
|
|
|
|
<p>For example, <tt>boost::remove_const</tt> traits template from Boost <tt>type_traits</tt> library <span class="citation">[<a class="interlink" href="refs.html#ref.ttl" title="[ttl]">TTL</a>]</span> is a class template (obviously), or a <a class="interlink" href="usage.html#metafunctions" title="2.2. metafunctions">metafunction</a> in MPL terminology. The simplest example of an ‘inline composition’ of it would be something like:</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef boost::remove_const<_1> expr;
|
|
</pre>
|
|
|
|
<p>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 <span class="emphasis"><em>transformed</em></span> into a metafunction class using the MPL's <tt>lambda</tt> facility:</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef boost::remove_const<_1> expr;
|
|
typedef mpl::lambda<expr>::type func;
|
|
</pre>
|
|
|
|
<p>The <tt>func</tt> is a unary metafunction class and can be used as such. In particular, it can be pass around or invoked (applied):</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef mpl::apply<func,int const>::type res;
|
|
BOOST_MPL_ASSERT_IS_SAME(res, int);
|
|
</pre>
|
|
|
|
<p>or even</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef func::apply<int const>::type res;
|
|
BOOST_MPL_ASSERT_IS_SAME(res, int);
|
|
</pre>
|
|
|
|
<p>Inline composition is very appealing syntactically when one deals with metafunctions, because it makes the expression obvious:</p>
|
|
|
|
<pre class="programlisting">
|
|
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;
|
|
</pre>
|
|
|
|
<p>And one does not have to specify the last part (<tt>typedef lambda<expr>::type func</tt>), because all the algorithms do this to any of their metafunction class operands internally (a <tt>lambda<T>::type</tt> expression applied to a metafunction class gives back the same metafunction class, so it's safe to apply the expression unconditionally).</p>
|
|
|
|
<p>The alternative way to write an equivalent of the above metafunction class would be:</p>
|
|
|
|
<pre class="programlisting">
|
|
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;
|
|
</pre>
|
|
|
|
<p>Or to use <tt>mpl::compose_</tt> family of templates in a similar way. Here, we use <tt>mpl::meta_fun</tt> templates to convert metafunctions into metafunction classes and then combine them using <tt>mpl::bind</tt>. The transformation from this form to the above inline lambda expression and vice-versa is mechanical, and that is essentially what the <tt>typedef mpl::lambda<expr>::type</tt> expression does.</p>
|
|
|
|
<p>For its own metafunctions (algorithms, primitives, etc.), MPL enables one to write the above in a less cumbersome way:</p>
|
|
|
|
<pre class="programlisting">
|
|
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;
|
|
</pre>
|
|
|
|
<p>Note that we still have to wrap <tt>is_same</tt> into <tt>make_f2</tt>, because it's a foreign template.</p>
|
|
|
|
<p>Now, about combining class template metafunctions and metafunction classes in the single lambda expression - it can be done like this:</p>
|
|
|
|
<pre class="programlisting">
|
|
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;
|
|
</pre>
|
|
|
|
<p>To bind something to one of its arguments (or change the order of parameters), then use either:</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef mpl::logical_or<
|
|
mpl::less< mpl::size_of<_>,mpl::int_c<16> >
|
|
, mpl::bind<my_predicate,int,_>::type // here
|
|
> expr;
|
|
</pre>
|
|
|
|
<p>or</p>
|
|
|
|
<pre class="programlisting">
|
|
typedef mpl::logical_or<
|
|
mpl::less< mpl::size_of<_>,mpl::int_c<16> >
|
|
, my_predicate::apply<int,_> // here
|
|
> expr;
|
|
</pre>
|
|
</div>
|
|
|
|
<div class="navfooter">
|
|
<hr>
|
|
<table width="100%" summary="Navigation footer">
|
|
<tr>
|
|
<td width="40%" align="left"><a accesskey="p" href="usage.html">Prev</a> </td>
|
|
<td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td>
|
|
<td width="40%" align="right"> <a accesskey="n" href="codegeneration.html">Next</a></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td width="40%" align="left" valign="top">2. Basic usage </td>
|
|
<td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td>
|
|
<td width="40%" align="right" valign="top"> 4. Code generation facilities</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|