boost-react-native-bundle
Version:
Boost library as in https://sourceforge.net/projects/boost/files/boost/1.57.0/
1,298 lines (997 loc) • 125 kB
text/xml
<?xml version="1.0" encoding="ISO-Latin-1"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library name="Lambda" dirname="lambda" id="lambda"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
<author>
<firstname>Jaakko</firstname>
<surname>J�rvi</surname>
<email>jarvi at cs tamu edu</email>
</author>
<copyright>
<year>1999</year>
<year>2000</year>
<year>2001</year>
<year>2002</year>
<year>2003</year>
<year>2004</year>
<holder>Jaakko J�rvi</holder>
<holder>Gary Powell</holder>
</copyright>
<legalnotice>
<para>Use, modification and distribution is subject to the Boost
Software License, Version 1.0. (See accompanying file
<filename>LICENSE_1_0.txt</filename> or copy at <ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)</para>
</legalnotice>
<librarypurpose>Define small unnamed function objects at the actual call site, and more</librarypurpose>
<librarycategory name="category:higher-order"/>
</libraryinfo>
<title>Boost.Lambda</title>
<!-- -->
<section id="introduction">
<title>In a nutshell</title>
<para>
The Boost Lambda Library (BLL in the sequel) is a C++ template
library, which implements a form of <emphasis>lambda abstractions</emphasis> for C++.
The term originates from functional programming and lambda calculus, where a lambda abstraction defines an unnamed function.
The primary motivation for the BLL is to provide flexible and
convenient means to define unnamed function objects for STL algorithms.
In explaining what the library is about, a line of code says more than a thousand words; the
following line outputs the elements of some STL container
<literal>a</literal> separated by spaces:
<programlisting><![CDATA[for_each(a.begin(), a.end(), std::cout << _1 << ' ');]]></programlisting>
The expression <literal><![CDATA[std::cout << _1 << ' ']]></literal> defines a unary function object.
The variable <literal>_1</literal> is the parameter of this function, a <emphasis>placeholder</emphasis> for the actual argument.
Within each iteration of <literal>for_each</literal>, the function is
called with an element of <literal>a</literal> as the actual argument.
This actual argument is substituted for the placeholder, and the <quote>body</quote> of the function is evaluated.
</para>
<para>The essence of BLL is letting you define small unnamed function objects, such as the one above, directly on the call site of an STL algorithm.
</para>
</section>
<section id="lambda.getting_started">
<title>Getting Started</title>
<section>
<title>Installing the library</title>
<para>
The library consists of include files only, hence there is no
installation procedure. The <literal>boost</literal> include directory
must be on the include path.
There are a number of include files that give different functionality:
<!-- TODO: tarkista viel� riippuvuudet-->
<itemizedlist>
<listitem><para>
<filename>lambda/lambda.hpp</filename> defines lambda expressions for different C++
operators, see <xref linkend="lambda.operator_expressions"/>.
</para></listitem>
<listitem><para>
<filename>lambda/bind.hpp</filename> defines <literal>bind</literal> functions for up to 9 arguments, see <xref linkend="lambda.bind_expressions"/>.</para></listitem>
<listitem><para>
<filename>lambda/if.hpp</filename> defines lambda function equivalents for if statements and the conditional operator, see <xref linkend="lambda.lambda_expressions_for_control_structures"/> (includes <filename>lambda.hpp</filename>).
</para></listitem>
<listitem><para>
<filename>lambda/loops.hpp</filename> defines lambda function equivalent for looping constructs, see <xref linkend="lambda.lambda_expressions_for_control_structures"/>.
</para></listitem>
<listitem><para>
<filename>lambda/switch.hpp</filename> defines lambda function equivalent for the switch statement, see <xref linkend="lambda.lambda_expressions_for_control_structures"/>.
</para></listitem>
<listitem><para>
<filename>lambda/construct.hpp</filename> provides tools for writing lambda expressions with constructor, destructor, new and delete invocations, see <xref linkend="lambda.construction_and_destruction"/> (includes <filename>lambda.hpp</filename>).
</para></listitem>
<listitem><para>
<filename>lambda/casts.hpp</filename> provides lambda versions of different casts, as well as <literal>sizeof</literal> and <literal>typeid</literal>, see <xref linkend="lambda.cast_expressions"/>.
</para></listitem>
<listitem><para>
<filename>lambda/exceptions.hpp</filename> gives tools for throwing and catching
exceptions within lambda functions, <xref linkend="lambda.exceptions"/> (includes
<filename>lambda.hpp</filename>).
</para></listitem>
<listitem><para>
<filename>lambda/algorithm.hpp</filename> and <filename>lambda/numeric.hpp</filename> (cf. standard <filename>algortihm</filename> and <filename>numeric</filename> headers) allow nested STL algorithm invocations, see <xref linkend="lambda.nested_stl_algorithms"/>.
</para></listitem>
</itemizedlist>
Any other header files in the package are for internal use.
Additionally, the library depends on two other Boost Libraries, the
<emphasis>Tuple</emphasis> <xref linkend="cit:boost::tuple"/> and the <emphasis>type_traits</emphasis> <xref linkend="cit:boost::type_traits"/> libraries, and on the <filename>boost/ref.hpp</filename> header.
</para>
<para>
All definitions are placed in the namespace <literal>boost::lambda</literal> and its subnamespaces.
</para>
</section>
<section>
<title>Conventions used in this document</title>
<para>In most code examples, we omit the namespace prefixes for names in the <literal moreinfo="none">std</literal> and <literal moreinfo="none">boost::lambda</literal> namespaces.
Implicit using declarations
<programlisting>
using namespace std;
using namespace boost::lambda;
</programlisting>
are assumed to be in effect.
</para>
</section>
</section>
<section>
<title>Introduction</title>
<section>
<title>Motivation</title>
<para>The Standard Template Library (STL)
<xref role="citation" linkend="cit:stepanov:94"/>, now part of the C++ Standard Library <xref role="citation" linkend="cit:c++:98"/>, is a generic container and algorithm library.
Typically STL algorithms operate on container elements via <emphasis>function objects</emphasis>. These function objects are passed as arguments to the algorithms.
</para>
<para>
Any C++ construct that can be called with the function call syntax
is a function object.
The STL contains predefined function objects for some common cases (such as <literal>plus</literal>, <literal>less</literal> and <literal>not1</literal>).
As an example, one possible implementation for the standard <literal>plus</literal> template is:
<programlisting>
<![CDATA[template <class T>
struct plus : public binary_function<T, T, T> {
T operator()(const T& i, const T& j) const {
return i + j;
}
};]]>
</programlisting>
The base class <literal><![CDATA[binary_function<T, T, T>]]></literal> contains typedefs for the argument and return types of the function object, which are needed to make the function object <emphasis>adaptable</emphasis>.
</para>
<para>
In addition to the basic function object classes, such as the one above,
the STL contains <emphasis>binder</emphasis> templates for creating a unary function object from an adaptable binary function object by fixing one of the arguments to a constant value.
For example, instead of having to explicitly write a function object class like:
<programlisting>
<![CDATA[class plus_1 {
int _i;
public:
plus_1(const int& i) : _i(i) {}
int operator()(const int& j) { return _i + j; }
};]]>
</programlisting>
the equivalent functionality can be achieved with the <literal moreinfo="none">plus</literal> template and one of the binder templates (<literal moreinfo="none">bind1st</literal>).
E.g., the following two expressions create function objects with identical functionalities;
when invoked, both return the result of adding <literal moreinfo="none">1</literal> to the argument of the function object:
<programlisting>
<![CDATA[plus_1(1)
bind1st(plus<int>(), 1)]]>
</programlisting>
The subexpression <literal><![CDATA[plus<int>()]]></literal> in the latter line is a binary function object which computes the sum of two integers, and <literal>bind1st</literal> invokes this function object partially binding the first argument to <literal>1</literal>.
As an example of using the above function object, the following code adds <literal>1</literal> to each element of some container <literal>a</literal> and outputs the results into the standard output stream <literal>cout</literal>.
<programlisting>
<![CDATA[transform(a.begin(), a.end(), ostream_iterator<int>(cout),
bind1st(plus<int>(), 1));]]>
</programlisting>
</para>
<para>
To make the binder templates more generally applicable, the STL contains <emphasis>adaptors</emphasis> for making
pointers or references to functions, and pointers to member functions,
adaptable.
Finally, some STL implementations contain function composition operations as
extensions to the standard <xref linkend="cit:sgi:02"/>.
</para>
<para>
All these tools aim at one goal: to make it possible to specify
<emphasis>unnamed functions</emphasis> in a call of an STL algorithm,
in other words, to pass code fragments as an argument to a function.
However, this goal is attained only partially.
The simple example above shows that the definition of unnamed functions
with the standard tools is cumbersome.
Complex expressions involving functors, adaptors, binders and
function composition operations tend to be difficult to comprehend.
In addition to this, there are significant restrictions in applying
the standard tools. E.g. the standard binders allow only one argument
of a binary function to be bound; there are no binders for
3-ary, 4-ary etc. functions.
</para>
<para>
The Boost Lambda Library provides solutions for the problems described above:
<itemizedlist>
<listitem>
<para>
Unnamed functions can be created easily with an intuitive syntax.
The above example can be written as:
<programlisting>
<![CDATA[transform(a.begin(), a.end(), ostream_iterator<int>(cout),
1 + _1);]]>
</programlisting>
or even more intuitively:
<programlisting>
<![CDATA[for_each(a.begin(), a.end(), cout << (1 + _1));]]>
</programlisting>
</para>
</listitem>
<listitem>
<para>
Most of the restrictions in argument binding are removed,
arbitrary arguments of practically any C++ function can be bound.
</para>
</listitem>
<listitem>
<para>
Separate function composition operations are not needed,
as function composition is supported implicitly.
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Introduction to lambda expressions</title>
<para>
Lambda expression are common in functional programming languages.
Their syntax varies between languages (and between different forms of lambda calculus), but the basic form of a lambda expressions is:
<programlisting>
lambda x<subscript>1</subscript> ... x<subscript>n</subscript>.e
</programlisting>
<!-- $\lambda x_1 \cdots x_n . e$ -->
A lambda expression defines an unnamed function and consists of:
<itemizedlist>
<listitem>
<para>
the parameters of this function: <literal>x<subscript>1</subscript> ... x<subscript>n</subscript></literal>.
<!--$x_1 \cdots x_n$-->
</para>
</listitem>
<listitem>
<para>the expression e which computes the value of the function in terms of the parameters <literal>x<subscript>1</subscript> ... x<subscript>n</subscript></literal>.
</para>
</listitem>
</itemizedlist>
A simple example of a lambda expression is
<programlisting>
lambda x y.x+y
</programlisting>
Applying the lambda function means substituting the formal parameters with the actual arguments:
<programlisting>
(lambda x y.x+y) 2 3 = 2 + 3 = 5
</programlisting>
</para>
<para>
In the C++ version of lambda expressions the <literal>lambda x<subscript>1</subscript> ... x<subscript>n</subscript></literal> part is missing and the formal parameters have predefined names.
In the current version of the library,
there are three such predefined formal parameters,
called <emphasis>placeholders</emphasis>:
<literal>_1</literal>, <literal>_2</literal> and <literal>_3</literal>.
They refer to the first, second and third argument of the function defined
by the lambda expression.
For example, the C++ version of the definition
<programlisting>lambda x y.x+y</programlisting>
is
<programlisting>_1 + _2</programlisting>
</para>
<para>
Hence, there is no syntactic keyword for C++ lambda expressions.
The use of a placeholder as an operand implies that the operator invocation is a lambda expression.
However, this is true only for operator invocations.
Lambda expressions containing function calls, control structures, casts etc. require special syntactic constructs.
Most importantly, function calls need to be wrapped inside a <literal>bind</literal> function.
As an example, consider the lambda expression:
<programlisting>lambda x y.foo(x,y)</programlisting>
Rather than <literal>foo(_1, _2)</literal>, the C++ counterpart for this expression is:
<programlisting>bind(foo, _1, _2)</programlisting>
We refer to this type of C++ lambda expressions as <emphasis>bind expressions</emphasis>.
</para>
<para>A lambda expression defines a C++ function object, hence function application syntax is like calling any other function object, for instance: <literal>(_1 + _2)(i, j)</literal>.
</para>
<section id="lambda.partial_function_application">
<title>Partial function application</title>
<para>
A bind expression is in effect a <emphasis>partial function application</emphasis>.
In partial function application, some of the arguments of a function are bound to fixed values.
The result is another function, with possibly fewer arguments.
When called with the unbound arguments, this new function invokes the original function with the merged argument list of bound and unbound arguments.
</para>
<!-- <para>The underlying implementation of the BLL unifies the two types of lambda expressions (bind expressions and lambda expressions consisting of operator calls).
If operators are regarded as functions, it is easy to see that lambda expressions using operators are partial function applications as well.
E.g. the lambda expression <literal>_1 + 1</literal> can be seen as syntactic sugar for the pseudo code <literal>bind(operator+, _1, 1)</literal>.
</para>
-->
</section>
<section id="lambda.terminology">
<title>Terminology</title>
<para>
A lambda expression defines a function. A C++ lambda expression concretely constructs a function object, <emphasis>a functor</emphasis>, when evaluated. We use the name <emphasis>lambda functor</emphasis> to refer to such a function object.
Hence, in the terminology adopted here, the result of evaluating a lambda expression is a lambda functor.
</para>
</section>
</section>
</section>
<section id = "lambda.using_library">
<title>Using the library</title>
<para>
The purpose of this section is to introduce the basic functionality of the library.
There are quite a lot of exceptions and special cases, but discussion of them is postponed until later sections.
</para>
<section id = "lambda.introductory_examples">
<title>Introductory Examples</title>
<para>
In this section we give basic examples of using BLL lambda expressions in STL algorithm invocations.
We start with some simple expressions and work up.
First, we initialize the elements of a container, say, a <literal>list</literal>, to the value <literal>1</literal>:
<programlisting>
<![CDATA[list<int> v(10);
for_each(v.begin(), v.end(), _1 = 1);]]></programlisting>
The expression <literal>_1 = 1</literal> creates a lambda functor which assigns the value <literal>1</literal> to every element in <literal>v</literal>.<footnote>
<para>
Strictly taken, the C++ standard defines <literal>for_each</literal> as a <emphasis>non-modifying sequence operation</emphasis>, and the function object passed to <literal moreinfo="none">for_each</literal> should not modify its argument.
The requirements for the arguments of <literal>for_each</literal> are unnecessary strict, since as long as the iterators are <emphasis>mutable</emphasis>, <literal>for_each</literal> accepts a function object that can have side-effects on their argument.
Nevertheless, it is straightforward to provide another function template with the functionality of<literal>std::for_each</literal> but more fine-grained requirements for its arguments.
</para>
</footnote>
</para>
<para>
Next, we create a container of pointers and make them point to the elements in the first container <literal>v</literal>:
<programlisting>
<![CDATA[vector<int*> vp(10);
transform(v.begin(), v.end(), vp.begin(), &_1);]]></programlisting>
The expression <literal><![CDATA[&_1]]></literal> creates a function object for getting the address of each element in <literal>v</literal>.
The addresses get assigned to the corresponding elements in <literal>vp</literal>.
</para>
<para>
The next code fragment changes the values in <literal>v</literal>.
For each element, the function <literal>foo</literal> is called.
The original value of the element is passed as an argument to <literal>foo</literal>.
The result of <literal>foo</literal> is assigned back to the element:
<programlisting>
<![CDATA[int foo(int);
for_each(v.begin(), v.end(), _1 = bind(foo, _1));]]></programlisting>
</para>
<para>
The next step is to sort the elements of <literal>vp</literal>:
<programlisting>sort(vp.begin(), vp.end(), *_1 > *_2);</programlisting>
In this call to <literal>sort</literal>, we are sorting the elements by their contents in descending order.
</para>
<para>
Finally, the following <literal>for_each</literal> call outputs the sorted content of <literal>vp</literal> separated by line breaks:
<programlisting>
<![CDATA[for_each(vp.begin(), vp.end(), cout << *_1 << '\n');]]>
</programlisting>
Note that a normal (non-lambda) expression as subexpression of a lambda expression is evaluated immediately.
This may cause surprises.
For instance, if the previous example is rewritten as
<programlisting>
<![CDATA[for_each(vp.begin(), vp.end(), cout << '\n' << *_1);]]>
</programlisting>
the subexpression <literal><![CDATA[cout << '\n']]></literal> is evaluated immediately and the effect is to output a single line break, followed by the elements of <literal>vp</literal>.
The BLL provides functions <literal>constant</literal> and <literal>var</literal> to turn constants and, respectively, variables into lambda expressions, and can be used to prevent the immediate evaluation of subexpressions:
<programlisting>
<![CDATA[for_each(vp.begin(), vp.end(), cout << constant('\n') << *_1);]]>
</programlisting>
These functions are described more thoroughly in <xref linkend="lambda.delaying_constants_and_variables"/>
</para>
</section>
<section id="lambda.parameter_and_return_types">
<title>Parameter and return types of lambda functors</title>
<para>
During the invocation of a lambda functor, the actual arguments are substituted for the placeholders.
The placeholders do not dictate the type of these actual arguments.
The basic rule is that a lambda function can be called with arguments of any types, as long as the lambda expression with substitutions performed is a valid C++ expression.
As an example, the expression
<literal>_1 + _2</literal> creates a binary lambda functor.
It can be called with two objects of any types <literal>A</literal> and <literal>B</literal> for which <literal>operator+(A,B)</literal> is defined (and for which BLL knows the return type of the operator, see below).
</para>
<para>
C++ lacks a mechanism to query a type of an expression.
However, this precise mechanism is crucial for the implementation of C++ lambda expressions.
Consequently, BLL includes a somewhat complex type deduction system which uses a set of traits classes for deducing the resulting type of lambda functions.
It handles expressions where the operands are of built-in types and many of the expressions with operands of standard library types.
Many of the user defined types are covered as well, particularly if the user defined operators obey normal conventions in defining the return types.
</para>
<!-- TODO: move this forward, and just refer to it. -->
<para>
There are, however, cases when the return type cannot be deduced. For example, suppose you have defined:
<programlisting>C operator+(A, B);</programlisting>
The following lambda function invocation fails, since the return type cannot be deduced:
<programlisting>A a; B b; (_1 + _2)(a, b);</programlisting>
</para>
<para>
There are two alternative solutions to this.
The first is to extend the BLL type deduction system to cover your own types (see <xref linkend="lambda.extending"/>).
The second is to use a special lambda expression (<literal>ret</literal>) which defines the return type in place (see <xref linkend = "lambda.overriding_deduced_return_type"/>):
<programlisting><![CDATA[A a; B b; ret<C>(_1 + _2)(a, b);]]></programlisting>
</para>
<para>
For bind expressions, the return type can be defined as a template argument of the bind function as well:
<programlisting><![CDATA[bind<int>(foo, _1, _2);]]></programlisting>
<!--
A rare case, where the <literal><![CDATA[ret<type>(bind(...))]]></literal> syntax does not work, but
<literal><![CDATA[bind<type>(...)]]></literal> does, is explained in <xref linkend="lambda.nullary_functors_and_ret"/>.
-->
</para>
</section>
<section id="lambda.actual_arguments_to_lambda_functors">
<title>About actual arguments to lambda functors</title>
<!-- <para><emphasis>This section is no longer (or currently) relevant;
acual arguments can be non-const rvalues.
The section can, however, become relevant again, if in the future BLL will support
lambda functors with higher arities than 3.</emphasis></para> -->
<para>A general restriction for the actual arguments is that they cannot be non-const rvalues.
For example:
<programlisting>
int i = 1; int j = 2;
(_1 + _2)(i, j); // ok
(_1 + _2)(1, 2); // error (!)
</programlisting>
This restriction is not as bad as it may look.
Since the lambda functors are most often called inside STL-algorithms,
the arguments originate from dereferencing iterators and the dereferencing operators seldom return rvalues.
And for the cases where they do, there are workarounds discussed in
<xref linkend="lambda.rvalues_as_actual_arguments"/>.
</para>
</section>
<section id="lambda.storing_bound_arguments">
<title>Storing bound arguments in lambda functions</title>
<para>
By default, temporary const copies of the bound arguments are stored
in the lambda functor.
This means that the value of a bound argument is fixed at the time of the
creation of the lambda function and remains constant during the lifetime
of the lambda function object.
For example:
<programlisting>
int i = 1;
(_1 = 2, _1 + i)(i);
</programlisting>
The comma operator is overloaded to combine lambda expressions into a sequence;
the resulting unary lambda functor first assigns 2 to its argument,
then adds the value of <literal>i</literal> to it.
The value of the expression in the last line is 3, not 4.
In other words, the lambda expression that is created is
<literal>lambda x.(x = 2, x + 1)</literal> rather than
<literal>lambda x.(x = 2, x + i)</literal>.
</para>
<para>
As said, this is the default behavior for which there are exceptions.
The exact rules are as follows:
<itemizedlist>
<listitem>
<para>
The programmer can control the storing mechanism with <literal>ref</literal>
and <literal>cref</literal> wrappers <xref linkend="cit:boost::ref"/>.
Wrapping an argument with <literal>ref</literal>, or <literal>cref</literal>,
instructs the library to store the argument as a reference,
or as a reference to const respectively.
For example, if we rewrite the previous example and wrap the variable
<literal>i</literal> with <literal>ref</literal>,
we are creating the lambda expression <literal>lambda x.(x = 2, x + i)</literal>
and the value of the expression in the last line will be 4:
<programlisting>
i = 1;
(_1 = 2, _1 + ref(i))(i);
</programlisting>
Note that <literal>ref</literal> and <literal>cref</literal> are different
from <literal>var</literal> and <literal>constant</literal>.
While the latter ones create lambda functors, the former do not.
For example:
<programlisting>
int i;
var(i) = 1; // ok
ref(i) = 1; // not ok, ref(i) is not a lambda functor
</programlisting>
The functions <literal>ref</literal> and <literal>cref</literal> mostly
exist for historical reasons,
and <literal>ref</literal> can always
be replaced with <literal>var</literal>, and <literal>cref</literal> with
<literal>constant_ref</literal>.
See <xref linkend="lambda.delaying_constants_and_variables"/> for details.
The <literal>ref</literal> and <literal>cref</literal> functions are
general purpose utility functions in Boost, and hence defined directly
in the <literal moreinfo="none">boost</literal> namespace.
</para>
</listitem>
<listitem>
<para>
Array types cannot be copied, they are thus stored as const reference by default.
</para>
</listitem>
<listitem>
<para>
For some expressions it makes more sense to store the arguments as references.
For example, the obvious intention of the lambda expression
<literal>i += _1</literal> is that calls to the lambda functor affect the
value of the variable <literal>i</literal>,
rather than some temporary copy of it.
As another example, the streaming operators take their leftmost argument
as non-const references.
The exact rules are:
<itemizedlist>
<listitem>
<para>The left argument of compound assignment operators (<literal>+=</literal>, <literal>*=</literal>, etc.) are stored as references to non-const.</para>
</listitem>
<listitem>
<para>If the left argument of <literal><![CDATA[<<]]></literal> or <literal><![CDATA[>>]]></literal> operator is derived from an instantiation of <literal>basic_ostream</literal> or respectively from <literal>basic_istream</literal>, the argument is stored as a reference to non-const.
For all other types, the argument is stored as a copy.
</para>
</listitem>
<listitem>
<para>
In pointer arithmetic expressions, non-const array types are stored as non-const references.
This is to prevent pointer arithmetic making non-const arrays const.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</section>
</section>
<section id="lambda.le_in_details">
<title>Lambda expressions in details</title>
<para>
This section describes different categories of lambda expressions in details.
We devote a separate section for each of the possible forms of a lambda expression.
</para>
<section id="lambda.placeholders">
<title>Placeholders</title>
<para>
The BLL defines three placeholder types: <literal>placeholder1_type</literal>, <literal>placeholder2_type</literal> and <literal>placeholder3_type</literal>.
BLL has a predefined placeholder variable for each placeholder type: <literal>_1</literal>, <literal>_2</literal> and <literal>_3</literal>.
However, the user is not forced to use these placeholders.
It is easy to define placeholders with alternative names.
This is done by defining new variables of placeholder types.
For example:
<programlisting>boost::lambda::placeholder1_type X;
boost::lambda::placeholder2_type Y;
boost::lambda::placeholder3_type Z;
</programlisting>
With these variables defined, <literal>X += Y * Z</literal> is equivalent to <literal>_1 += _2 * _3</literal>.
</para>
<para>
The use of placeholders in the lambda expression determines whether the resulting function is nullary, unary, binary or 3-ary.
The highest placeholder index is decisive. For example:
<programlisting>
_1 + 5 // unary
_1 * _1 + _1 // unary
_1 + _2 // binary
bind(f, _1, _2, _3) // 3-ary
_3 + 10 // 3-ary
</programlisting>
Note that the last line creates a 3-ary function, which adds <literal>10</literal> to its <emphasis>third</emphasis> argument.
The first two arguments are discarded.
Furthermore, lambda functors only have a minimum arity.
One can always provide more arguments (up the number of supported placeholders)
that is really needed.
The remaining arguments are just discarded.
For example:
<programlisting>
int i, j, k;
_1(i, j, k) // returns i, discards j and k
(_2 + _2)(i, j, k) // returns j+j, discards i and k
</programlisting>
See
<xref linkend="lambda.why_weak_arity"/> for the design rationale behind this
functionality.
</para>
<para>
In addition to these three placeholder types, there is also a fourth placeholder type <literal>placeholderE_type</literal>.
The use of this placeholder is defined in <xref linkend="lambda.exceptions"/> describing exception handling in lambda expressions.
</para>
<para>When an actual argument is supplied for a placeholder, the parameter passing mode is always by reference.
This means that any side-effects to the placeholder are reflected to the actual argument.
For example:
<programlisting>
<![CDATA[int i = 1;
(_1 += 2)(i); // i is now 3
(++_1, cout << _1)(i) // i is now 4, outputs 4]]>
</programlisting>
</para>
</section>
<section id="lambda.operator_expressions">
<title>Operator expressions</title>
<para>
The basic rule is that any C++ operator invocation with at least one argument being a lambda expression is itself a lambda expression.
Almost all overloadable operators are supported.
For example, the following is a valid lambda expression:
<programlisting><![CDATA[cout << _1, _2[_3] = _1 && false]]></programlisting>
</para>
<para>
However, there are some restrictions that originate from the C++ operator overloading rules, and some special cases.
</para>
<section>
<title>Operators that cannot be overloaded</title>
<para>
Some operators cannot be overloaded at all (<literal>::</literal>, <literal>.</literal>, <literal>.*</literal>).
For some operators, the requirements on return types prevent them to be overloaded to create lambda functors.
These operators are <literal>->.</literal>, <literal>-></literal>, <literal>new</literal>, <literal>new[]</literal>, <literal>delete</literal>, <literal>delete[]</literal> and <literal>?:</literal> (the conditional operator).
</para>
</section>
<section id="lambda.assignment_and_subscript">
<title>Assignment and subscript operators</title>
<para>
These operators must be implemented as class members.
Consequently, the left operand must be a lambda expression. For example:
<programlisting>
int i;
_1 = i; // ok
i = _1; // not ok. i is not a lambda expression
</programlisting>
There is a simple solution around this limitation, described in <xref linkend="lambda.delaying_constants_and_variables"/>.
In short,
the left hand argument can be explicitly turned into a lambda functor by wrapping it with a special <literal>var</literal> function:
<programlisting>
var(i) = _1; // ok
</programlisting>
</para>
</section>
<section id="lambda.logical_operators">
<title>Logical operators</title>
<para>
Logical operators obey the short-circuiting evaluation rules. For example, in the following code, <literal>i</literal> is never incremented:
<programlisting>
bool flag = true; int i = 0;
(_1 || ++_2)(flag, i);
</programlisting>
</para>
</section>
<section id="lambda.comma_operator">
<title>Comma operator</title>
<para>
Comma operator is the <quote>statement separator</quote> in lambda expressions.
Since comma is also the separator between arguments in a function call, extra parenthesis are sometimes needed:
<programlisting>
for_each(a.begin(), a.end(), (++_1, cout << _1));
</programlisting>
Without the extra parenthesis around <literal>++_1, cout << _1</literal>, the code would be interpreted as an attempt to call <literal>for_each</literal> with four arguments.
</para>
<para>
The lambda functor created by the comma operator adheres to the C++ rule of always evaluating the left operand before the right one.
In the above example, each element of <literal>a</literal> is first incremented, then written to the stream.
</para>
</section>
<section id="lambda.function_call_operator">
<title>Function call operator</title>
<para>
The function call operators have the effect of evaluating the lambda
functor.
Calls with too few arguments lead to a compile time error.
</para>
</section>
<section id="lambda.member_pointer_operator">
<title>Member pointer operator</title>
<para>
The member pointer operator <literal>operator->*</literal> can be overloaded freely.
Hence, for user defined types, member pointer operator is no special case.
The built-in meaning, however, is a somewhat more complicated case.
The built-in member pointer operator is applied if the left argument is a pointer to an object of some class <literal>A</literal>, and the right hand argument is a pointer to a member of <literal>A</literal>, or a pointer to a member of a class from which <literal>A</literal> derives.
We must separate two cases:
<itemizedlist>
<listitem>
<para>The right hand argument is a pointer to a data member.
In this case the lambda functor simply performs the argument substitution and calls the built-in member pointer operator, which returns a reference to the member pointed to.
For example:
<programlisting>
<![CDATA[struct A { int d; };
A* a = new A();
...
(a ->* &A::d); // returns a reference to a->d
(_1 ->* &A::d)(a); // likewise]]>
</programlisting>
</para>
</listitem>
<listitem>
<para>
The right hand argument is a pointer to a member function.
For a built-in call like this, the result is kind of a delayed member function call.
Such an expression must be followed by a function argument list, with which the delayed member function call is performed.
For example:
<programlisting>
<![CDATA[struct B { int foo(int); };
B* b = new B();
...
(b ->* &B::foo) // returns a delayed call to b->foo
// a function argument list must follow
(b ->* &B::foo)(1) // ok, calls b->foo(1)
(_1 ->* &B::foo)(b); // returns a delayed call to b->foo,
// no effect as such
(_1 ->* &B::foo)(b)(1); // calls b->foo(1)]]>
</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
</section>
</section>
<section id="lambda.bind_expressions">
<title>Bind expressions</title>
<para>
Bind expressions can have two forms:
<!-- TODO: shouldn't really be emphasis, but a variable or something-->
<programlisting>
bind(<parameter>target-function</parameter>, <parameter>bind-argument-list</parameter>)
bind(<parameter>target-member-function</parameter>, <parameter>object-argument</parameter>, <parameter>bind-argument-list</parameter>)
</programlisting>
A bind expression delays the call of a function.
If this <emphasis>target function</emphasis> is <emphasis>n</emphasis>-ary, then the <literal><emphasis>bind-argument-list</emphasis></literal> must contain <emphasis>n</emphasis> arguments as well.
In the current version of the BLL, <inlineequation>0 <= n <= 9</inlineequation> must hold.
For member functions, the number of arguments must be at most <inlineequation>8</inlineequation>, as the object argument takes one argument position.
Basically, the
<emphasis><literal>bind-argument-list</literal></emphasis> must be a valid argument list for the target function, except that any argument can be replaced with a placeholder, or more generally, with a lambda expression.
Note that also the target function can be a lambda expression.
The result of a bind expression is either a nullary, unary, binary or 3-ary function object depending on the use of placeholders in the <emphasis><literal>bind-argument-list</literal></emphasis> (see <xref linkend="lambda.placeholders"/>).
</para>
<para>
The return type of the lambda functor created by the bind expression can be given as an explicitly specified template parameter, as in the following example:
<programlisting>
bind<<emphasis>RET</emphasis>>(<emphasis>target-function</emphasis>, <emphasis>bind-argument-list</emphasis>)
</programlisting>
This is only necessary if the return type of the target function cannot be deduced.
</para>
<para>
The following sections describe the different types of bind expressions.
</para>
<section id="lambda.function_pointers_as_targets">
<title>Function pointers or references as targets</title>
<para>The target function can be a pointer or a reference to a function and it can be either bound or unbound. For example:
<programlisting>
<![CDATA[X foo(A, B, C); A a; B b; C c;
bind(foo, _1, _2, c)(a, b);
bind(&foo, _1, _2, c)(a, b);
bind(_1, a, b, c)(foo);]]>
</programlisting>
The return type deduction always succeeds with this type of bind expressions.
</para>
<para>
Note, that in C++ it is possible to take the address of an overloaded function only if the address is assigned to, or used as an initializer of, a variable, the type of which solves the amibiguity, or if an explicit cast expression is used.
This means that overloaded functions cannot be used in bind expressions directly, e.g.:
<programlisting>
<![CDATA[void foo(int);
void foo(float);
int i;
...
bind(&foo, _1)(i); // error
...
void (*pf1)(int) = &foo;
bind(pf1, _1)(i); // ok
bind(static_cast<void(*)(int)>(&foo), _1)(i); // ok]]>
</programlisting>
</para>
</section>
<section id="member_functions_as_targets">
<title>Member functions as targets</title>
<para>
The syntax for using pointers to member function in bind expression is:
<programlisting>
bind(<parameter>target-member-function</parameter>, <parameter>object-argument</parameter>, <parameter>bind-argument-list</parameter>)
</programlisting>
The object argument can be a reference or pointer to the object, the BLL supports both cases with a uniform interface:
<programlisting>
<![CDATA[bool A::foo(int) const;
A a;
vector<int> ints;
...
find_if(ints.begin(), ints.end(), bind(&A::foo, a, _1));
find_if(ints.begin(), ints.end(), bind(&A::foo, &a, _1));]]>
</programlisting>
Similarly, if the object argument is unbound, the resulting lambda functor can be called both via a pointer or a reference:
<programlisting>
<![CDATA[bool A::foo(int);
list<A> refs;
list<A*> pointers;
...
find_if(refs.begin(), refs.end(), bind(&A::foo, _1, 1));
find_if(pointers.begin(), pointers.end(), bind(&A::foo, _1, 1));]]>
</programlisting>
</para>
<!--%The exact rules for the object argument (whether it is bound, or supplied in the lambda function invoction) are as follows:
%If the target function is a pointer to a member function of some class \snip{A}, then the object argument must be an expression of type \snip{B}, where either
%\begin{itemize}
%\item \snip{B} = \snip{A} or there is an implicit conversion from \snip{B} to \snip{A}.
%\item \snip{B} = \snip{A*}.
%\item \snip{B} = \snip{C*}, where \snip{C} is any class derived form \snip{A}.
%\end{itemize}
%For example:
%\begin{alltt}
%struct A \{
% virtual void f();
% void fc() const;
%\};
%
%struct B : public A \{
% virtual void f();
%\};
%
%struct C \{
% operator A const() \{ return A(); \}
%\};
%
% A a; B b; C c;
% ...
% bind(&A::f, a)();
% bind(&A::f, b)(); // calls B::f
% bind(&A::fc, c)();
%
% bind(&A::f, &a)();
% bind(&A::f, &b)(); // calls B::f
% bind(&A::f, &c)(); // error: no conversion from C* \(\rightarrow\) A,
%\end{alltt}
-->
<para>
Even though the interfaces are the same, there are important semantic differences between using a pointer or a reference as the object argument.
The differences stem from the way <literal>bind</literal>-functions take their parameters, and how the bound parameters are stored within the lambda functor.
The object argument has the same parameter passing and storing mechanism as any other bind argument slot (see <xref linkend="lambda.storing_bound_arguments"/>); it is passed as a const reference and stored as a const copy in the lambda functor.
This creates some asymmetry between the lambda functor and the original member function, and between seemingly similar lambda functors. For example:
<programlisting>
class A {
int i; mutable int j;
public:
A(int ii, int jj) : i(ii), j(jj) {};
void set_i(int x) { i = x; };
void set_j(int x) const { j = x; };
};
</programlisting>
When a pointer is used, the behavior is what the programmer might expect:
<programlisting>
<![CDATA[A a(0,0); int k = 1;
bind(&A::set_i, &a, _1)(k); // a.i == 1
bind(&A::set_j, &a, _1)(k); // a.j == 1]]>
</programlisting>
Even though a const copy of the object argument is stored, the original object <literal>a</literal> is still modified.
This is since the object argument is a pointer, and the pointer is copied, not the object it points to.
When we use a reference, the behaviour is different:
<programlisting>
<![CDATA[A a(0,0); int k = 1;
bind(&A::set_i, a, _1)(k); // error; a const copy of a is stored.
// Cannot call a non-const function set_i
bind(&A::set_j, a, _1)(k); // a.j == 0, as a copy of a is modified]]>
</programlisting>
</para>
<para>
To prevent the copying from taking place, one can use the <literal>ref</literal> or <literal>cref</literal> wrappers (<literal>var</literal> and <literal>constant_ref</literal> would do as well):
<programlisting>
<![CDATA[bind(&A::set_i, ref(a), _1)(k); // a.j == 1
bind(&A::set_j, cref(a), _1)(k); // a.j == 1]]>
</programlisting>
</para>
<para>Note that the preceding discussion is relevant only for bound arguments.
If the object argument is unbound, the parameter passing mode is always by reference.
Hence, the argument <literal>a</literal> is not copied in the calls to the two lambda functors below:
<programlisting>
<![CDATA[A a(0,0);
bind(&A::set_i, _1, 1)(a); // a.i == 1
bind(&A::set_j, _1, 1)(a); // a.j == 1]]>
</programlisting>
</para>
</section>
<section id="lambda.members_variables_as_targets">
<title>Member variables as targets</title>
<para>
A pointer to a member variable is not really a function, but
the first argument to the <literal>bind</literal> function can nevertheless
be a pointer to a member variable.
Invoking such a bind expression returns a reference to the data member.
For example:
<programlisting>
<![CDATA[struct A { int data; };
A a;
bind(&A::data, _1)(a) = 1; // a.data == 1]]>
</programlisting>
The cv-qualifiers of the object whose member is accessed are respected.
For example, the following tries to write into a const location:
<programlisting>
<![CDATA[const A ca = a;
bind(&A::data, _1)(ca) = 1; // error]]>
</programlisting>
</para>
</section>
<section id="lambda.function_objects_as_targets">
<title>Function objects as targets</title>
<para>
Function objects, that is, class objects which have the function call
operator defined, can be used as target functions.
In general, BLL cannot deduce the return type of an arbitrary function object.
However, there are two methods for giving BLL this capability for a certain
function object class.
</para>
<simplesect>
<title>The result_type typedef</title>
<para>
The BLL supports the standard library convention of declaring the return type
of a function object with a member typedef named <literal>result_type</literal> in the
function object class.
Here is a simple example:
<programlisting>
<![CDATA[struct A {
typedef B result_type;
B operator()(X, Y, Z);
};]]>
</programlisting>
If a function object does not define a <literal>result_type</literal> typedef,
the method described below (<literal>sig</literal> template)
is attempted to resolve the return type of the
function object. If a function object defines both <literal>result_type</literal>
and <literal>sig</literal>, <literal>result_type</literal> takes precedence.
</para>
</simplesect>
<simplesect>
<title>The sig template</title>
<para>
Another mechanism that make BLL aware of the return type(s) of a function object is defining
member template struct
<literal><![CDATA[sig<Args>]]></literal> with a typedef
<literal>type</literal> that specifies the return type.
Here is a simple example:
<programlisting>
<![CDATA[struct A {
template <class Args> struct sig { typedef B type; }
B operator()(X, Y, Z);
};]]>
</programlisting>
The template argument <literal>Args</literal> is a
<literal>tuple</literal> (or more precisely a <literal>cons</literal> list)
type <xref linkend="cit:boost::tuple"/>, where the first element
is the function
object type itself, and the remaining elements are the types of
the arguments, with which the function object is being called.
This may seem overly complex compared to defining the <literal>result_type</literal> typedef.
Howver, there are two significant restrictions with using just a simple
typedef to express the return type:
<orderedlist>
<listitem>
<para>
If the function object defines several function call operators, there is no way to specify different result types for them.
</para>
</listitem>
<listitem>
<para>
If the function call operator is a template, the result type may
depend on the template parameters.
Hence, the typedef ought to be a template too, which the C++ language
does not support.
</para>
</listitem>
</orderedlist>
The following code shows an example, where the return type depends on the type
of one of the arguments, and how that dependency can be expressed with the
<literal>sig</literal> template:
<programlisting>
<![CDATA[struct A {
// the return type equals the third argument type:
template<class T1, class T2, class T3>
T3 operator()(const T1& t1, const T2& t2, const T3& t3) const;
template <class Args>
class sig {
// get the third argument type (4th element)
typedef typename
boost::tuples::element<3, Args>::type T3;
public:
typedef typename
boost::remove_cv<T3>::type type;
};
};]]>
</programlisting>
The elements of the <literal>Args</literal> tuple are always
non-reference types.
Moreover, the element types can have a const or volatile qualifier
(jointly referred to as <emphasis>cv-qualifiers</emphasis>), or both.
This is since the cv-qualifiers in the arguments can affect the return type.
The reason for including the potentially cv-qualified function object
type itself into the <literal>Args</literal> tuple, is that the function
object class can contain both const and non-const (or volatile, even
const volatile) function call operators, and they can each have a different
return type.
</para>
<para>
The <literal>sig</literal> template can be seen as a
<emphasis>meta-function</emphasis> that maps the argument type tuple to
the result type of the call made with arguments of the types in the tuple.
As the example above demonstrates, the template can end up being somewhat
complex.
Typical tasks to be performed are the extraction of the relevant types
from the tuple, removing cv-qualifiers etc.
See the Boost type_traits <xref linkend="cit:boost::type_traits"/> and
Tuple <xref linkend="cit:boost::type_traits"/> libraries
for tools that can aid in these tasks.
The <literal>sig</literal> templates are a refined version of a similar
mechanism first introduced in the FC++ library
<xref linkend="cit:fc++"/>.
</para>
</simplesect>
</section>
</section>
<section id="lambda.overriding_deduced_return_type">
<title>Overriding the deduced return type</title>
<para>
The return type deduction system may not be able to deduce the return types of some user defined operators or bind expressions with class objects.
<!-- (see the example in <xref linkend="lambda.parameter_and_return_types"/>).-->
A specia