summaryrefslogtreecommitdiff
path: root/libs/lambda
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-06-25 22:59:01 +0000
committer <>2013-09-27 11:49:28 +0000
commit8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch)
treec09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/lambda
downloadboost-tarball-baserock/morph.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'libs/lambda')
-rw-r--r--libs/lambda/doc/Jamfile.v212
-rw-r--r--libs/lambda/doc/detail/README7
-rw-r--r--libs/lambda/doc/detail/lambda_doc.xml3456
-rw-r--r--libs/lambda/doc/detail/lambda_doc.xsl19
-rw-r--r--libs/lambda/doc/detail/lambda_doc_chunks.xsl19
-rw-r--r--libs/lambda/doc/index.html12
-rw-r--r--libs/lambda/doc/lambda.xml3452
-rw-r--r--libs/lambda/index.html12
-rw-r--r--libs/lambda/test/Jamfile35
-rw-r--r--libs/lambda/test/Makefile89
-rw-r--r--libs/lambda/test/README_gcc2.9x_users6
-rw-r--r--libs/lambda/test/algorithm_test.cpp60
-rw-r--r--libs/lambda/test/bind_tests_advanced.cpp420
-rw-r--r--libs/lambda/test/bind_tests_simple.cpp187
-rw-r--r--libs/lambda/test/bind_tests_simple_f_refs.cpp148
-rw-r--r--libs/lambda/test/bll_and_function.cpp68
-rw-r--r--libs/lambda/test/cast_test.cpp107
-rw-r--r--libs/lambda/test/constructor_tests.cpp265
-rw-r--r--libs/lambda/test/control_structures.cpp123
-rw-r--r--libs/lambda/test/exception_test.cpp621
-rw-r--r--libs/lambda/test/extending_rt_traits.cpp394
-rw-r--r--libs/lambda/test/is_instance_of_test.cpp79
-rw-r--r--libs/lambda/test/istreambuf_test.cpp30
-rw-r--r--libs/lambda/test/member_pointer_test.cpp192
-rw-r--r--libs/lambda/test/operator_tests_simple.cpp431
-rw-r--r--libs/lambda/test/phoenix_control_structures.cpp148
-rw-r--r--libs/lambda/test/result_of_tests.cpp314
-rw-r--r--libs/lambda/test/ret_test.cpp53
-rw-r--r--libs/lambda/test/rvalue_test.cpp57
-rw-r--r--libs/lambda/test/switch_construct.cpp392
30 files changed, 11208 insertions, 0 deletions
diff --git a/libs/lambda/doc/Jamfile.v2 b/libs/lambda/doc/Jamfile.v2
new file mode 100644
index 000000000..1723bb732
--- /dev/null
+++ b/libs/lambda/doc/Jamfile.v2
@@ -0,0 +1,12 @@
+project boost/doc ;
+import boostbook : boostbook ;
+
+# Are these really the correct images??
+path-constant images : ../../spirit/phoenix/doc/html ;
+
+boostbook lambda-doc : lambda.xml
+:
+ <xsl:param>boost.root=../../../..
+ <format>pdf:<xsl:param>img.src.path=$(images)/
+;
+
diff --git a/libs/lambda/doc/detail/README b/libs/lambda/doc/detail/README
new file mode 100644
index 000000000..51d75a9de
--- /dev/null
+++ b/libs/lambda/doc/detail/README
@@ -0,0 +1,7 @@
+- lambda_doc.xml is a DocBook xml file from which the lambda docs are
+generated
+- lambda_doc_chunks.xsl loads the stylesheets that generate a separate
+html-file for each section
+- lambda_doc.xsl loads stylesheets that generate one big html-file
+(you need to edit the paths in these files to make them work)
+
diff --git a/libs/lambda/doc/detail/lambda_doc.xml b/libs/lambda/doc/detail/lambda_doc.xml
new file mode 100644
index 000000000..42522cb38
--- /dev/null
+++ b/libs/lambda/doc/detail/lambda_doc.xml
@@ -0,0 +1,3456 @@
+<?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: 2008-03-22 14:45:55 -0700 (Sat, 22 Mar 2008) $"
+ 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>
+
+ <!-- -->
+
+ <section id="introduction">
+
+ <title>In a nutshell</title>
+
+ <para>
+
+ The Boost Lambda Library (BLL in the sequel) is a C++ template
+ library, which implements 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="sect: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="sect:operator_expressions"/>.
+ </para></listitem>
+
+ <listitem><para>
+ <filename>lambda/bind.hpp</filename> defines <literal>bind</literal> functions for up to 9 arguments, see <xref linkend="sect: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="sect: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="sect: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="sect: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="sect: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="sect:cast_expressions"/>.
+ </para></listitem>
+
+ <listitem><para>
+ <filename>lambda/exceptions.hpp</filename> gives tools for throwing and catching
+ exceptions within lambda functions, <xref linkend="sect: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="sect: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="sect: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="sect: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 = "sect: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 = "sect: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="sect:delaying_constants_and_variables"/>
+
+</para>
+
+
+
+
+
+ </section>
+
+
+ <section id="sect: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="sect:extending_return_type_system"/>).
+ The second is to use a special lambda expression (<literal>ret</literal>) which defines the return type in place (see <xref linkend = "sect: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="sect:nullary_functors_and_ret"/>.
+-->
+ </para>
+ </section>
+
+ <section id="sect: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="sect:rvalues_as_actual_arguments"/>.
+
+
+ </para>
+
+ </section>
+
+
+<section id="sect: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="sect: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="sect:lambda_expressions_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="sect: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="sect: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="sect: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="sect: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="sect: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="sect: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="sect: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="sect: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 &lt;&lt; _1));
+</programlisting>
+
+Without the extra parenthesis around <literal>++_1, cout &lt;&lt; _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="sect: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="sect: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="sect: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 &lt;= n &lt;= 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="sect: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&lt;<emphasis>RET</emphasis>&gt;(<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="sect: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="sect: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="sect: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="sect: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, T2, T3>
+ T3 operator()(const T1& t1, const T2& t2, const T3& t3);
+
+ 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="sect: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="sect:parameter_and_return_types"/>).-->
+A special lambda expression type is provided for stating the return type explicitly and overriding the deduction system.
+To state that the return type of the lambda functor defined by the lambda expression <literal>e</literal> is <literal>T</literal>, you can write:
+
+<programlisting><![CDATA[ret<T>(e);]]></programlisting>
+
+The effect is that the return type deduction is not performed for the lambda expression <literal>e</literal> at all, but instead, <literal>T</literal> is used as the return type.
+Obviously <literal>T</literal> cannot be an arbitrary type, the true result of the lambda functor must be implicitly convertible to <literal>T</literal>.
+For example:
+
+<programlisting>
+<![CDATA[A a; B b;
+C operator+(A, B);
+int operator*(A, B);
+ ...
+ret<D>(_1 + _2)(a, b); // error (C cannot be converted to D)
+ret<C>(_1 + _2)(a, b); // ok
+ret<float>(_1 * _2)(a, b); // ok (int can be converted to float)
+ ...
+struct X {
+ Y operator(int)();
+};
+ ...
+X x; int i;
+bind(x, _1)(i); // error, return type cannot be deduced
+ret<Y>(bind(x, _1))(i); // ok]]>
+</programlisting>
+For bind expressions, there is a short-hand notation that can be used instead of <literal>ret</literal>.
+The last line could alternatively be written as:
+
+<programlisting><![CDATA[bind<Z>(x, _1)(i);]]></programlisting>
+This feature is modeled after the Boost Bind library <xref linkend="cit:boost::bind"/>.
+
+</para>
+
+<para>Note that within nested lambda expressions,
+the <literal>ret</literal> must be used at each subexpression where
+the deduction would otherwise fail.
+For example:
+<programlisting>
+<![CDATA[A a; B b;
+C operator+(A, B); D operator-(C);
+ ...
+ret<D>( - (_1 + _2))(a, b); // error
+ret<D>( - ret<C>(_1 + _2))(a, b); // ok]]>
+</programlisting>
+</para>
+
+<para>If you find yourself using <literal>ret</literal> repeatedly with the same types, it is worth while extending the return type deduction (see <xref linkend="sect:extending_return_type_system"/>).
+</para>
+
+<section id="sect:nullary_functors_and_ret">
+<title>Nullary lambda functors and ret</title>
+
+<para>
+As stated above, the effect of <literal>ret</literal> is to prevent the return type deduction to be performed.
+However, there is an exception.
+Due to the way the C++ template instantiation works, the compiler is always forced to instantiate the return type deduction templates for zero-argument lambda functors.
+This introduces a slight problem with <literal>ret</literal>, best described with an example:
+
+<programlisting>
+<![CDATA[struct F { int operator()(int i) const; };
+F f;
+ ...
+bind(f, _1); // fails, cannot deduce the return type
+ret<int>(bind(f, _1)); // ok
+ ...
+bind(f, 1); // fails, cannot deduce the return type
+ret<int>(bind(f, 1)); // fails as well!]]>
+</programlisting>
+The BLL cannot deduce the return types of the above bind calls, as <literal>F</literal> does not define the typedef <literal>result_type</literal>.
+One would expect <literal>ret</literal> to fix this, but for the nullary lambda functor that results from a bind expression (last line above) this does not work.
+The return type deduction templates are instantiated, even though it would not be necessary and the result is a compilation error.
+</para>
+
+<para>The solution to this is not to use the <literal>ret</literal> function, but rather define the return type as an explicitly specified template parameter in the <literal>bind</literal> call:
+<programlisting>
+<![CDATA[bind<int>(f, 1); // ok]]>
+</programlisting>
+
+The lambda functors created with
+<literal>ret&lt;<parameter>T</parameter>&gt;(bind(<parameter>arg-list</parameter>))</literal> and
+<literal>bind&lt;<parameter>T</parameter>&gt;(<parameter>arg-list</parameter>)</literal> have the exact same functionality &mdash;
+apart from the fact that for some nullary lambda functors the former does not work while the latter does.
+</para>
+</section>
+</section>
+
+
+<section id="sect:delaying_constants_and_variables">
+<title>Delaying constants and variables</title>
+
+<para>
+The unary functions <literal>constant</literal>,
+<literal>constant_ref</literal> and <literal>var</literal> turn their argument into a lambda functor, that implements an identity mapping.
+The former two are for constants, the latter for variables.
+The use of these <emphasis>delayed</emphasis> constants and variables is sometimes necessary due to the lack of explicit syntax for lambda expressions.
+For example:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(), cout << _1 << ' ');
+for_each(a.begin(), a.end(), cout << ' ' << _1);]]>
+</programlisting>
+The first line outputs the elements of <literal>a</literal> separated by spaces, while the second line outputs a space followed by the elements of <literal>a</literal> without any separators.
+The reason for this is that neither of the operands of
+<literal><![CDATA[cout << ' ']]></literal> is a lambda expression, hence <literal><![CDATA[cout << ' ']]></literal> is evaluated immediately.
+
+To delay the evaluation of <literal><![CDATA[cout << ' ']]></literal>, one of the operands must be explicitly marked as a lambda expression.
+This is accomplished with the <literal>constant</literal> function:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(), cout << constant(' ') << _1);]]>
+</programlisting>
+
+The call <literal>constant(' ')</literal> creates a nullary lambda functor which stores the character constant <literal>' '</literal>
+and returns a reference to it when invoked.
+The function <literal>constant_ref</literal> is similar, except that it
+stores a constant reference to its argument.
+
+The <literal>constant</literal> and <literal>consant_ref</literal> are only
+needed when the operator call has side effects, like in the above example.
+</para>
+
+<para>
+Sometimes we need to delay the evaluation of a variable.
+Suppose we wanted to output the elements of a container in a numbered list:
+
+<programlisting>
+<![CDATA[int index = 0;
+for_each(a.begin(), a.end(), cout << ++index << ':' << _1 << '\n');
+for_each(a.begin(), a.end(), cout << ++var(index) << ':' << _1 << '\n');]]>
+</programlisting>
+
+The first <literal>for_each</literal> invocation does not do what we want; <literal>index</literal> is incremented only once, and its value is written into the output stream only once.
+By using <literal>var</literal> to make <literal>index</literal> a lambda expression, we get the desired effect.
+<!-- Note that <literal>var</literal> accepts const objects as well, in which case
+calling <literal>var</literal> equals calling <literal>constant_ref</literal>.-->
+</para>
+
+<para>
+In sum, <literal>var(x)</literal> creates a nullary lambda functor,
+which stores a reference to the variable <literal>x</literal>.
+When the lambda functor is invoked, a reference to <literal>x</literal> is returned.
+</para>
+
+<simplesect>
+<title>Naming delayed constants and variables</title>
+
+<para>
+It is possible to predefine and name a delayed variable or constant outside a lambda expression.
+The templates <literal>var_type</literal>, <literal>constant_type</literal>
+and <literal>constant_ref_type</literal> serve for this purpose.
+They are used as:
+<programlisting>
+<![CDATA[var_type<T>::type delayed_i(var(i));
+constant_type<T>::type delayed_c(constant(c));]]>
+</programlisting>
+The first line defines the variable <literal>delayed_i</literal> which is a delayed version of the variable <literal>i</literal> of type <literal>T</literal>.
+Analogously, the second line defines the constant <literal>delayed_c</literal> as a delayed version of the constant <literal>c</literal>.
+For example:
+
+<programlisting>
+int i = 0; int j;
+for_each(a.begin(), a.end(), (var(j) = _1, _1 = var(i), var(i) = var(j)));
+</programlisting>
+is equivalent to:
+<programlisting>
+<![CDATA[int i = 0; int j;
+var_type<int>::type vi(var(i)), vj(var(j));
+for_each(a.begin(), a.end(), (vj = _1, _1 = vi, vi = vj));]]>
+</programlisting>
+</para>
+<para>
+Here is an example of naming a delayed constant:
+<programlisting>
+<![CDATA[constant_type<char>::type space(constant(' '));
+for_each(a.begin(),a.end(), cout << space << _1);]]>
+</programlisting>
+</para>
+
+</simplesect>
+
+<simplesect>
+<title>About assignment and subscript operators</title>
+
+<para>
+As described in <xref linkend="sect:assignment_and_subscript"/>, assignment and subscripting operators are always defined as member functions.
+This means, that for expressions of the form
+<literal>x = y</literal> or <literal>x[y]</literal> to be interpreted as lambda expressions, the left-hand operand <literal>x</literal> must be a lambda expression.
+Consequently, it is sometimes necessary to use <literal>var</literal> for this purpose.
+We repeat the example from <xref linkend="sect:assignment_and_subscript"/>:
+
+<programlisting>
+int i;
+i = _1; // error
+var(i) = _1; // ok
+</programlisting>
+</para>
+
+<para>
+
+Note that the compound assignment operators <literal>+=</literal>, <literal>-=</literal> etc. can be defined as non-member functions, and thus they are interpreted as lambda expressions even if only the right-hand operand is a lambda expression.
+Nevertheless, it is perfectly ok to delay the left operand explicitly.
+For example, <literal>i += _1</literal> is equivalent to <literal>var(i) += _1</literal>.
+</para>
+</simplesect>
+
+</section>
+
+<section id="sect:lambda_expressions_for_control_structures">
+<title>Lambda expressions for control structures</title>
+
+<para>
+BLL defines several functions to create lambda functors that represent control structures.
+They all take lambda functors as parameters and return <literal>void</literal>.
+To start with an example, the following code outputs all even elements of some container <literal>a</literal>:
+
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(),
+ if_then(_1 % 2 == 0, cout << _1));]]>
+</programlisting>
+</para>
+
+<para>
+The BLL supports the following function templates for control structures:
+
+<programlisting>
+if_then(condition, then_part)
+if_then_else(condition, then_part, else_part)
+if_then_else_return(condition, then_part, else_part)
+while_loop(condition, body)
+while_loop(condition) // no body case
+do_while_loop(condition, body)
+do_while_loop(condition) // no body case
+for_loop(init, condition, increment, body)
+for_loop(init, condition, increment) // no body case
+switch_statement(...)
+</programlisting>
+
+The return types of all control construct lambda functor is
+<literal>void</literal>, except for <literal>if_then_else_return</literal>,
+which wraps a call to the conditional operator
+<programlisting>
+condition ? then_part : else_part
+</programlisting>
+The return type rules for this operator are somewhat complex.
+Basically, if the branches have the same type, this type is the return type.
+If the type of the branches differ, one branch, say of type
+<literal>A</literal>, must be convertible to the other branch,
+say of type <literal>B</literal>.
+In this situation, the result type is <literal>B</literal>.
+Further, if the common type is an lvalue, the return type will be an lvalue
+too.
+</para>
+
+
+<para>
+Delayed variables tend to be commonplace in control structure lambda expressions.
+For instance, here we use the <literal>var</literal> function to turn the arguments of <literal>for_loop</literal> into lambda expressions.
+The effect of the code is to add 1 to each element of a two-dimensional array:
+
+<programlisting>
+<![CDATA[int a[5][10]; int i;
+for_each(a, a+5,
+ for_loop(var(i)=0, var(i)<10, ++var(i),
+ _1[var(i)] += 1));]]>
+</programlisting>
+
+<!--
+As explained in <xref linkend="sect:delaying_constants_and_variables"/>, we can avoid the repeated use of wrapping of <literal>var</literal> if we define it beforehand:
+
+<programlisting>
+<![CDATA[int i;
+var_type<int>::type vi(var(i));
+for_each(a, a+5,
+ for_loop(vi=0, vi<10, ++vi, _1[vi] += 6));]]>
+</programlisting>
+
+-->
+</para>
+
+<para>
+The BLL supports an alternative syntax for control expressions, suggested
+by Joel de Guzmann.
+By overloading the <literal>operator[]</literal> we can
+get a closer resemblance with the built-in control structures:
+
+<programlisting>
+<![CDATA[if_(condition)[then_part]
+if_(condition)[then_part].else_[else_part]
+while_(condition)[body]
+do_[body].while_(condition)
+for_(init, condition, increment)[body]]]>
+</programlisting>
+
+For example, using this syntax the <literal>if_then</literal> example above
+can be written as:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(),
+ if_(_1 % 2 == 0)[ cout << _1 ])]]>
+</programlisting>
+
+As more experience is gained, we may end up deprecating one or the other
+of these syntaces.
+
+</para>
+
+
+
+<section id="sect:switch_statement">
+<title>Switch statement</title>
+</section>
+
+<para>
+The lambda expressions for <literal>switch</literal> control structures are more complex since the number of cases may vary.
+The general form of a switch lambda expression is:
+
+<programlisting>
+switch_statement(<parameter>condition</parameter>,
+ case_statement&lt;<parameter>label</parameter>&gt;(<parameter>lambda expression</parameter>),
+ case_statement&lt;<parameter>label</parameter>&gt;(<parameter>lambda expression</parameter>),
+ ...
+ default_statement(<parameter>lambda expression</parameter>)
+)
+</programlisting>
+
+The <literal><parameter>condition</parameter></literal> argument must be a lambda expression that creates a lambda functor with an integral return type.
+The different cases are created with the <literal>case_statement</literal> functions, and the optional default case with the <literal>default_statement</literal> function.
+The case labels are given as explicitly specified template arguments to <literal>case_statement</literal> functions and
+<literal>break</literal> statements are implicitly part of each case.
+For example, <literal><![CDATA[case_statement<1>(a)]]></literal>, where <literal>a</literal> is some lambda functor, generates the code:
+
+<programlisting>
+case 1:
+ <parameter>evaluate lambda functor</parameter> a;
+ break;
+</programlisting>
+The <literal>switch_statement</literal> function is specialized for up to 9 case statements.
+
+</para>
+
+<para>
+As a concrete example, the following code iterates over some container <literal>v</literal> and ouptuts <quote>zero</quote> for each <literal>0</literal>, <quote>one</quote> for each <literal>1</literal>, and <quote>other: <parameter>n</parameter></quote> for any other value <parameter>n</parameter>.
+Note that another lambda expression is sequenced after the <literal>switch_statement</literal> to output a line break after each element:
+
+<programlisting>
+<![CDATA[std::for_each(v.begin(), v.end(),
+ (
+ switch_statement(
+ _1,
+ case_statement<0>(std::cout << constant("zero")),
+ case_statement<1>(std::cout << constant("one")),
+ default_statement(cout << constant("other: ") << _1)
+ ),
+ cout << constant("\n")
+ )
+);]]>
+</programlisting>
+</para>
+
+</section>
+
+<section id="sect:exceptions">
+<title>Exceptions</title>
+
+<para>
+The BLL provides lambda functors that throw and catch exceptions.
+Lambda functors for throwing exceptions are created with the unary function <literal>throw_exception</literal>.
+The argument to this function is the exception to be thrown, or a lambda functor which creates the exception to be thrown.
+A lambda functor for rethrowing exceptions is created with the nullary <literal>rethrow</literal> function.
+</para>
+
+<para>
+Lambda expressions for handling exceptions are somewhat more complex.
+The general form of a lambda expression for try catch blocks is as follows:
+
+<programlisting>
+try_catch(
+ <parameter>lambda expression</parameter>,
+ catch_exception&lt;<parameter>type</parameter>&gt;(<parameter>lambda expression</parameter>),
+ catch_exception&lt;<parameter>type</parameter>&gt;(<parameter>lambda expression</parameter>),
+ ...
+ catch_all(<parameter>lambda expression</parameter>)
+)
+</programlisting>
+
+The first lambda expression is the try block.
+Each <literal>catch_exception</literal> defines a catch block where the
+explicitly specified template argument defines the type of the exception
+to catch.
+
+The lambda expression within the <literal>catch_exception</literal> defines
+the actions to take if the exception is caught.
+
+Note that the resulting exception handlers catch the exceptions as
+references, i.e., <literal>catch_exception&lt;T&gt;(...)</literal>
+results in the catch block:
+
+<programlisting>
+catch(T&amp; e) { ... }
+</programlisting>
+
+The last catch block can alternatively be a call to
+<literal>catch_exception&lt;<parameter>type</parameter>&gt;</literal>
+or to
+<literal>catch_all</literal>, which is the lambda expression equivalent to
+<literal>catch(...)</literal>.
+
+</para>
+
+<para>
+
+The <xref linkend="ex:exceptions"/> demonstrates the use of the BLL
+exception handling tools.
+The first handler catches exceptions of type <literal>foo_exception</literal>.
+Note the use of <literal>_1</literal> placeholder in the body of the handler.
+</para>
+
+<para>
+The second handler shows how to throw exceptions, and demonstrates the
+use of the <emphasis>exception placeholder</emphasis> <literal>_e</literal>.
+
+It is a special placeholder, which refers to the caught exception object
+within the handler body.
+
+Here we are handling an exception of type <literal>std::exception</literal>,
+which carries a string explaining the cause of the exception.
+
+This explanation can be queried with the zero-argument member
+function <literal>what</literal>.
+
+The expression
+<literal>bind(&amp;std::exception::what, _e)</literal> creates the lambda
+function for making that call.
+
+Note that <literal>_e</literal> cannot be used outside of an exception handler lambda expression.
+<!--Violating this rule is caught by the compiler.-->
+
+The last line of the second handler constructs a new exception object and
+throws that with <literal>throw exception</literal>.
+
+Constructing and destructing objects within lambda expressions is
+explained in <xref linkend="sect:construction_and_destruction"/>
+</para>
+
+<para>
+Finally, the third handler (<literal>catch_all</literal>) demonstrates
+rethrowing exceptions.
+</para>
+
+<example id="ex:exceptions">
+<title>Throwing and handling exceptions in lambda expressions.</title>
+<programlisting>
+<![CDATA[for_each(
+ a.begin(), a.end(),
+ try_catch(
+ bind(foo, _1), // foo may throw
+ catch_exception<foo_exception>(
+ cout << constant("Caught foo_exception: ")
+ << "foo was called with argument = " << _1
+ ),
+ catch_exception<std::exception>(
+ cout << constant("Caught std::exception: ")
+ << bind(&std::exception::what, _e),
+ throw_exception(bind(constructor<bar_exception>(), _1)))
+ ),
+ catch_all(
+ (cout << constant("Unknown"), rethrow())
+ )
+ )
+);]]>
+</programlisting>
+</example>
+
+</section>
+
+<section id="sect:construction_and_destruction">
+<title>Construction and destruction</title>
+
+
+<para>
+Operators <literal>new</literal> and <literal>delete</literal> can be
+overloaded, but their return types are fixed.
+
+Particularly, the return types cannot be lambda functors,
+which prevents them to be overloaded for lambda expressions.
+
+It is not possible to take the address of a constructor,
+hence constructors cannot be used as target functions in bind expressions.
+
+The same is true for destructors.
+
+As a way around these constraints, BLL defines wrapper classes for
+<literal>new</literal> and <literal>delete</literal> calls,
+as well as for constructors and destructors.
+
+Instances of these classes are function objects, that can be used as
+target functions of bind expressions.
+
+For example:
+
+<programlisting>
+<![CDATA[int* a[10];
+for_each(a, a+10, _1 = bind(new_ptr<int>()));
+for_each(a, a+10, bind(delete_ptr(), _1));]]>
+</programlisting>
+
+The <literal>new_ptr&lt;int&gt;()</literal> expression creates
+a function object that calls <literal>new int()</literal> when invoked,
+and wrapping that inside <literal>bind</literal> makes it a lambda functor.
+
+In the same way, the expression <literal>delete_ptr()</literal> creates
+a function object that invokes <literal>delete</literal> on its argument.
+
+Note that <literal>new_ptr&lt;<parameter>T</parameter>&gt;()</literal>
+can take arguments as well.
+
+They are passed directly to the constructor invocation and thus allow
+calls to constructors which take arguments.
+
+</para>
+
+<para>
+
+As an example of constructor calls in lambda expressions,
+the following code reads integers from two containers <literal>x</literal>
+and <literal>y</literal>,
+constructs pairs out of them and inserts them into a third container:
+
+<programlisting>
+<![CDATA[vector<pair<int, int> > v;
+transform(x.begin(), x.end(), y.begin(), back_inserter(v),
+ bind(constructor<pair<int, int> >(), _1, _2));]]>
+</programlisting>
+
+<xref linkend="table:constructor_destructor_fos"/> lists all the function
+objects related to creating and destroying objects,
+ showing the expression to create and call the function object,
+and the effect of evaluating that expression.
+
+</para>
+
+
+
+<table id="table:constructor_destructor_fos">
+<title>Construction and destruction related function objects.</title>
+<tgroup cols="2">
+<thead>
+<row>
+<entry>Function object call</entry>
+<entry>Wrapped expression</entry>
+</row>
+</thead>
+<tbody>
+<row>
+<entry><literal>constructor&lt;T&gt;()(<parameter>arg_list</parameter>)</literal></entry>
+<entry>T(<parameter>arg_list</parameter>)</entry>
+</row>
+<row>
+<entry><literal>destructor()(a)</literal></entry>
+<entry><literal>a.~A()</literal>, where <literal>a</literal> is of type <literal>A</literal></entry>
+</row>
+<row>
+<entry><literal>destructor()(pa)</literal></entry>
+<entry><literal>pa->~A()</literal>, where <literal>pa</literal> is of type <literal>A*</literal></entry>
+</row>
+<row>
+<entry><literal>new_ptr&lt;T&gt;()(<parameter>arg_list</parameter>)</literal></entry>
+<entry><literal>new T(<parameter>arg_list</parameter>)</literal></entry>
+</row>
+<row>
+<entry><literal>new_array&lt;T&gt;()(sz)</literal></entry>
+<entry><literal>new T[sz]</literal></entry>
+</row>
+<row>
+<entry><literal>delete_ptr()(p)</literal></entry>
+<entry><literal>delete p</literal></entry>
+</row>
+<row>
+<entry><literal>delete_array()(p)</literal></entry>
+<entry><literal>delete p[]</literal></entry>
+</row>
+
+
+</tbody>
+</tgroup>
+</table>
+
+</section>
+
+
+<section>
+<title>Special lambda expressions</title>
+
+<section>
+<title>Preventing argument substitution</title>
+
+<para>
+When a lambda functor is called, the default behavior is to substitute
+the actual arguments for the placeholders within all subexpressions.
+
+This section describes the tools to prevent the substitution and
+evaluation of a subexpression, and explains when these tools should be used.
+</para>
+
+
+<para>
+The arguments to a bind expression can be arbitrary lambda expressions,
+e.g., other bind expressions.
+
+For example:
+
+<programlisting>
+int foo(int); int bar(int);
+...
+int i;
+bind(foo, bind(bar, _1)(i);
+</programlisting>
+
+The last line makes the call <literal>foo(bar(i));</literal>
+
+Note that the first argument in a bind expression, the target function,
+is no exception, and can thus be a bind expression too.
+
+The innermost lambda functor just has to return something that can be used
+as a target function: another lambda functor, function pointer,
+pointer to member function etc.
+
+For example, in the following code the innermost lambda functor makes
+a selection between two functions, and returns a pointer to one of them:
+
+<programlisting>
+int add(int a, int b) { return a+b; }
+int mul(int a, int b) { return a*b; }
+
+int(*)(int, int) add_or_mul(bool x) {
+ return x ? add : mul;
+}
+
+bool condition; int i; int j;
+...
+bind(bind(&amp;add_or_mul, _1), _2, _3)(condition, i, j);
+</programlisting>
+
+</para>
+
+
+
+<section id="sect:unlambda">
+<title>Unlambda</title>
+
+<para>A nested bind expression may occur inadvertently,
+if the target function is a variable with a type that depends on a
+template parameter.
+
+Typically the target function could be a formal parameter of a
+function template.
+
+In such a case, the programmer may not know whether the target function is a lambda functor or not.
+</para>
+
+<para>Consider the following function template:
+
+<programlisting>
+<![CDATA[template<class F>
+int nested(const F& f) {
+ int x;
+ ...
+ bind(f, _1)(x);
+ ...
+}]]>
+</programlisting>
+
+Somewhere inside the function the formal parameter
+<literal>f</literal> is used as a target function in a bind expression.
+
+In order for this <literal>bind</literal> call to be valid,
+<literal>f</literal> must be a unary function.
+
+Suppose the following two calls to <literal>nested</literal> are made:
+
+<programlisting>
+<![CDATA[int foo(int);
+int bar(int, int);
+nested(&foo);
+nested(bind(bar, 1, _1));]]>
+</programlisting>
+
+Both are unary functions, or function objects, with appropriate argument
+and return types, but the latter will not compile.
+
+In the latter call, the bind expression inside <literal>nested</literal>
+will become:
+
+<programlisting>
+bind(bind(bar, 1, _1), _1)
+</programlisting>
+
+When this is invoked with <literal>x</literal>,
+after substituitions we end up trying to call
+
+<programlisting>
+bar(1, x)(x)
+</programlisting>
+
+which is an error.
+
+The call to <literal>bar</literal> returns int,
+not a unary function or function object.
+</para>
+
+<para>
+In the example above, the intent of the bind expression in the
+<literal>nested</literal> function is to treat <literal>f</literal>
+as an ordinary function object, instead of a lambda functor.
+
+The BLL provides the function template <literal>unlambda</literal> to
+express this: a lambda functor wrapped inside <literal>unlambda</literal>
+is not a lambda functor anymore, and does not take part into the
+argument substitution process.
+
+Note that for all other argument types <literal>unlambda</literal> is
+an identity operation, except for making non-const objects const.
+</para>
+
+<para>
+Using <literal>unlambda</literal>, the <literal>nested</literal>
+function is written as:
+
+<programlisting>
+<![CDATA[template<class F>
+int nested(const F& f) {
+ int x;
+ ...
+ bind(unlambda(f), _1)(x);
+ ...
+}]]>
+</programlisting>
+
+</para>
+
+</section>
+
+<section>
+<title>Protect</title>
+
+<para>
+The <literal>protect</literal> function is related to unlambda.
+
+It is also used to prevent the argument substitution taking place,
+but whereas <literal>unlambda</literal> turns a lambda functor into
+an ordinary function object for good, <literal>protect</literal> does
+this temporarily, for just one evaluation round.
+
+For example:
+
+<programlisting>
+int x = 1, y = 10;
+(_1 + protect(_1 + 2))(x)(y);
+</programlisting>
+
+The first call substitutes <literal>x</literal> for the leftmost
+<literal>_1</literal>, and results in another lambda functor
+<literal>x + (_1 + 2)</literal>, which after the call with
+<literal>y</literal> becomes <literal>x + (y + 2)</literal>,
+and thus finally 13.
+</para>
+
+<para>
+Primary motivation for including <literal>protect</literal> into the library,
+was to allow nested STL algorithm invocations
+(<xref linkend="sect:nested_stl_algorithms"/>).
+</para>
+
+</section>
+
+</section>
+
+<section id="sect:rvalues_as_actual_arguments">
+<title>Rvalues as actual arguments to lambda functors</title>
+
+ <para><emphasis>This section and all of its subsections
+ are no longer (or currently) relevant;
+ acual arguments can be non-const rvalues and these workarounds are thus
+ not needed.
+ The section can, however, become relevant again, if in the future BLL will support
+ lambda functors with higher arities than 3.</emphasis></para>
+
+<para>
+Actual arguments to the lambda functors cannot be non-const rvalues.
+This is due to a deliberate design decision: either we have this restriction,
+or there can be no side-effects to the actual arguments.
+
+There are ways around this limitation.
+
+We repeat the example from section
+<xref linkend="sect:actual_arguments_to_lambda_functors"/> and list the
+different solutions:
+
+<programlisting>
+int i = 1; int j = 2;
+(_1 + _2)(i, j); // ok
+(_1 + _2)(1, 2); // error (!)
+</programlisting>
+
+<orderedlist>
+<listitem>
+<para>
+If the rvalue is of a class type, the return type of the function that
+creates the rvalue should be defined as const.
+Due to an unfortunate language restriction this does not work for
+built-in types, as built-in rvalues cannot be const qualified.
+</para>
+</listitem>
+
+<listitem>
+<para>
+If the lambda function call is accessible, the <literal>make_const</literal>
+function can be used to <emphasis>constify</emphasis> the rvalue. E.g.:
+
+<programlisting>
+(_1 + _2)(make_const(1), make_const(2)); // ok
+</programlisting>
+
+Commonly the lambda function call site is inside a standard algorithm
+function template, preventing this solution to be used.
+
+</para>
+</listitem>
+
+<listitem>
+<para>
+If neither of the above is possible, the lambda expression can be wrapped
+in a <literal>const_parameters</literal> function.
+It creates another type of lambda functor, which takes its arguments as
+const references. For example:
+
+<programlisting>
+const_parameters(_1 + _2)(1, 2); // ok
+</programlisting>
+
+Note that <literal>const_parameters</literal> makes all arguments const.
+Hence, in the case were one of the arguments is a non-const rvalue,
+and another argument needs to be passed as a non-const reference,
+this approach cannot be used.
+</para>
+
+</listitem>
+
+<listitem>
+<para>If none of the above is possible, there is still one solution,
+which unfortunately can break const correctness.
+
+The solution is yet another lambda functor wrapper, which we have named
+<literal>break_const</literal> to alert the user of the potential dangers
+of this function.
+
+The <literal>break_const</literal> function creates a lambda functor that
+takes its arguments as const, and casts away constness prior to the call
+to the original wrapped lambda functor.
+
+For example:
+<programlisting>
+int i;
+...
+(_1 += _2)(i, 2); // error, 2 is a non-const rvalue
+const_parameters(_1 += _2)(i, 2); // error, i becomes const
+break_const(_1 += _2)(i, 2); // ok, but dangerous
+</programlisting>
+
+Note, that the results of <literal> break_const</literal> or
+<literal>const_parameters</literal> are not lambda functors,
+so they cannot be used as subexpressions of lambda expressions. For instance:
+
+<programlisting>
+break_const(_1 + _2) + _3; // fails.
+const_parameters(_1 + _2) + _3; // fails.
+</programlisting>
+
+However, this kind of code should never be necessary,
+since calls to sub lambda functors are made inside the BLL,
+and are not affected by the non-const rvalue problem.
+</para>
+</listitem>
+
+</orderedlist>
+
+</para>
+</section>
+
+</section>
+
+
+<section>
+<title>Casts, sizeof and typeid</title>
+
+<section id="sect:cast_expressions">
+<title>
+Cast expressions
+</title>
+<para>
+The BLL defines its counterparts for the four cast expressions
+<literal>static_cast</literal>, <literal>dynamic_cast</literal>,
+<literal>const_cast</literal> and <literal>reinterpret_cast</literal>.
+
+The BLL versions of the cast expressions have the prefix
+<literal>ll_</literal>.
+
+The type to cast to is given as an explicitly specified template argument,
+and the sole argument is the expression from which to perform the cast.
+
+If the argument is a lambda functor, the lambda functor is evaluated first.
+
+For example, the following code uses <literal>ll_dynamic_cast</literal>
+to count the number of <literal>derived</literal> instances in the container
+<literal>a</literal>:
+
+<programlisting>
+<![CDATA[class base {};
+class derived : public base {};
+
+vector<base*> a;
+...
+int count = 0;
+for_each(a.begin(), a.end(),
+ if_then(ll_dynamic_cast<derived*>(_1), ++var(count)));]]>
+</programlisting>
+</para>
+</section>
+
+<section>
+<title>Sizeof and typeid</title>
+<para>
+The BLL counterparts for these expressions are named
+<literal>ll_sizeof</literal> and <literal>ll_typeid</literal>.
+
+Both take one argument, which can be a lambda expression.
+The lambda functor created wraps the <literal>sizeof</literal> or
+<literal>typeid</literal> call, and when the lambda functor is called
+the wrapped operation is performed.
+
+For example:
+
+<programlisting>
+<![CDATA[vector<base*> a;
+...
+for_each(a.begin(), a.end(),
+ cout << bind(&type_info::name, ll_typeid(*_1)));]]>
+</programlisting>
+
+Here <literal>ll_typeid</literal> creates a lambda functor for
+calling <literal>typeid</literal> for each element.
+
+The result of a <literal>typeid</literal> call is an instance of
+the <literal>type_info</literal> class, and the bind expression creates
+a lambda functor for calling the <literal>name</literal> member
+function of that class.
+
+</para>
+</section>
+
+
+
+</section>
+
+<section id="sect:nested_stl_algorithms">
+<title>Nesting STL algorithm invocations</title>
+
+<para>
+The BLL defines common STL algorithms as function object classes,
+instances of which can be used as target functions in bind expressions.
+For example, the following code iterates over the elements of a
+two-dimensional array, and computes their sum.
+
+<programlisting>
+int a[100][200];
+int sum = 0;
+
+std::for_each(a, a + 100,
+ bind(ll::for_each(), _1, _1 + 200, protect(sum += _1)));
+</programlisting>
+
+The BLL versions of the STL algorithms are classes, which define the function call operator (or several overloaded ones) to call the corresponding function templates in the <literal>std</literal> namespace.
+All these structs are placed in the subnamespace <literal>boost::lambda:ll</literal>.
+<!--The supported algorithms are listed in <xref linkend="table:nested_algorithms"/>.-->
+</para>
+
+<para>
+Note that there is no easy way to express an overloaded member function
+call in a lambda expression.
+
+This limits the usefulness of nested STL algorithms, as for instance
+the <literal>begin</literal> function has more than one overloaded
+definitions in container templates.
+
+In general, something analogous to the pseudo-code below cannot be written:
+
+<programlisting>
+std::for_each(a.begin(), a.end(),
+ bind(ll::for_each(), _1.begin(), _1.end(), protect(sum += _1)));
+</programlisting>
+
+Some aid for common special cases can be provided though.
+
+The BLL defines two helper function object classes,
+<literal>call_begin</literal> and <literal>call_end</literal>,
+which wrap a call to the <literal>begin</literal> and, respectively,
+<literal>end</literal> functions of a container, and return the
+<literal>const_iterator</literal> type of the container.
+
+With these helper templates, the above code becomes:
+<programlisting>
+std::for_each(a.begin(), a.end(),
+ bind(ll::for_each(),
+ bind(call_begin(), _1), bind(call_end(), _1),
+ protect(sum += _1)));
+</programlisting>
+
+</para>
+
+<!--
+<table id="table:nested_algorithms">
+<title>The nested STL algorithms.</title>
+<tgroup cols="1">
+<thead>
+<trow><entry>Otsikko</entry></trow>
+</thead>
+<tbody>
+<row><entry><literal>for_each</literal></entry></row>
+<row><entry><literal>find</literal></entry></row>
+<row><entry><literal>find_if</literal></entry></row>
+<row><entry><literal>find_end</literal></entry></row>
+<row><entry><literal>find_first_of</literal></entry></row>
+<row><entry><literal>transform</literal></entry></row>
+</tbody>
+</tgroup>
+
+</table>
+
+-->
+
+</section>
+
+
+</section>
+
+
+<!--
+<section>
+<title>Common gothcas</title>
+
+calling member functions a.begin()
+
+calling templated functions ...
+
+</section>
+
+-->
+
+<section id="sect:extending_return_type_system">
+<title>Extending return type deduction system</title>
+
+<para>
+<!--The <xref linkend = "sect:overriding_deduced_return_type"/> showed how to make BLL aware of the return type of a function object in bind expressions.-->
+
+In this section, we explain how to extend the return type deduction system
+to cover user defined operators.
+
+In many cases this is not necessary,
+as the BLL defines default return types for operators.
+
+For example, the default return type for all comparison operators is
+<literal>bool</literal>, and as long as the user defined comparison operators
+have a bool return type, there is no need to write new specializations
+for the return type deduction classes.
+
+Sometimes this cannot be avoided, though.
+
+</para>
+
+<para>
+The overloadable user defined operators are either unary or binary.
+
+For each arity, there are two traits templates that define the
+return types of the different operators.
+
+Hence, the return type system can be extended by providing more
+specializations for these templates.
+
+The templates for unary functors are
+
+<literal>
+<![CDATA[plain_return_type_1<Action, A>]]>
+</literal>
+
+and
+
+<literal>
+<![CDATA[return_type_1<Action, A>]]>
+</literal>, and
+
+<literal>
+<![CDATA[plain_return_type_2<Action, A, B>]]>
+</literal>
+
+and
+
+<literal>
+<![CDATA[return_type_2<Action, A, B>]]>
+</literal>
+
+respectively for binary functors.
+
+</para>
+
+<para>
+The first parameter (<literal>Action</literal>) to all these templates
+is the <emphasis>action</emphasis> class, which specifies the operator.
+
+Operators with similar return type rules are grouped together into
+<emphasis>action groups</emphasis>,
+and only the action class and action group together define the operator
+unambiguously.
+
+As an example, the action type
+<literal><![CDATA[arithmetic_action<plus_action>]]></literal> stands for
+<literal>operator+</literal>.
+
+The complete listing of different action types is shown in
+<xref linkend="table:actions"/>.
+</para>
+
+<para>
+The latter parameters, <literal>A</literal> in the unary case,
+or <literal>A</literal> and <literal>B</literal> in the binary case,
+stand for the argument types of the operator call.
+
+The two sets of templates,
+<literal>plain_return_type_<parameter>n</parameter></literal> and
+<literal>return_type_<parameter>n</parameter></literal>
+(<parameter>n</parameter> is 1 or 2) differ in the way how parameter types
+are presented to them.
+
+For the former templates, the parameter types are always provided as
+non-reference types, and do not have const or volatile qualifiers.
+
+This makes specializing easy, as commonly one specialization for each
+user defined operator, or operator group, is enough.
+
+On the other hand, if a particular operator is overloaded for different
+cv-qualifications of the same argument types,
+and the return types of these overloaded versions differ, a more fine-grained control is needed.
+
+Hence, for the latter templates, the parameter types preserve the
+cv-qualifiers, and are non-reference types as well.
+
+The downside is, that for an overloaded set of operators of the
+kind described above, one may end up needing up to
+16 <literal>return_type_2</literal> specializations.
+</para>
+
+<para>
+Suppose the user has overloaded the following operators for some user defined
+types <literal>X</literal>, <literal>Y</literal> and <literal>Z</literal>:
+
+<programlisting>
+<![CDATA[Z operator+(const X&, const Y&);
+Z operator-(const X&, const Y&);]]>
+</programlisting>
+
+Now, one can add a specialization stating, that if the left hand argument
+is of type <literal>X</literal>, and the right hand one of type
+<literal>Y</literal>, the return type of all such binary arithmetic
+operators is <literal>Z</literal>:
+
+<programlisting>
+<![CDATA[namespace boost {
+namespace lambda {
+
+template<class Act>
+struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+}
+}]]>
+</programlisting>
+
+Having this specialization defined, BLL is capable of correctly
+deducing the return type of the above two operators.
+
+Note, that the specializations must be in the same namespace,
+<literal>::boost::lambda</literal>, with the primary template.
+
+For brevity, we do not show the namespace definitions in the examples below.
+</para>
+
+<para>
+It is possible to specialize on the level of an individual operator as well,
+in addition to providing a specialization for a group of operators.
+Say, we add a new arithmetic operator for argument types <literal>X</literal>
+and <literal>Y</literal>:
+
+<programlisting>
+<![CDATA[X operator*(const X&, const Y&);]]>
+</programlisting>
+
+Our first rule for all arithmetic operators specifies that the return
+type of this operator is <literal>Z</literal>,
+which obviously is not the case.
+Hence, we provide a new rule for the multiplication operator:
+
+<programlisting>
+<![CDATA[template<>
+struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
+ typedef X type;
+};]]>
+</programlisting>
+</para>
+
+<para>
+The specializations can define arbitrary mappings from the argument types
+to the return type.
+
+Suppose we have some mathematical vector type, templated on the element type:
+
+<programlisting>
+<![CDATA[template <class T> class my_vector;]]>
+</programlisting>
+
+Suppose the addition operator is defined between any two
+<literal>my_vector</literal> instantiations,
+as long as the addition operator is defined between their element types.
+
+Furthermore, the element type of the resulting <literal>my_vector</literal>
+is the same as the result type of the addition between the element types.
+
+E.g., adding <literal><![CDATA[my_vector<int>]]></literal> and
+<literal><![CDATA[my_vector<double>]]></literal> results in
+<literal><![CDATA[my_vector<double>]]></literal>.
+
+The BLL has traits classes to perform the implicit built-in and standard
+type conversions between integral, floating point, and complex classes.
+
+Using BLL tools, the addition operator described above can be defined as:
+
+<programlisting>
+<![CDATA[template<class A, class B>
+my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type>
+operator+(const my_vector<A>& a, const my_vector<B>& b)
+{
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
+ return my_vector<res_type>();
+}]]>
+</programlisting>
+</para>
+
+<para>
+To allow BLL to deduce the type of <literal>my_vector</literal>
+additions correctly, we can define:
+
+<programlisting>
+<![CDATA[template<class A, class B>
+class plain_return_type_2<arithmetic_action<plus_action>,
+ my_vector<A>, my_vector<B> > {
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
+public:
+ typedef my_vector<res_type> type;
+};]]>
+</programlisting>
+Note, that we are reusing the existing specializations for the
+BLL <literal>return_type_2</literal> template,
+which require that the argument types are references.
+</para>
+
+<!-- TODO: is an example of specifying the other level needed at all -->
+<!-- TODO: comma operator is a special case for that -->
+
+<table id = "table:actions">
+<title>Action types</title>
+<tgroup cols="2">
+<tbody>
+
+<row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[arithmetic_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[arithmetic_action<minus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[arithmetic_action<multiply_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[/]]></literal></entry><entry><literal><![CDATA[arithmetic_action<divide_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[%]]></literal></entry><entry><literal><![CDATA[arithmetic_action<remainder_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<minus_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[bitwise_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[|]]></literal></entry><entry><literal><![CDATA[bitwise_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[~]]></literal></entry><entry><literal><![CDATA[bitwise_action<not_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[^]]></literal></entry><entry><literal><![CDATA[bitwise_action<xor_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<<]]></literal></entry><entry><literal><![CDATA[bitwise_action<leftshift_action_no_stream>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>>]]></literal></entry><entry><literal><![CDATA[bitwise_action<rightshift_action_no_stream>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&&]]></literal></entry><entry><literal><![CDATA[logical_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[||]]></literal></entry><entry><literal><![CDATA[logical_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[!]]></literal></entry><entry><literal><![CDATA[logical_action<not_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[<]]></literal></entry><entry><literal><![CDATA[relational_action<less_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>]]></literal></entry><entry><literal><![CDATA[relational_action<greater_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<=]]></literal></entry><entry><literal><![CDATA[relational_action<lessorequal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>=]]></literal></entry><entry><literal><![CDATA[relational_action<greaterorequal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[==]]></literal></entry><entry><literal><![CDATA[relational_action<equal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[!=]]></literal></entry><entry><literal><![CDATA[relational_action<notequal_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[+=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<minus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<multiply_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[/=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<divide_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[%=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<remainder_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[=|]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[^=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<xor_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<<=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<leftshift_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>>=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<rightshift_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<increment_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<decrement_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<increment_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<decrement_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[other_action<address_of_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[other_action<contents_of_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[,]]></literal></entry><entry><literal><![CDATA[other_action<comma_action>]]></literal></entry></row>
+
+</tbody>
+</tgroup>
+</table>
+
+</section>
+
+
+<section>
+<title>Practical considerations</title>
+
+
+<section>
+<title>Performance</title>
+
+<para>In theory, all overhead of using STL algorithms and lambda functors
+compared to hand written loops can be optimized away, just as the overhead
+from standard STL function objects and binders can.
+
+Depending on the compiler, this can also be true in practice.
+We ran two tests with the GCC 3.0.4 compiler on 1.5 GHz Intel Pentium 4.
+The optimization flag -03 was used.
+</para>
+
+<para>
+In the first test we compared lambda functors against explicitly written
+function objects.
+We used both of these styles to define unary functions which multiply the
+argument repeatedly by itself.
+We started with the identity function, going up to
+x<superscript>5</superscript>.
+The expressions were called inside a <literal>std::transform</literal> loop,
+reading the argument from one <literal><![CDATA[std::vector<int>]]></literal>
+and placing the result into another.
+The length of the vectors was 100 elements.
+The running times are listed in
+<xref linkend="table:increasing_arithmetic_test"/>.
+
+We can observe that there is no significant difference between the
+two approaches.
+</para>
+
+<para>
+In the second test we again used <literal>std::transform</literal> to
+perform an operation to each element in a 100-element long vector.
+This time the element type of the vectors was <literal>double</literal>
+and we started with very simple arithmetic expressions and moved to
+more complex ones.
+The running times are listed in <xref linkend="table:ll_vs_stl_test"/>.
+
+Here, we also included classic STL style unnamed functions into tests.
+We do not show these expressions, as they get rather complex.
+For example, the
+last expression in <xref linkend="table:ll_vs_stl_test"/> written with
+classic STL tools contains 7 calls to <literal>compose2</literal>,
+8 calls to <literal>bind1st</literal>
+and altogether 14 constructor invocations for creating
+<literal>multiplies</literal>, <literal>minus</literal>
+and <literal>plus</literal> objects.
+
+In this test the BLL expressions are a little slower (roughly 10% on average,
+less than 14% in all cases)
+than the corresponding hand-written function objects.
+The performance hit is a bit greater with classic STL expressions,
+up to 27% for the simplest expressios.
+</para>
+
+<para>
+The tests suggest that the BLL does not introduce a loss of performance
+compared to STL function objects.
+With a reasonable optimizing compiler, one should expect the performance characteristics be comparable to using classic STL.
+Moreover, with simple expressions the performance can be expected to be close
+to that of explicitly written function objects.
+
+<!-- We repeated both tests with the KAI C++ 4.0f compiler (using +K2 -O3 flags),
+generally considered a good optimizing compiler.
+We do not list the results here, since the running times for the two alternatives in the first test were essentially the same, just as the running times
+for the three different alternatives in the second test.
+These tests suggest there to be no performance penalty at all
+with a good optimizing compiler.
+-->
+
+Note however, that evaluating a lambda functor consist of a sequence of calls to small functions that are declared inline.
+If the compiler fails to actually expand these functions inline,
+the performance can suffer.
+The running time can more than double if this happens.
+Although the above tests do not include such an expression, we have experienced
+this for some seemingly simple expressions.
+
+
+<table id = "table:increasing_arithmetic_test">
+<title>Test 1. CPU time of expressions with integer multiplication written as a lambda expression and as a traditional hand-coded function object class.
+The running times are expressed in arbitrary units.</title>
+<tgroup cols="3">
+<thead>
+<row>
+<entry>expression</entry><entry>lambda expression</entry><entry>hand-coded function object</entry></row>
+</thead>
+
+<tbody>
+
+<row>
+<entry>x</entry><entry>240</entry><entry>230</entry>
+</row>
+
+<row>
+<entry>x*x</entry><entry>340</entry><entry>350</entry>
+</row>
+
+<row>
+<entry>x*x*x</entry><entry>770</entry><entry>760</entry>
+</row>
+
+<row>
+<entry>x*x*x*x</entry><entry>1180</entry><entry>1210</entry>
+</row>
+
+<row>
+<entry>x*x*x*x*x</entry><entry>1950</entry><entry>1910</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+</para>
+
+<!--
+16:19:49 bench [601] ./arith.out 100 1000000
+
+Number of elements = 100
+L1 : 240
+L2 : 340
+L3 : 770
+L4 : 1180
+L5 : 1950
+
+P2 : 1700
+P3 : 2130
+P4 : 2530
+P5 : 3000
+
+F1 : 230
+F2 : 350
+F3 : 760
+F4 : 1210
+F5 : 1910
+
+
+Number of elements = 100
+Number of outer_iters = 1000000
+L1 : 330
+L2 : 350
+L3 : 470
+L4 : 620
+L5 : 1660
+LP : 1230
+C1 : 370
+C2 : 370
+C3 : 500
+C4 : 670
+C5 : 1660
+CP : 1770
+F1 : 290
+F2 : 310
+F3 : 420
+F4 : 600
+F5 : 1460
+FP : 1040
+
+-->
+
+
+<para>
+<table id = "table:ll_vs_stl_test">
+<title>Test 2. CPU time of arithmetic expressions written as lambda
+expressions, as classic STL unnamed functions (using <literal>compose2</literal>, <literal>bind1st</literal> etc.) and as traditional hand-coded function object classes.
+Using BLL terminology,
+<literal>a</literal> and <literal>b</literal> are bound arguments in the expressions, and <literal>x</literal> is open.
+All variables were of types <literal>double</literal>.
+The running times are expressed in arbitrary units.</title>
+<tgroup cols="4">
+<thead>
+<row>
+<entry>expression</entry><entry>lambda expression</entry><entry>classic STL expression</entry><entry>hand-coded function object</entry></row>
+</thead>
+
+<tbody>
+
+<row>
+<entry>ax</entry><entry>330</entry><entry>370</entry><entry>290</entry>
+</row>
+
+<row>
+<entry>-ax</entry><entry>350</entry><entry>370</entry><entry>310</entry>
+</row>
+
+<row>
+<entry>ax-(a+x)</entry><entry>470</entry><entry>500</entry><entry>420</entry>
+</row>
+
+<row>
+<entry>(ax-(a+x))(a+x)</entry><entry>620</entry><entry>670</entry><entry>600</entry>
+</row>
+
+<row>
+<entry>((ax) - (a+x))(bx - (b+x))(ax - (b+x))(bx - (a+x))</entry><entry>1660</entry><entry>1660</entry><entry>1460</entry>
+</row>
+
+</tbody>
+</tgroup>
+
+</table>
+</para>
+
+
+<para>Some additional performance testing with an earlier version of the
+library is described
+<xref linkend="cit:jarvi:00"/>.
+</para>
+
+</section>
+ <section>
+ <title>About compiling</title>
+
+ <para>The BLL uses templates rather heavily, performing numerous recursive instantiations of the same templates.
+This has (at least) three implications:
+<itemizedlist>
+
+<listitem>
+<para>
+While it is possible to write incredibly complex lambda expressions, it probably isn't a good idea.
+Compiling such expressions may end up requiring a lot of memory
+at compile time, and being slow to compile.
+</para>
+</listitem>
+
+
+<listitem>
+<para>
+The types of lambda functors that result from even the simplest lambda expressions are cryptic.
+Usually the programmer doesn't need to deal with the lambda functor types at all, but in the case of an error in a lambda expression, the compiler usually outputs the types of the lambda functors involved.
+This can make the error messages very long and difficult to interpret, particularly if the compiler outputs the whole chain of template instantiations.
+</para>
+</listitem>
+
+<listitem>
+<para>
+The C++ Standard suggests a template nesting level of 17 to help detect infinite recursion.
+Complex lambda templates can easily exceed this limit.
+Most compilers allow a greater number of nested templates, but commonly require the limit explicitly increased with a command line argument.
+</para>
+</listitem>
+</itemizedlist></para>
+
+ </section>
+
+ <section>
+ <title>Portability</title>
+ <para>
+The BLL works with the following compilers, that is, the compilers are capable of compiling the test cases that are included with the BLL:
+
+ <itemizedlist>
+ <listitem>GCC 3.0.4
+ </listitem>
+ <listitem>KCC 4.0f with EDG 2.43.1
+ </listitem>
+ <listitem>GCC 2.96 (fails with one test case, the <filename>exception_test.cpp</filename> results in an internal compiler error.
+)
+
+ </listitem>
+ </itemizedlist>
+</para>
+
+ <section>
+ <title>Test coverage</title>
+
+<para>The following list describes the test files included and the features that each file covers:
+
+<itemizedlist>
+<listitem>
+<para>
+<filename>bind_tests_simple.cpp</filename> : Bind expressions of different arities and types of target functions: function pointers, function objects and member functions.
+Function composition with bind expressions.</para>
+</listitem>
+
+<listitem>
+<para><filename>bind_tests_simple_function_references.cpp</filename> :
+Repeats all tests from <filename moreinfo="none">bind_tests_simple.cpp</filename> where the target function is a function pointer, but uses function references instead.
+</para></listitem>
+
+
+<listitem>
+<para><filename>bind_tests_advanced.cpp</filename> : Contains tests for nested bind expressions, <literal>unlambda</literal>, <literal>protect</literal>, <literal>const_parameters</literal> and <literal>break_const</literal>.
+Tests passing lambda functors as actual arguments to other lambda functors, currying, and using the <literal>sig</literal> template to specify the return type of a function object.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>operator_tests_simple.cpp</filename> :
+Tests using all operators that are overloaded for lambda expressions, that is, unary and binary arithmetic,
+bitwise,
+comparison,
+logical,
+increment and decrement,
+compound,
+assignment,
+subscrict,
+address of,
+dereference, and comma operators.
+The streaming nature of shift operators is tested, as well as pointer arithmetic with plus and minus operators.
+</para>
+</listitem>
+
+<listitem>
+<para><filename>member_pointer_test.cpp</filename> : The pointer to member operator is complex enough to warrant a separate test file.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>control_structures.cpp</filename> :
+Tests for the looping and if constructs.
+</para></listitem>
+
+<listitem>
+<para>
+<filename>switch_construct.cpp</filename> :
+Includes tests for all supported arities of the switch statement, both with and without the default case.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>exception_test.cpp</filename> :
+Includes tests for throwing exceptions and for try/catch constructs with varying number of catch blocks.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>constructor_tests.cpp</filename> :
+Contains tests for <literal>constructor</literal>, <literal>destructor</literal>, <literal>new_ptr</literal>, <literal>delete_ptr</literal>, <literal>new_array</literal> and <literal>delete_array</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>cast_test.cpp</filename> : Tests for the four cast expressions, as well as <filename>typeid</filename> and <literal>sizeof</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>extending_return_type_traits.cpp</filename> : Tests extending the return type deduction system for user defined types.
+Contains several user defined operators and the corresponding specializations for the return type deduction templates.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>is_instance_of_test.cpp</filename> : Includes tests for an internally used traits template, which can detect whether a given type is an instance of a certain template or not.
+</para></listitem>
+
+<listitem>
+<para>
+<filename>bll_and_function.cpp</filename> :
+Contains tests for using <literal>boost::function</literal> together with lambda functors.
+</para></listitem>
+
+ </itemizedlist>
+
+</para>
+
+ </section>
+
+ </section>
+
+
+</section>
+
+
+<section>
+<title>Relation to other Boost libraries</title>
+
+<section>
+<title>Boost Function</title>
+
+<para>Sometimes it is convenient to store lambda functors in variables.
+However, the types of even the simplest lambda functors are long and unwieldy, and it is in general unfeasible to declare variables with lambda functor types.
+<emphasis>The Boost Function library</emphasis> <xref linkend="cit:boost::function"/> defines wrappers for arbitrary function objects, for example
+lambda functors; and these wrappers have types that are easy to type out.
+
+For example:
+
+<programlisting>
+<![CDATA[boost::function<int(int, int)> f = _1 + _2;
+boost::function<int&(int&)> g = (_1 += 10);
+int i = 1, j = 2;
+f(i, j); // returns 3
+g(i); // sets i to = 11;]]>
+</programlisting>
+
+The return and parameter types of the wrapped function object must be written explicilty as the template argument to the wrapper template <literal>boost::function</literal>; even when lambda functors, which otherwise have generic parameters, are wrapped.
+Wrapping a function object with <literal>boost::function</literal> introduces a performance cost comparable to virtual function dispatch, though virtual functions are not actually used.
+
+Note that storing lambda functors inside <literal>boost::function</literal>
+introduces a danger.
+Certain types of lambda functors may store references to the bound
+arguments, instead as taking copies of the arguments of the lambda expression.
+When temporary lambda functor objects are used
+in STL algorithm invocations this is always safe, as the lambda functor gets
+destructed immediately after the STL algortihm invocation is completed.
+
+However, a lambda functor wrapped inside <literal>boost::function</literal>
+may continue to exist longer, creating the possibility of dangling references.
+For example:
+
+<programlisting>
+<![CDATA[int* sum = new int();
+*sum = 0;
+boost::function<int&(int)> counter = *sum += _1;
+counter(5); // ok, *sum = 5;
+delete sum;
+counter(3); // error, *sum does not exist anymore]]>
+</programlisting>
+
+</para>
+
+</section>
+
+<section>
+<title>Boost Bind</title>
+<para>
+<emphasis>The Boost Bind</emphasis> <xref linkend="cit:boost::bind"/> library has partially overlapping functionality with the BLL.
+Basically, the Boost Bind library (BB in the sequel) implements the bind expression part of BLL.
+There are, however, some semantical differerences.
+</para>
+<para>
+The BLL and BB evolved separately, and have different implementations.
+This means that the bind expressions from the BB cannot be used within
+bind expressions, or within other type of lambda expressions, of the BLL.
+The same holds for using BLL bind expressions in the BB.
+The libraries can coexist, however, as
+the names of the BB library are in <literal>boost</literal> namespace,
+whereas the BLL names are in <literal>boost::lambda</literal> namespace.
+</para>
+
+<para>
+The BLL requires a compiler that is reasonably conformant to the
+C++ standard, whereas the BB library is more portable, and works with
+a larger set of compilers.
+</para>
+
+<para>
+The following two sections describe what are the semantic differences
+between the bind expressions in BB and BLL.
+</para>
+
+
+
+
+<section>
+<title>First argument of bind expression</title>
+
+In BB the first argument of the bind expression, the target function,
+is treated differently from the other arguments,
+as no argument substitution takes place within that argument.
+In BLL the first argument is not a special case in this respect.
+
+For example:
+
+<programlisting>
+<![CDATA[template<class F>
+int foo(const F& f) {
+ int x;
+ ..
+ bind(f, _1)(x);
+ ...
+}]]>
+</programlisting>
+
+<programlisting>
+<![CDATA[int bar(int, int);
+nested(bind(bar, 1, _1));]]>
+</programlisting>
+
+The bind expression inside <literal>foo</literal> becomes:
+<programlisting>
+bind(bind(bar, 1, _1), _1)(x)
+</programlisting>
+
+The BLL interpretes this as:
+<programlisting>
+bar(1, x)(x)
+</programlisting>
+whereas the BB library as
+<programlisting>
+bar(1, x)
+</programlisting>
+
+To get this functionality in BLL, the bind expression inside the <literal moreinfo="none">foo</literal> function can be written as:
+<programlisting>
+bind(unlambda(f), _1)(x);
+</programlisting>
+as explained in <xref linkend = "sect:unlambda"/>.
+
+</section>
+
+
+
+
+<para>
+The BB library supports up to nine placeholders, while the BLL
+defines only three placeholders.
+The rationale for not providing more, is that the highest arity of the
+function objects accepted by any STL algorithm is two.
+The placeholder count is easy to increase in the BB library.
+In BLL it is possible, but more laborous.
+The BLL currently passes the actual arguments to the lambda functors
+internally just as they are and does not wrap them inside a tuple object.
+The reason for this is that some widely used compilers are not capable
+of optimizing the intermediate tuple objects away.
+The creation of the intermediate tuples would cause a significant
+performance hit, particularly for the simplest (and thus the most common)
+lambda functors.
+We are working on a hybrid approach, which will allow more placeholders
+but not compromise the performance of simple lambda functors.
+</para>
+
+</section>
+
+ </section>
+
+
+<section>
+<title>Contributors</title>
+
+The main body of the library was written by Jaakko Järvi and Gary Powell.
+We've got outside help, suggestions and ideas from Jeremy Siek, Peter Higley, Peter Dimov, Valentin Bonnard, William Kempf.
+We would particularly like to mention Joel de Guzmann and his work with
+Phoenix which has influenced BLL significantly, making it considerably simpler
+to extend the library with new features.
+
+</section>
+
+
+
+<appendix>
+<title>Rationale for some of the design decisions</title>
+
+<section id="sect:why_weak_arity">
+<title>
+Lambda functor arity
+</title>
+
+<para>
+The highest placeholder index in a lambda expression determines the arity of the resulting function object.
+However, this is just the minimal arity, as the function object can take arbitrarily many arguments; those not needed are discarded.
+Consider the two bind expressions and their invocations below:
+
+<programlisting>
+bind(g, _3, _3, _3)(x, y, z);
+bind(g, _1, _1, _1)(x, y, z);
+</programlisting>
+
+This first line discards arguments <literal>x</literal> and
+<literal>y</literal>, and makes the call:
+<programlisting>
+g(z, z, z)
+</programlisting>
+whereas the second line discards arguments <literal>y</literal> and
+<literal>z</literal>, and calls:
+<programlisting>
+g(x, x, x)
+</programlisting>
+In earlier versions of the library, the latter line resulted in a compile
+time error.
+
+This is basically a tradeoff between safety and flexibility, and the issue
+was extensively discussed during the Boost review period of the library.
+The main points for the <emphasis>strict arity</emphasis> checking
+was that it might
+catch a programming error at an earlier time and that a lambda expression that
+explicitly discards its arguments is easy to write:
+<programlisting>
+(_3, bind(g, _1, _1, _1))(x, y, z);
+</programlisting>
+This lambda expression takes three arguments.
+The left-hand argument of the comma operator does nothing, and as comma
+returns the result of evaluating the right-hand argument we end up with
+the call
+<literal>g(x, x, x)</literal>
+even with the strict arity.
+</para>
+
+<para>
+The main points against the strict arity checking were that the need to
+discard arguments is commonplace, and should therefore be straightforward,
+and that strict arity checking does not really buy that much more safety,
+particularly as it is not symmetric.
+For example, if the programmer wanted to write the expression
+<literal>_1 + _2</literal> but mistakenly wrote <literal>_1 + 2</literal>,
+with strict arity checking, the complier would spot the error.
+However, if the erroneous expression was <literal>1 + _2</literal> instead,
+the error would go unnoticed.
+Furthermore, weak arity checking simplifies the implementation a bit.
+Following the recommendation of the Boost review, strict arity checking
+was dropped.
+</para>
+
+</section>
+
+</appendix>
+
+
+
+<bibliography>
+
+<biblioentry id="cit:stepanov:94">
+<abbrev>STL94</abbrev>
+<authorgroup>
+<author>
+<surname>Stepanov</surname>
+<firstname>A. A.</firstname>
+</author>
+<author>
+<surname>Lee</surname>
+<firstname>M.</firstname>
+</author>
+</authorgroup>
+<title>The Standard Template Library</title>
+<orgname>Hewlett-Packard Laboratories</orgname>
+<pubdate>1994</pubdate>
+<bibliomisc>
+<ulink url="http://www.hpl.hp.com/techreports">www.hpl.hp.com/techreports</ulink>
+</bibliomisc>
+</biblioentry>
+
+<biblioentry id="cit:sgi:02">
+<abbrev>SGI02</abbrev>
+<title>The SGI Standard Template Library</title>
+<pubdate>2002</pubdate>
+<bibliomisc><ulink url="http://www.sgi.com/tech/stl/">www.sgi.com/tech/stl/</ulink></bibliomisc>
+
+</biblioentry>
+
+<biblioentry id="cit:c++:98">
+<abbrev>C++98</abbrev>
+<title>International Standard, Programming Languages &ndash; C++</title>
+<subtitle>ISO/IEC:14882</subtitle>
+<pubdate>1998</pubdate>
+</biblioentry>
+
+
+<biblioentry id="cit:jarvi:99">
+<abbrev>Jär99</abbrev>
+
+<articleinfo>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<title>C++ Function Object Binders Made Easy</title>
+</articleinfo>
+
+<title>Lecture Notes in Computer Science</title>
+<volumenum>1977</volumenum>
+<publishername>Springer</publishername>
+
+<pubdate>2000</pubdate>
+</biblioentry>
+
+
+
+<biblioentry id="cit:jarvi:00">
+<abbrev>Jär00</abbrev>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+<title>The Lambda Library : Lambda Abstraction in C++</title>
+ <orgname>Turku Centre for Computer Science</orgname>
+<bibliomisc>Technical Report </bibliomisc>
+ <issuenum>378</issuenum>
+<pubdate>2000</pubdate>
+<bibliomisc><ulink url="http://www.tucs.fi/Publications/techreports/TR378.php">www.tucs.fi/publications</ulink></bibliomisc>
+
+
+</biblioentry>
+
+
+<biblioentry id="cit:jarvi:01">
+<abbrev>Jär01</abbrev>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+<title>The Lambda Library : Lambda Abstraction in C++</title>
+ <confgroup>
+ <conftitle>Second Workshop on C++ Template Programming</conftitle>
+ <address>Tampa Bay, OOPSLA'01</address>
+ </confgroup>
+<pubdate>2001</pubdate>
+<bibliomisc><ulink url="http://www.oonumerics.org/tmpw01/">www.oonumerics.org/tmpw01/</ulink></bibliomisc>
+</biblioentry>
+
+<biblioentry id="cit:jarvi:03">
+<abbrev>Jär03</abbrev>
+
+<articleinfo>
+
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+
+<author>
+<firstname>Andrew</firstname>
+<surname>Lumsdaine</surname>
+</author>
+<title>The Lambda Library : unnamed functions in C++</title>
+
+</articleinfo>
+
+<title>Software - Practice and Expreience</title>
+<volumenum>33:259-291</volumenum>
+
+
+<pubdate>2003</pubdate>
+</biblioentry>
+
+
+<biblioentry id="cit:boost::tuple">
+<abbrev>tuple</abbrev>
+<title>The Boost Tuple Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html">www.boost.org/libs/tuple/doc/tuple_users_guide.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::type_traits">
+<abbrev>type_traits</abbrev>
+<title>The Boost type_traits</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/type_traits/index.htm">www.boost.org/libs/type_traits/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::ref">
+<abbrev>ref</abbrev>
+<title>Boost ref</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/bind/ref.html">www.boost.org/libs/bind/ref.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::bind">
+<abbrev>bind</abbrev>
+<title>Boost Bind Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/bind/bind.html">www.boost.org/libs/bind/bind.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::function">
+<abbrev>function</abbrev>
+<title>Boost Function Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/function/">www.boost.org/libs/function/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:fc++">
+<abbrev>fc++</abbrev>
+<title>The FC++ library: Functional Programming in C++</title>
+<author>
+<surname>Smaragdakis</surname>
+<firstname>Yannis</firstname>
+</author>
+<author>
+<firstname>Brian</firstname>
+<surname>McNamara</surname>
+</author>
+<bibliomisc><ulink url="http://www.cc.gatech.edu/~yannis/fc++/">www.cc.gatech.edu/~yannis/fc++/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+
+
+
+</bibliography>
+
+
+
+</library>
+
+
+
+
+
+
diff --git a/libs/lambda/doc/detail/lambda_doc.xsl b/libs/lambda/doc/detail/lambda_doc.xsl
new file mode 100644
index 000000000..3a622ecd6
--- /dev/null
+++ b/libs/lambda/doc/detail/lambda_doc.xsl
@@ -0,0 +1,19 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version='1.0'
+ xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="/u/jajarvi/dtd/docbook-xsl/html/docbook.xsl"/>
+
+
+<!-- Add other variable definitions here -->
+
+<xsl:variable name="shade.verbatim">0</xsl:variable>
+
+<xsl:variable name="section.autolabel">1</xsl:variable>
+
+<xsl:variable name="bibliography.collection">lambda_bib.xml</xsl:variable>
+
+
+</xsl:stylesheet>
diff --git a/libs/lambda/doc/detail/lambda_doc_chunks.xsl b/libs/lambda/doc/detail/lambda_doc_chunks.xsl
new file mode 100644
index 000000000..a63d37929
--- /dev/null
+++ b/libs/lambda/doc/detail/lambda_doc_chunks.xsl
@@ -0,0 +1,19 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version='1.0'
+ xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="/u/jajarvi/dtd/docbook-xsl/html/chunk.xsl"/>
+
+
+<!-- Add other variable definitions here -->
+
+<xsl:variable name="shade.verbatim">0</xsl:variable>
+
+<xsl:variable name="section.autolabel">1</xsl:variable>
+
+<xsl:variable name="bibliography.collection">lambda_bib.xml</xsl:variable>
+
+
+</xsl:stylesheet>
diff --git a/libs/lambda/doc/index.html b/libs/lambda/doc/index.html
new file mode 100644
index 000000000..59f1bfc58
--- /dev/null
+++ b/libs/lambda/doc/index.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=../../../doc/html/lambda.html">
+</head>
+<body>
+Automatic redirection failed, please go to <a href="../../../doc/html/lambda.html">www.boost.org/doc/html/lambda.html</a>&nbsp;<hr>
+<p>© Copyright Beman Dawes, 2001</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
+at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html>
diff --git a/libs/lambda/doc/lambda.xml b/libs/lambda/doc/lambda.xml
new file mode 100644
index 000000000..6f617aabd
--- /dev/null
+++ b/libs/lambda/doc/lambda.xml
@@ -0,0 +1,3452 @@
+<?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: 2009-06-13 14:18:10 -0700 (Sat, 13 Jun 2009) $"
+ 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 &lt;&lt; _1));
+</programlisting>
+
+Without the extra parenthesis around <literal>++_1, cout &lt;&lt; _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 &lt;= n &lt;= 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&lt;<emphasis>RET</emphasis>&gt;(<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 special lambda expression type is provided for stating the return type explicitly and overriding the deduction system.
+To state that the return type of the lambda functor defined by the lambda expression <literal>e</literal> is <literal>T</literal>, you can write:
+
+<programlisting><![CDATA[ret<T>(e);]]></programlisting>
+
+The effect is that the return type deduction is not performed for the lambda expression <literal>e</literal> at all, but instead, <literal>T</literal> is used as the return type.
+Obviously <literal>T</literal> cannot be an arbitrary type, the true result of the lambda functor must be implicitly convertible to <literal>T</literal>.
+For example:
+
+<programlisting>
+<![CDATA[A a; B b;
+C operator+(A, B);
+int operator*(A, B);
+ ...
+ret<D>(_1 + _2)(a, b); // error (C cannot be converted to D)
+ret<C>(_1 + _2)(a, b); // ok
+ret<float>(_1 * _2)(a, b); // ok (int can be converted to float)
+ ...
+struct X {
+ Y operator(int)();
+};
+ ...
+X x; int i;
+bind(x, _1)(i); // error, return type cannot be deduced
+ret<Y>(bind(x, _1))(i); // ok]]>
+</programlisting>
+For bind expressions, there is a short-hand notation that can be used instead of <literal>ret</literal>.
+The last line could alternatively be written as:
+
+<programlisting><![CDATA[bind<Z>(x, _1)(i);]]></programlisting>
+This feature is modeled after the Boost Bind library <xref linkend="cit:boost::bind"/>.
+
+</para>
+
+<para>Note that within nested lambda expressions,
+the <literal>ret</literal> must be used at each subexpression where
+the deduction would otherwise fail.
+For example:
+<programlisting>
+<![CDATA[A a; B b;
+C operator+(A, B); D operator-(C);
+ ...
+ret<D>( - (_1 + _2))(a, b); // error
+ret<D>( - ret<C>(_1 + _2))(a, b); // ok]]>
+</programlisting>
+</para>
+
+<para>If you find yourself using <literal>ret</literal> repeatedly with the same types, it is worth while extending the return type deduction (see <xref linkend="lambda.extending"/>).
+</para>
+
+<section id="lambda.nullary_functors_and_ret">
+<title>Nullary lambda functors and ret</title>
+
+<para>
+As stated above, the effect of <literal>ret</literal> is to prevent the return type deduction to be performed.
+However, there is an exception.
+Due to the way the C++ template instantiation works, the compiler is always forced to instantiate the return type deduction templates for zero-argument lambda functors.
+This introduces a slight problem with <literal>ret</literal>, best described with an example:
+
+<programlisting>
+<![CDATA[struct F { int operator()(int i) const; };
+F f;
+ ...
+bind(f, _1); // fails, cannot deduce the return type
+ret<int>(bind(f, _1)); // ok
+ ...
+bind(f, 1); // fails, cannot deduce the return type
+ret<int>(bind(f, 1)); // fails as well!]]>
+</programlisting>
+The BLL cannot deduce the return types of the above bind calls, as <literal>F</literal> does not define the typedef <literal>result_type</literal>.
+One would expect <literal>ret</literal> to fix this, but for the nullary lambda functor that results from a bind expression (last line above) this does not work.
+The return type deduction templates are instantiated, even though it would not be necessary and the result is a compilation error.
+</para>
+
+<para>The solution to this is not to use the <literal>ret</literal> function, but rather define the return type as an explicitly specified template parameter in the <literal>bind</literal> call:
+<programlisting>
+<![CDATA[bind<int>(f, 1); // ok]]>
+</programlisting>
+
+The lambda functors created with
+<literal>ret&lt;<parameter>T</parameter>&gt;(bind(<parameter>arg-list</parameter>))</literal> and
+<literal>bind&lt;<parameter>T</parameter>&gt;(<parameter>arg-list</parameter>)</literal> have the exact same functionality &mdash;
+apart from the fact that for some nullary lambda functors the former does not work while the latter does.
+</para>
+</section>
+</section>
+
+
+<section id="lambda.delaying_constants_and_variables">
+<title>Delaying constants and variables</title>
+
+<para>
+The unary functions <literal>constant</literal>,
+<literal>constant_ref</literal> and <literal>var</literal> turn their argument into a lambda functor, that implements an identity mapping.
+The former two are for constants, the latter for variables.
+The use of these <emphasis>delayed</emphasis> constants and variables is sometimes necessary due to the lack of explicit syntax for lambda expressions.
+For example:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(), cout << _1 << ' ');
+for_each(a.begin(), a.end(), cout << ' ' << _1);]]>
+</programlisting>
+The first line outputs the elements of <literal>a</literal> separated by spaces, while the second line outputs a space followed by the elements of <literal>a</literal> without any separators.
+The reason for this is that neither of the operands of
+<literal><![CDATA[cout << ' ']]></literal> is a lambda expression, hence <literal><![CDATA[cout << ' ']]></literal> is evaluated immediately.
+
+To delay the evaluation of <literal><![CDATA[cout << ' ']]></literal>, one of the operands must be explicitly marked as a lambda expression.
+This is accomplished with the <literal>constant</literal> function:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(), cout << constant(' ') << _1);]]>
+</programlisting>
+
+The call <literal>constant(' ')</literal> creates a nullary lambda functor which stores the character constant <literal>' '</literal>
+and returns a reference to it when invoked.
+The function <literal>constant_ref</literal> is similar, except that it
+stores a constant reference to its argument.
+
+The <literal>constant</literal> and <literal>consant_ref</literal> are only
+needed when the operator call has side effects, like in the above example.
+</para>
+
+<para>
+Sometimes we need to delay the evaluation of a variable.
+Suppose we wanted to output the elements of a container in a numbered list:
+
+<programlisting>
+<![CDATA[int index = 0;
+for_each(a.begin(), a.end(), cout << ++index << ':' << _1 << '\n');
+for_each(a.begin(), a.end(), cout << ++var(index) << ':' << _1 << '\n');]]>
+</programlisting>
+
+The first <literal>for_each</literal> invocation does not do what we want; <literal>index</literal> is incremented only once, and its value is written into the output stream only once.
+By using <literal>var</literal> to make <literal>index</literal> a lambda expression, we get the desired effect.
+<!-- Note that <literal>var</literal> accepts const objects as well, in which case
+calling <literal>var</literal> equals calling <literal>constant_ref</literal>.-->
+</para>
+
+<para>
+In sum, <literal>var(x)</literal> creates a nullary lambda functor,
+which stores a reference to the variable <literal>x</literal>.
+When the lambda functor is invoked, a reference to <literal>x</literal> is returned.
+</para>
+
+<simplesect>
+<title>Naming delayed constants and variables</title>
+
+<para>
+It is possible to predefine and name a delayed variable or constant outside a lambda expression.
+The templates <literal>var_type</literal>, <literal>constant_type</literal>
+and <literal>constant_ref_type</literal> serve for this purpose.
+They are used as:
+<programlisting>
+<![CDATA[var_type<T>::type delayed_i(var(i));
+constant_type<T>::type delayed_c(constant(c));]]>
+</programlisting>
+The first line defines the variable <literal>delayed_i</literal> which is a delayed version of the variable <literal>i</literal> of type <literal>T</literal>.
+Analogously, the second line defines the constant <literal>delayed_c</literal> as a delayed version of the constant <literal>c</literal>.
+For example:
+
+<programlisting>
+int i = 0; int j;
+for_each(a.begin(), a.end(), (var(j) = _1, _1 = var(i), var(i) = var(j)));
+</programlisting>
+is equivalent to:
+<programlisting>
+<![CDATA[int i = 0; int j;
+var_type<int>::type vi(var(i)), vj(var(j));
+for_each(a.begin(), a.end(), (vj = _1, _1 = vi, vi = vj));]]>
+</programlisting>
+</para>
+<para>
+Here is an example of naming a delayed constant:
+<programlisting>
+<![CDATA[constant_type<char>::type space(constant(' '));
+for_each(a.begin(),a.end(), cout << space << _1);]]>
+</programlisting>
+</para>
+
+</simplesect>
+
+<simplesect>
+<title>About assignment and subscript operators</title>
+
+<para>
+As described in <xref linkend="lambda.assignment_and_subscript"/>, assignment and subscripting operators are always defined as member functions.
+This means, that for expressions of the form
+<literal>x = y</literal> or <literal>x[y]</literal> to be interpreted as lambda expressions, the left-hand operand <literal>x</literal> must be a lambda expression.
+Consequently, it is sometimes necessary to use <literal>var</literal> for this purpose.
+We repeat the example from <xref linkend="lambda.assignment_and_subscript"/>:
+
+<programlisting>
+int i;
+i = _1; // error
+var(i) = _1; // ok
+</programlisting>
+</para>
+
+<para>
+
+Note that the compound assignment operators <literal>+=</literal>, <literal>-=</literal> etc. can be defined as non-member functions, and thus they are interpreted as lambda expressions even if only the right-hand operand is a lambda expression.
+Nevertheless, it is perfectly ok to delay the left operand explicitly.
+For example, <literal>i += _1</literal> is equivalent to <literal>var(i) += _1</literal>.
+</para>
+</simplesect>
+
+</section>
+
+<section id="lambda.lambda_expressions_for_control_structures">
+<title>Lambda expressions for control structures</title>
+
+<para>
+BLL defines several functions to create lambda functors that represent control structures.
+They all take lambda functors as parameters and return <literal>void</literal>.
+To start with an example, the following code outputs all even elements of some container <literal>a</literal>:
+
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(),
+ if_then(_1 % 2 == 0, cout << _1));]]>
+</programlisting>
+</para>
+
+<para>
+The BLL supports the following function templates for control structures:
+
+<programlisting>
+if_then(condition, then_part)
+if_then_else(condition, then_part, else_part)
+if_then_else_return(condition, then_part, else_part)
+while_loop(condition, body)
+while_loop(condition) // no body case
+do_while_loop(condition, body)
+do_while_loop(condition) // no body case
+for_loop(init, condition, increment, body)
+for_loop(init, condition, increment) // no body case
+switch_statement(...)
+</programlisting>
+
+The return types of all control construct lambda functor is
+<literal>void</literal>, except for <literal>if_then_else_return</literal>,
+which wraps a call to the conditional operator
+<programlisting>
+condition ? then_part : else_part
+</programlisting>
+The return type rules for this operator are somewhat complex.
+Basically, if the branches have the same type, this type is the return type.
+If the type of the branches differ, one branch, say of type
+<literal>A</literal>, must be convertible to the other branch,
+say of type <literal>B</literal>.
+In this situation, the result type is <literal>B</literal>.
+Further, if the common type is an lvalue, the return type will be an lvalue
+too.
+</para>
+
+
+<para>
+Delayed variables tend to be commonplace in control structure lambda expressions.
+For instance, here we use the <literal>var</literal> function to turn the arguments of <literal>for_loop</literal> into lambda expressions.
+The effect of the code is to add 1 to each element of a two-dimensional array:
+
+<programlisting>
+<![CDATA[int a[5][10]; int i;
+for_each(a, a+5,
+ for_loop(var(i)=0, var(i)<10, ++var(i),
+ _1[var(i)] += 1));]]>
+</programlisting>
+
+<!--
+As explained in <xref linkend="lambda.delaying_constants_and_variables"/>, we can avoid the repeated use of wrapping of <literal>var</literal> if we define it beforehand:
+
+<programlisting>
+<![CDATA[int i;
+var_type<int>::type vi(var(i));
+for_each(a, a+5,
+ for_loop(vi=0, vi<10, ++vi, _1[vi] += 6));]]>
+</programlisting>
+
+-->
+</para>
+
+<para>
+The BLL supports an alternative syntax for control expressions, suggested
+by Joel de Guzmann.
+By overloading the <literal>operator[]</literal> we can
+get a closer resemblance with the built-in control structures:
+
+<programlisting>
+<![CDATA[if_(condition)[then_part]
+if_(condition)[then_part].else_[else_part]
+while_(condition)[body]
+do_[body].while_(condition)
+for_(init, condition, increment)[body]]]>
+</programlisting>
+
+For example, using this syntax the <literal>if_then</literal> example above
+can be written as:
+<programlisting>
+<![CDATA[for_each(a.begin(), a.end(),
+ if_(_1 % 2 == 0)[ cout << _1 ])]]>
+</programlisting>
+
+As more experience is gained, we may end up deprecating one or the other
+of these syntaces.
+
+</para>
+
+
+
+<section id="lambda.switch_statement">
+<title>Switch statement</title>
+</section>
+
+<para>
+The lambda expressions for <literal>switch</literal> control structures are more complex since the number of cases may vary.
+The general form of a switch lambda expression is:
+
+<programlisting>
+switch_statement(<parameter>condition</parameter>,
+ case_statement&lt;<parameter>label</parameter>&gt;(<parameter>lambda expression</parameter>),
+ case_statement&lt;<parameter>label</parameter>&gt;(<parameter>lambda expression</parameter>),
+ ...
+ default_statement(<parameter>lambda expression</parameter>)
+)
+</programlisting>
+
+The <literal><parameter>condition</parameter></literal> argument must be a lambda expression that creates a lambda functor with an integral return type.
+The different cases are created with the <literal>case_statement</literal> functions, and the optional default case with the <literal>default_statement</literal> function.
+The case labels are given as explicitly specified template arguments to <literal>case_statement</literal> functions and
+<literal>break</literal> statements are implicitly part of each case.
+For example, <literal><![CDATA[case_statement<1>(a)]]></literal>, where <literal>a</literal> is some lambda functor, generates the code:
+
+<programlisting>
+case 1:
+ <parameter>evaluate lambda functor</parameter> a;
+ break;
+</programlisting>
+The <literal>switch_statement</literal> function is specialized for up to 9 case statements.
+
+</para>
+
+<para>
+As a concrete example, the following code iterates over some container <literal>v</literal> and ouptuts <quote>zero</quote> for each <literal>0</literal>, <quote>one</quote> for each <literal>1</literal>, and <quote>other: <parameter>n</parameter></quote> for any other value <parameter>n</parameter>.
+Note that another lambda expression is sequenced after the <literal>switch_statement</literal> to output a line break after each element:
+
+<programlisting>
+<![CDATA[std::for_each(v.begin(), v.end(),
+ (
+ switch_statement(
+ _1,
+ case_statement<0>(std::cout << constant("zero")),
+ case_statement<1>(std::cout << constant("one")),
+ default_statement(cout << constant("other: ") << _1)
+ ),
+ cout << constant("\n")
+ )
+);]]>
+</programlisting>
+</para>
+
+</section>
+
+<section id="lambda.exceptions">
+<title>Exceptions</title>
+
+<para>
+The BLL provides lambda functors that throw and catch exceptions.
+Lambda functors for throwing exceptions are created with the unary function <literal>throw_exception</literal>.
+The argument to this function is the exception to be thrown, or a lambda functor which creates the exception to be thrown.
+A lambda functor for rethrowing exceptions is created with the nullary <literal>rethrow</literal> function.
+</para>
+
+<para>
+Lambda expressions for handling exceptions are somewhat more complex.
+The general form of a lambda expression for try catch blocks is as follows:
+
+<programlisting>
+try_catch(
+ <parameter>lambda expression</parameter>,
+ catch_exception&lt;<parameter>type</parameter>&gt;(<parameter>lambda expression</parameter>),
+ catch_exception&lt;<parameter>type</parameter>&gt;(<parameter>lambda expression</parameter>),
+ ...
+ catch_all(<parameter>lambda expression</parameter>)
+)
+</programlisting>
+
+The first lambda expression is the try block.
+Each <literal>catch_exception</literal> defines a catch block where the
+explicitly specified template argument defines the type of the exception
+to catch.
+
+The lambda expression within the <literal>catch_exception</literal> defines
+the actions to take if the exception is caught.
+
+Note that the resulting exception handlers catch the exceptions as
+references, i.e., <literal>catch_exception&lt;T&gt;(...)</literal>
+results in the catch block:
+
+<programlisting>
+catch(T&amp; e) { ... }
+</programlisting>
+
+The last catch block can alternatively be a call to
+<literal>catch_exception&lt;<parameter>type</parameter>&gt;</literal>
+or to
+<literal>catch_all</literal>, which is the lambda expression equivalent to
+<literal>catch(...)</literal>.
+
+</para>
+
+<para>
+
+The <xref linkend="ex:exceptions"/> demonstrates the use of the BLL
+exception handling tools.
+The first handler catches exceptions of type <literal>foo_exception</literal>.
+Note the use of <literal>_1</literal> placeholder in the body of the handler.
+</para>
+
+<para>
+The second handler shows how to throw exceptions, and demonstrates the
+use of the <emphasis>exception placeholder</emphasis> <literal>_e</literal>.
+
+It is a special placeholder, which refers to the caught exception object
+within the handler body.
+
+Here we are handling an exception of type <literal>std::exception</literal>,
+which carries a string explaining the cause of the exception.
+
+This explanation can be queried with the zero-argument member
+function <literal>what</literal>.
+
+The expression
+<literal>bind(&amp;std::exception::what, _e)</literal> creates the lambda
+function for making that call.
+
+Note that <literal>_e</literal> cannot be used outside of an exception handler lambda expression.
+<!--Violating this rule is caught by the compiler.-->
+
+The last line of the second handler constructs a new exception object and
+throws that with <literal>throw exception</literal>.
+
+Constructing and destructing objects within lambda expressions is
+explained in <xref linkend="lambda.construction_and_destruction"/>
+</para>
+
+<para>
+Finally, the third handler (<literal>catch_all</literal>) demonstrates
+rethrowing exceptions.
+</para>
+
+<example id="ex:exceptions">
+<title>Throwing and handling exceptions in lambda expressions.</title>
+<programlisting>
+<![CDATA[for_each(
+ a.begin(), a.end(),
+ try_catch(
+ bind(foo, _1), // foo may throw
+ catch_exception<foo_exception>(
+ cout << constant("Caught foo_exception: ")
+ << "foo was called with argument = " << _1
+ ),
+ catch_exception<std::exception>(
+ cout << constant("Caught std::exception: ")
+ << bind(&std::exception::what, _e),
+ throw_exception(bind(constructor<bar_exception>(), _1)))
+ ),
+ catch_all(
+ (cout << constant("Unknown"), rethrow())
+ )
+ )
+);]]>
+</programlisting>
+</example>
+
+</section>
+
+<section id="lambda.construction_and_destruction">
+<title>Construction and destruction</title>
+
+
+<para>
+Operators <literal>new</literal> and <literal>delete</literal> can be
+overloaded, but their return types are fixed.
+
+Particularly, the return types cannot be lambda functors,
+which prevents them to be overloaded for lambda expressions.
+
+It is not possible to take the address of a constructor,
+hence constructors cannot be used as target functions in bind expressions.
+
+The same is true for destructors.
+
+As a way around these constraints, BLL defines wrapper classes for
+<literal>new</literal> and <literal>delete</literal> calls,
+as well as for constructors and destructors.
+
+Instances of these classes are function objects, that can be used as
+target functions of bind expressions.
+
+For example:
+
+<programlisting>
+<![CDATA[int* a[10];
+for_each(a, a+10, _1 = bind(new_ptr<int>()));
+for_each(a, a+10, bind(delete_ptr(), _1));]]>
+</programlisting>
+
+The <literal>new_ptr&lt;int&gt;()</literal> expression creates
+a function object that calls <literal>new int()</literal> when invoked,
+and wrapping that inside <literal>bind</literal> makes it a lambda functor.
+
+In the same way, the expression <literal>delete_ptr()</literal> creates
+a function object that invokes <literal>delete</literal> on its argument.
+
+Note that <literal>new_ptr&lt;<parameter>T</parameter>&gt;()</literal>
+can take arguments as well.
+
+They are passed directly to the constructor invocation and thus allow
+calls to constructors which take arguments.
+
+</para>
+
+<para>
+
+As an example of constructor calls in lambda expressions,
+the following code reads integers from two containers <literal>x</literal>
+and <literal>y</literal>,
+constructs pairs out of them and inserts them into a third container:
+
+<programlisting>
+<![CDATA[vector<pair<int, int> > v;
+transform(x.begin(), x.end(), y.begin(), back_inserter(v),
+ bind(constructor<pair<int, int> >(), _1, _2));]]>
+</programlisting>
+
+<xref linkend="table:constructor_destructor_fos"/> lists all the function
+objects related to creating and destroying objects,
+ showing the expression to create and call the function object,
+and the effect of evaluating that expression.
+
+</para>
+
+
+
+<table id="table:constructor_destructor_fos">
+<title>Construction and destruction related function objects.</title>
+<tgroup cols="2">
+<thead>
+<row>
+<entry>Function object call</entry>
+<entry>Wrapped expression</entry>
+</row>
+</thead>
+<tbody>
+<row>
+<entry><literal>constructor&lt;T&gt;()(<parameter>arg_list</parameter>)</literal></entry>
+<entry>T(<parameter>arg_list</parameter>)</entry>
+</row>
+<row>
+<entry><literal>destructor()(a)</literal></entry>
+<entry><literal>a.~A()</literal>, where <literal>a</literal> is of type <literal>A</literal></entry>
+</row>
+<row>
+<entry><literal>destructor()(pa)</literal></entry>
+<entry><literal>pa->~A()</literal>, where <literal>pa</literal> is of type <literal>A*</literal></entry>
+</row>
+<row>
+<entry><literal>new_ptr&lt;T&gt;()(<parameter>arg_list</parameter>)</literal></entry>
+<entry><literal>new T(<parameter>arg_list</parameter>)</literal></entry>
+</row>
+<row>
+<entry><literal>new_array&lt;T&gt;()(sz)</literal></entry>
+<entry><literal>new T[sz]</literal></entry>
+</row>
+<row>
+<entry><literal>delete_ptr()(p)</literal></entry>
+<entry><literal>delete p</literal></entry>
+</row>
+<row>
+<entry><literal>delete_array()(p)</literal></entry>
+<entry><literal>delete p[]</literal></entry>
+</row>
+
+
+</tbody>
+</tgroup>
+</table>
+
+</section>
+
+
+<section>
+<title>Special lambda expressions</title>
+
+<section>
+<title>Preventing argument substitution</title>
+
+<para>
+When a lambda functor is called, the default behavior is to substitute
+the actual arguments for the placeholders within all subexpressions.
+
+This section describes the tools to prevent the substitution and
+evaluation of a subexpression, and explains when these tools should be used.
+</para>
+
+
+<para>
+The arguments to a bind expression can be arbitrary lambda expressions,
+e.g., other bind expressions.
+
+For example:
+
+<programlisting>
+int foo(int); int bar(int);
+...
+int i;
+bind(foo, bind(bar, _1))(i);
+</programlisting>
+
+The last line makes the call <literal>foo(bar(i));</literal>
+
+Note that the first argument in a bind expression, the target function,
+is no exception, and can thus be a bind expression too.
+
+The innermost lambda functor just has to return something that can be used
+as a target function: another lambda functor, function pointer,
+pointer to member function etc.
+
+For example, in the following code the innermost lambda functor makes
+a selection between two functions, and returns a pointer to one of them:
+
+<programlisting>
+int add(int a, int b) { return a+b; }
+int mul(int a, int b) { return a*b; }
+
+int(*)(int, int) add_or_mul(bool x) {
+ return x ? add : mul;
+}
+
+bool condition; int i; int j;
+...
+bind(bind(&amp;add_or_mul, _1), _2, _3)(condition, i, j);
+</programlisting>
+
+</para>
+
+
+
+<section id="lambda.unlambda">
+<title>Unlambda</title>
+
+<para>A nested bind expression may occur inadvertently,
+if the target function is a variable with a type that depends on a
+template parameter.
+
+Typically the target function could be a formal parameter of a
+function template.
+
+In such a case, the programmer may not know whether the target function is a lambda functor or not.
+</para>
+
+<para>Consider the following function template:
+
+<programlisting>
+<![CDATA[template<class F>
+int nested(const F& f) {
+ int x;
+ ...
+ bind(f, _1)(x);
+ ...
+}]]>
+</programlisting>
+
+Somewhere inside the function the formal parameter
+<literal>f</literal> is used as a target function in a bind expression.
+
+In order for this <literal>bind</literal> call to be valid,
+<literal>f</literal> must be a unary function.
+
+Suppose the following two calls to <literal>nested</literal> are made:
+
+<programlisting>
+<![CDATA[int foo(int);
+int bar(int, int);
+nested(&foo);
+nested(bind(bar, 1, _1));]]>
+</programlisting>
+
+Both are unary functions, or function objects, with appropriate argument
+and return types, but the latter will not compile.
+
+In the latter call, the bind expression inside <literal>nested</literal>
+will become:
+
+<programlisting>
+bind(bind(bar, 1, _1), _1)
+</programlisting>
+
+When this is invoked with <literal>x</literal>,
+after substituitions we end up trying to call
+
+<programlisting>
+bar(1, x)(x)
+</programlisting>
+
+which is an error.
+
+The call to <literal>bar</literal> returns int,
+not a unary function or function object.
+</para>
+
+<para>
+In the example above, the intent of the bind expression in the
+<literal>nested</literal> function is to treat <literal>f</literal>
+as an ordinary function object, instead of a lambda functor.
+
+The BLL provides the function template <literal>unlambda</literal> to
+express this: a lambda functor wrapped inside <literal>unlambda</literal>
+is not a lambda functor anymore, and does not take part into the
+argument substitution process.
+
+Note that for all other argument types <literal>unlambda</literal> is
+an identity operation, except for making non-const objects const.
+</para>
+
+<para>
+Using <literal>unlambda</literal>, the <literal>nested</literal>
+function is written as:
+
+<programlisting>
+<![CDATA[template<class F>
+int nested(const F& f) {
+ int x;
+ ...
+ bind(unlambda(f), _1)(x);
+ ...
+}]]>
+</programlisting>
+
+</para>
+
+</section>
+
+<section>
+<title>Protect</title>
+
+<para>
+The <literal>protect</literal> function is related to unlambda.
+
+It is also used to prevent the argument substitution taking place,
+but whereas <literal>unlambda</literal> turns a lambda functor into
+an ordinary function object for good, <literal>protect</literal> does
+this temporarily, for just one evaluation round.
+
+For example:
+
+<programlisting>
+int x = 1, y = 10;
+(_1 + protect(_1 + 2))(x)(y);
+</programlisting>
+
+The first call substitutes <literal>x</literal> for the leftmost
+<literal>_1</literal>, and results in another lambda functor
+<literal>x + (_1 + 2)</literal>, which after the call with
+<literal>y</literal> becomes <literal>x + (y + 2)</literal>,
+and thus finally 13.
+</para>
+
+<para>
+Primary motivation for including <literal>protect</literal> into the library,
+was to allow nested STL algorithm invocations
+(<xref linkend="lambda.nested_stl_algorithms"/>).
+</para>
+
+</section>
+
+</section>
+
+<section id="lambda.rvalues_as_actual_arguments">
+<title>Rvalues as actual arguments to lambda functors</title>
+
+<!-- <para><emphasis>This section and all of its subsections
+ are no longer (or currently) relevant;
+ acual arguments can be non-const rvalues and these workarounds are thus
+ not needed.
+ The section can, however, become relevant again, if in the future BLL will support
+ lambda functors with higher arities than 3.</emphasis></para> -->
+
+<para>
+Actual arguments to the lambda functors cannot be non-const rvalues.
+This is due to a deliberate design decision: either we have this restriction,
+or there can be no side-effects to the actual arguments.
+
+There are ways around this limitation.
+
+We repeat the example from section
+<xref linkend="lambda.actual_arguments_to_lambda_functors"/> and list the
+different solutions:
+
+<programlisting>
+int i = 1; int j = 2;
+(_1 + _2)(i, j); // ok
+(_1 + _2)(1, 2); // error (!)
+</programlisting>
+
+<orderedlist>
+<listitem>
+<para>
+If the rvalue is of a class type, the return type of the function that
+creates the rvalue should be defined as const.
+Due to an unfortunate language restriction this does not work for
+built-in types, as built-in rvalues cannot be const qualified.
+</para>
+</listitem>
+
+<listitem>
+<para>
+If the lambda function call is accessible, the <literal>make_const</literal>
+function can be used to <emphasis>constify</emphasis> the rvalue. E.g.:
+
+<programlisting>
+(_1 + _2)(make_const(1), make_const(2)); // ok
+</programlisting>
+
+Commonly the lambda function call site is inside a standard algorithm
+function template, preventing this solution to be used.
+
+</para>
+</listitem>
+
+<listitem>
+<para>
+If neither of the above is possible, the lambda expression can be wrapped
+in a <literal>const_parameters</literal> function.
+It creates another type of lambda functor, which takes its arguments as
+const references. For example:
+
+<programlisting>
+const_parameters(_1 + _2)(1, 2); // ok
+</programlisting>
+
+Note that <literal>const_parameters</literal> makes all arguments const.
+Hence, in the case were one of the arguments is a non-const rvalue,
+and another argument needs to be passed as a non-const reference,
+this approach cannot be used.
+</para>
+
+</listitem>
+
+<listitem>
+<para>If none of the above is possible, there is still one solution,
+which unfortunately can break const correctness.
+
+The solution is yet another lambda functor wrapper, which we have named
+<literal>break_const</literal> to alert the user of the potential dangers
+of this function.
+
+The <literal>break_const</literal> function creates a lambda functor that
+takes its arguments as const, and casts away constness prior to the call
+to the original wrapped lambda functor.
+
+For example:
+<programlisting>
+int i;
+...
+(_1 += _2)(i, 2); // error, 2 is a non-const rvalue
+const_parameters(_1 += _2)(i, 2); // error, i becomes const
+break_const(_1 += _2)(i, 2); // ok, but dangerous
+</programlisting>
+
+Note, that the results of <literal> break_const</literal> or
+<literal>const_parameters</literal> are not lambda functors,
+so they cannot be used as subexpressions of lambda expressions. For instance:
+
+<programlisting>
+break_const(_1 + _2) + _3; // fails.
+const_parameters(_1 + _2) + _3; // fails.
+</programlisting>
+
+However, this kind of code should never be necessary,
+since calls to sub lambda functors are made inside the BLL,
+and are not affected by the non-const rvalue problem.
+</para>
+</listitem>
+
+</orderedlist>
+
+</para>
+</section>
+
+</section>
+
+
+<section>
+<title>Casts, sizeof and typeid</title>
+
+<section id="lambda.cast_expressions">
+<title>
+Cast expressions
+</title>
+<para>
+The BLL defines its counterparts for the four cast expressions
+<literal>static_cast</literal>, <literal>dynamic_cast</literal>,
+<literal>const_cast</literal> and <literal>reinterpret_cast</literal>.
+
+The BLL versions of the cast expressions have the prefix
+<literal>ll_</literal>.
+
+The type to cast to is given as an explicitly specified template argument,
+and the sole argument is the expression from which to perform the cast.
+
+If the argument is a lambda functor, the lambda functor is evaluated first.
+
+For example, the following code uses <literal>ll_dynamic_cast</literal>
+to count the number of <literal>derived</literal> instances in the container
+<literal>a</literal>:
+
+<programlisting>
+<![CDATA[class base {};
+class derived : public base {};
+
+vector<base*> a;
+...
+int count = 0;
+for_each(a.begin(), a.end(),
+ if_then(ll_dynamic_cast<derived*>(_1), ++var(count)));]]>
+</programlisting>
+</para>
+</section>
+
+<section>
+<title>Sizeof and typeid</title>
+<para>
+The BLL counterparts for these expressions are named
+<literal>ll_sizeof</literal> and <literal>ll_typeid</literal>.
+
+Both take one argument, which can be a lambda expression.
+The lambda functor created wraps the <literal>sizeof</literal> or
+<literal>typeid</literal> call, and when the lambda functor is called
+the wrapped operation is performed.
+
+For example:
+
+<programlisting>
+<![CDATA[vector<base*> a;
+...
+for_each(a.begin(), a.end(),
+ cout << bind(&type_info::name, ll_typeid(*_1)));]]>
+</programlisting>
+
+Here <literal>ll_typeid</literal> creates a lambda functor for
+calling <literal>typeid</literal> for each element.
+
+The result of a <literal>typeid</literal> call is an instance of
+the <literal>type_info</literal> class, and the bind expression creates
+a lambda functor for calling the <literal>name</literal> member
+function of that class.
+
+</para>
+</section>
+
+
+
+</section>
+
+<section id="lambda.nested_stl_algorithms">
+<title>Nesting STL algorithm invocations</title>
+
+<para>
+The BLL defines common STL algorithms as function object classes,
+instances of which can be used as target functions in bind expressions.
+For example, the following code iterates over the elements of a
+two-dimensional array, and computes their sum.
+
+<programlisting>
+int a[100][200];
+int sum = 0;
+
+std::for_each(a, a + 100,
+ bind(ll::for_each(), _1, _1 + 200, protect(sum += _1)));
+</programlisting>
+
+The BLL versions of the STL algorithms are classes, which define the function call operator (or several overloaded ones) to call the corresponding function templates in the <literal>std</literal> namespace.
+All these structs are placed in the subnamespace <literal>boost::lambda:ll</literal>.
+<!--The supported algorithms are listed in <xref linkend="table:nested_algorithms"/>.-->
+</para>
+
+<para>
+Note that there is no easy way to express an overloaded member function
+call in a lambda expression.
+
+This limits the usefulness of nested STL algorithms, as for instance
+the <literal>begin</literal> function has more than one overloaded
+definitions in container templates.
+
+In general, something analogous to the pseudo-code below cannot be written:
+
+<programlisting>
+std::for_each(a.begin(), a.end(),
+ bind(ll::for_each(), _1.begin(), _1.end(), protect(sum += _1)));
+</programlisting>
+
+Some aid for common special cases can be provided though.
+
+The BLL defines two helper function object classes,
+<literal>call_begin</literal> and <literal>call_end</literal>,
+which wrap a call to the <literal>begin</literal> and, respectively,
+<literal>end</literal> functions of a container, and return the
+<literal>const_iterator</literal> type of the container.
+
+With these helper templates, the above code becomes:
+<programlisting>
+std::for_each(a.begin(), a.end(),
+ bind(ll::for_each(),
+ bind(call_begin(), _1), bind(call_end(), _1),
+ protect(sum += _1)));
+</programlisting>
+
+</para>
+
+<!--
+<table id="table:nested_algorithms">
+<title>The nested STL algorithms.</title>
+<tgroup cols="1">
+<thead>
+<trow><entry>Otsikko</entry></trow>
+</thead>
+<tbody>
+<row><entry><literal>for_each</literal></entry></row>
+<row><entry><literal>find</literal></entry></row>
+<row><entry><literal>find_if</literal></entry></row>
+<row><entry><literal>find_end</literal></entry></row>
+<row><entry><literal>find_first_of</literal></entry></row>
+<row><entry><literal>transform</literal></entry></row>
+</tbody>
+</tgroup>
+
+</table>
+
+-->
+
+</section>
+
+
+</section>
+
+
+<!--
+<section>
+<title>Common gothcas</title>
+
+calling member functions a.begin()
+
+calling templated functions ...
+
+</section>
+
+-->
+
+<section id="lambda.extending">
+<title>Extending return type deduction system</title>
+
+<para>
+<!--The <xref linkend = "lambda.overriding_deduced_return_type"/> showed how to make BLL aware of the return type of a function object in bind expressions.-->
+
+In this section, we explain how to extend the return type deduction system
+to cover user defined operators.
+
+In many cases this is not necessary,
+as the BLL defines default return types for operators.
+
+For example, the default return type for all comparison operators is
+<literal>bool</literal>, and as long as the user defined comparison operators
+have a bool return type, there is no need to write new specializations
+for the return type deduction classes.
+
+Sometimes this cannot be avoided, though.
+
+</para>
+
+<para>
+The overloadable user defined operators are either unary or binary.
+
+For each arity, there are two traits templates that define the
+return types of the different operators.
+
+Hence, the return type system can be extended by providing more
+specializations for these templates.
+
+The templates for unary functors are
+
+<literal>
+<![CDATA[plain_return_type_1<Action, A>]]>
+</literal>
+
+and
+
+<literal>
+<![CDATA[return_type_1<Action, A>]]>
+</literal>, and
+
+<literal>
+<![CDATA[plain_return_type_2<Action, A, B>]]>
+</literal>
+
+and
+
+<literal>
+<![CDATA[return_type_2<Action, A, B>]]>
+</literal>
+
+respectively for binary functors.
+
+</para>
+
+<para>
+The first parameter (<literal>Action</literal>) to all these templates
+is the <emphasis>action</emphasis> class, which specifies the operator.
+
+Operators with similar return type rules are grouped together into
+<emphasis>action groups</emphasis>,
+and only the action class and action group together define the operator
+unambiguously.
+
+As an example, the action type
+<literal><![CDATA[arithmetic_action<plus_action>]]></literal> stands for
+<literal>operator+</literal>.
+
+The complete listing of different action types is shown in
+<xref linkend="table:actions"/>.
+</para>
+
+<para>
+The latter parameters, <literal>A</literal> in the unary case,
+or <literal>A</literal> and <literal>B</literal> in the binary case,
+stand for the argument types of the operator call.
+
+The two sets of templates,
+<literal>plain_return_type_<parameter>n</parameter></literal> and
+<literal>return_type_<parameter>n</parameter></literal>
+(<parameter>n</parameter> is 1 or 2) differ in the way how parameter types
+are presented to them.
+
+For the former templates, the parameter types are always provided as
+non-reference types, and do not have const or volatile qualifiers.
+
+This makes specializing easy, as commonly one specialization for each
+user defined operator, or operator group, is enough.
+
+On the other hand, if a particular operator is overloaded for different
+cv-qualifications of the same argument types,
+and the return types of these overloaded versions differ, a more fine-grained control is needed.
+
+Hence, for the latter templates, the parameter types preserve the
+cv-qualifiers, and are non-reference types as well.
+
+The downside is, that for an overloaded set of operators of the
+kind described above, one may end up needing up to
+16 <literal>return_type_2</literal> specializations.
+</para>
+
+<para>
+Suppose the user has overloaded the following operators for some user defined
+types <literal>X</literal>, <literal>Y</literal> and <literal>Z</literal>:
+
+<programlisting>
+<![CDATA[Z operator+(const X&, const Y&);
+Z operator-(const X&, const Y&);]]>
+</programlisting>
+
+Now, one can add a specialization stating, that if the left hand argument
+is of type <literal>X</literal>, and the right hand one of type
+<literal>Y</literal>, the return type of all such binary arithmetic
+operators is <literal>Z</literal>:
+
+<programlisting>
+<![CDATA[namespace boost {
+namespace lambda {
+
+template<class Act>
+struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+}
+}]]>
+</programlisting>
+
+Having this specialization defined, BLL is capable of correctly
+deducing the return type of the above two operators.
+
+Note, that the specializations must be in the same namespace,
+<literal>::boost::lambda</literal>, with the primary template.
+
+For brevity, we do not show the namespace definitions in the examples below.
+</para>
+
+<para>
+It is possible to specialize on the level of an individual operator as well,
+in addition to providing a specialization for a group of operators.
+Say, we add a new arithmetic operator for argument types <literal>X</literal>
+and <literal>Y</literal>:
+
+<programlisting>
+<![CDATA[X operator*(const X&, const Y&);]]>
+</programlisting>
+
+Our first rule for all arithmetic operators specifies that the return
+type of this operator is <literal>Z</literal>,
+which obviously is not the case.
+Hence, we provide a new rule for the multiplication operator:
+
+<programlisting>
+<![CDATA[template<>
+struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
+ typedef X type;
+};]]>
+</programlisting>
+</para>
+
+<para>
+The specializations can define arbitrary mappings from the argument types
+to the return type.
+
+Suppose we have some mathematical vector type, templated on the element type:
+
+<programlisting>
+<![CDATA[template <class T> class my_vector;]]>
+</programlisting>
+
+Suppose the addition operator is defined between any two
+<literal>my_vector</literal> instantiations,
+as long as the addition operator is defined between their element types.
+
+Furthermore, the element type of the resulting <literal>my_vector</literal>
+is the same as the result type of the addition between the element types.
+
+E.g., adding <literal><![CDATA[my_vector<int>]]></literal> and
+<literal><![CDATA[my_vector<double>]]></literal> results in
+<literal><![CDATA[my_vector<double>]]></literal>.
+
+The BLL has traits classes to perform the implicit built-in and standard
+type conversions between integral, floating point, and complex classes.
+
+Using BLL tools, the addition operator described above can be defined as:
+
+<programlisting>
+<![CDATA[template<class A, class B>
+my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type>
+operator+(const my_vector<A>& a, const my_vector<B>& b)
+{
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
+ return my_vector<res_type>();
+}]]>
+</programlisting>
+</para>
+
+<para>
+To allow BLL to deduce the type of <literal>my_vector</literal>
+additions correctly, we can define:
+
+<programlisting>
+<![CDATA[template<class A, class B>
+class plain_return_type_2<arithmetic_action<plus_action>,
+ my_vector<A>, my_vector<B> > {
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
+public:
+ typedef my_vector<res_type> type;
+};]]>
+</programlisting>
+Note, that we are reusing the existing specializations for the
+BLL <literal>return_type_2</literal> template,
+which require that the argument types are references.
+</para>
+
+<!-- TODO: is an example of specifying the other level needed at all -->
+<!-- TODO: comma operator is a special case for that -->
+
+<table id = "table:actions">
+<title>Action types</title>
+<tgroup cols="2">
+<tbody>
+
+<row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[arithmetic_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[arithmetic_action<minus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[arithmetic_action<multiply_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[/]]></literal></entry><entry><literal><![CDATA[arithmetic_action<divide_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[%]]></literal></entry><entry><literal><![CDATA[arithmetic_action<remainder_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<minus_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[bitwise_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[|]]></literal></entry><entry><literal><![CDATA[bitwise_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[~]]></literal></entry><entry><literal><![CDATA[bitwise_action<not_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[^]]></literal></entry><entry><literal><![CDATA[bitwise_action<xor_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<<]]></literal></entry><entry><literal><![CDATA[bitwise_action<leftshift_action_no_stream>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>>]]></literal></entry><entry><literal><![CDATA[bitwise_action<rightshift_action_no_stream>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&&]]></literal></entry><entry><literal><![CDATA[logical_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[||]]></literal></entry><entry><literal><![CDATA[logical_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[!]]></literal></entry><entry><literal><![CDATA[logical_action<not_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[<]]></literal></entry><entry><literal><![CDATA[relational_action<less_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>]]></literal></entry><entry><literal><![CDATA[relational_action<greater_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<=]]></literal></entry><entry><literal><![CDATA[relational_action<lessorequal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>=]]></literal></entry><entry><literal><![CDATA[relational_action<greaterorequal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[==]]></literal></entry><entry><literal><![CDATA[relational_action<equal_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[!=]]></literal></entry><entry><literal><![CDATA[relational_action<notequal_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[+=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<plus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[-=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<minus_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<multiply_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[/=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<divide_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[%=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<remainder_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<and_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[=|]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<or_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[^=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<xor_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[<<=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<leftshift_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[>>=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<rightshift_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<increment_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<decrement_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<increment_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<decrement_action>]]></literal></entry></row>
+
+
+
+<row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[other_action<address_of_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[other_action<contents_of_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[,]]></literal></entry><entry><literal><![CDATA[other_action<comma_action>]]></literal></entry></row>
+<row><entry><literal><![CDATA[->*]]></literal></entry><entry><literal><![CDATA[other_action<member_pointer_action>]]></literal></entry></row>
+
+</tbody>
+</tgroup>
+</table>
+
+</section>
+
+
+<section>
+<title>Practical considerations</title>
+
+
+<section>
+<title>Performance</title>
+
+<para>In theory, all overhead of using STL algorithms and lambda functors
+compared to hand written loops can be optimized away, just as the overhead
+from standard STL function objects and binders can.
+
+Depending on the compiler, this can also be true in practice.
+We ran two tests with the GCC 3.0.4 compiler on 1.5 GHz Intel Pentium 4.
+The optimization flag -03 was used.
+</para>
+
+<para>
+In the first test we compared lambda functors against explicitly written
+function objects.
+We used both of these styles to define unary functions which multiply the
+argument repeatedly by itself.
+We started with the identity function, going up to
+x<superscript>5</superscript>.
+The expressions were called inside a <literal>std::transform</literal> loop,
+reading the argument from one <literal><![CDATA[std::vector<int>]]></literal>
+and placing the result into another.
+The length of the vectors was 100 elements.
+The running times are listed in
+<xref linkend="table:increasing_arithmetic_test"/>.
+
+We can observe that there is no significant difference between the
+two approaches.
+</para>
+
+<para>
+In the second test we again used <literal>std::transform</literal> to
+perform an operation to each element in a 100-element long vector.
+This time the element type of the vectors was <literal>double</literal>
+and we started with very simple arithmetic expressions and moved to
+more complex ones.
+The running times are listed in <xref linkend="table:ll_vs_stl_test"/>.
+
+Here, we also included classic STL style unnamed functions into tests.
+We do not show these expressions, as they get rather complex.
+For example, the
+last expression in <xref linkend="table:ll_vs_stl_test"/> written with
+classic STL tools contains 7 calls to <literal>compose2</literal>,
+8 calls to <literal>bind1st</literal>
+and altogether 14 constructor invocations for creating
+<literal>multiplies</literal>, <literal>minus</literal>
+and <literal>plus</literal> objects.
+
+In this test the BLL expressions are a little slower (roughly 10% on average,
+less than 14% in all cases)
+than the corresponding hand-written function objects.
+The performance hit is a bit greater with classic STL expressions,
+up to 27% for the simplest expressios.
+</para>
+
+<para>
+The tests suggest that the BLL does not introduce a loss of performance
+compared to STL function objects.
+With a reasonable optimizing compiler, one should expect the performance characteristics be comparable to using classic STL.
+Moreover, with simple expressions the performance can be expected to be close
+to that of explicitly written function objects.
+
+<!-- We repeated both tests with the KAI C++ 4.0f compiler (using +K2 -O3 flags),
+generally considered a good optimizing compiler.
+We do not list the results here, since the running times for the two alternatives in the first test were essentially the same, just as the running times
+for the three different alternatives in the second test.
+These tests suggest there to be no performance penalty at all
+with a good optimizing compiler.
+-->
+
+Note however, that evaluating a lambda functor consist of a sequence of calls to small functions that are declared inline.
+If the compiler fails to actually expand these functions inline,
+the performance can suffer.
+The running time can more than double if this happens.
+Although the above tests do not include such an expression, we have experienced
+this for some seemingly simple expressions.
+
+
+<table id = "table:increasing_arithmetic_test">
+<title>Test 1</title>
+<caption>CPU time of expressions with integer multiplication written as a lambda expression and as a traditional hand-coded function object class.
+The running times are expressed in arbitrary units.</caption>
+<tgroup cols="3">
+<thead>
+<row>
+<entry>expression</entry><entry>lambda expression</entry><entry>hand-coded function object</entry></row>
+</thead>
+
+<tbody>
+
+<row>
+<entry>x</entry><entry>240</entry><entry>230</entry>
+</row>
+
+<row>
+<entry>x*x</entry><entry>340</entry><entry>350</entry>
+</row>
+
+<row>
+<entry>x*x*x</entry><entry>770</entry><entry>760</entry>
+</row>
+
+<row>
+<entry>x*x*x*x</entry><entry>1180</entry><entry>1210</entry>
+</row>
+
+<row>
+<entry>x*x*x*x*x</entry><entry>1950</entry><entry>1910</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+</para>
+
+<!--
+16:19:49 bench [601] ./arith.out 100 1000000
+
+Number of elements = 100
+L1 : 240
+L2 : 340
+L3 : 770
+L4 : 1180
+L5 : 1950
+
+P2 : 1700
+P3 : 2130
+P4 : 2530
+P5 : 3000
+
+F1 : 230
+F2 : 350
+F3 : 760
+F4 : 1210
+F5 : 1910
+
+
+Number of elements = 100
+Number of outer_iters = 1000000
+L1 : 330
+L2 : 350
+L3 : 470
+L4 : 620
+L5 : 1660
+LP : 1230
+C1 : 370
+C2 : 370
+C3 : 500
+C4 : 670
+C5 : 1660
+CP : 1770
+F1 : 290
+F2 : 310
+F3 : 420
+F4 : 600
+F5 : 1460
+FP : 1040
+
+-->
+
+
+<para>
+<table id = "table:ll_vs_stl_test">
+<title>Test 2</title>
+<caption>CPU time of arithmetic expressions written as lambda
+expressions, as classic STL unnamed functions (using <literal>compose2</literal>, <literal>bind1st</literal> etc.) and as traditional hand-coded function object classes.
+Using BLL terminology,
+<literal>a</literal> and <literal>b</literal> are bound arguments in the expressions, and <literal>x</literal> is open.
+All variables were of types <literal>double</literal>.
+The running times are expressed in arbitrary units.</caption>
+<tgroup cols="4">
+<thead>
+<row>
+<entry>expression</entry><entry>lambda expression</entry><entry>classic STL expression</entry><entry>hand-coded function object</entry></row>
+</thead>
+
+<tbody>
+
+<row>
+<entry>ax</entry><entry>330</entry><entry>370</entry><entry>290</entry>
+</row>
+
+<row>
+<entry>-ax</entry><entry>350</entry><entry>370</entry><entry>310</entry>
+</row>
+
+<row>
+<entry>ax-(a+x)</entry><entry>470</entry><entry>500</entry><entry>420</entry>
+</row>
+
+<row>
+<entry>(ax-(a+x))(a+x)</entry><entry>620</entry><entry>670</entry><entry>600</entry>
+</row>
+
+<row>
+<entry>((ax) - (a+x))(bx - (b+x))(ax - (b+x))(bx - (a+x))</entry><entry>1660</entry><entry>1660</entry><entry>1460</entry>
+</row>
+
+</tbody>
+</tgroup>
+
+</table>
+</para>
+
+
+<para>Some additional performance testing with an earlier version of the
+library is described
+<xref linkend="cit:jarvi:00"/>.
+</para>
+
+</section>
+ <section>
+ <title>About compiling</title>
+
+ <para>The BLL uses templates rather heavily, performing numerous recursive instantiations of the same templates.
+This has (at least) three implications:
+<itemizedlist>
+
+<listitem>
+<para>
+While it is possible to write incredibly complex lambda expressions, it probably isn't a good idea.
+Compiling such expressions may end up requiring a lot of memory
+at compile time, and being slow to compile.
+</para>
+</listitem>
+
+
+<listitem>
+<para>
+The types of lambda functors that result from even the simplest lambda expressions are cryptic.
+Usually the programmer doesn't need to deal with the lambda functor types at all, but in the case of an error in a lambda expression, the compiler usually outputs the types of the lambda functors involved.
+This can make the error messages very long and difficult to interpret, particularly if the compiler outputs the whole chain of template instantiations.
+</para>
+</listitem>
+
+<listitem>
+<para>
+The C++ Standard suggests a template nesting level of 17 to help detect infinite recursion.
+Complex lambda templates can easily exceed this limit.
+Most compilers allow a greater number of nested templates, but commonly require the limit explicitly increased with a command line argument.
+</para>
+</listitem>
+</itemizedlist></para>
+
+ </section>
+
+ <section>
+ <title>Portability</title>
+ <para>
+The BLL works with the following compilers, that is, the compilers are capable of compiling the test cases that are included with the BLL:
+
+ <itemizedlist>
+ <listitem>GCC 3.0.4
+ </listitem>
+ <listitem>KCC 4.0f with EDG 2.43.1
+ </listitem>
+ <listitem>GCC 2.96 (fails with one test case, the <filename>exception_test.cpp</filename> results in an internal compiler error.
+)
+
+ </listitem>
+ </itemizedlist>
+</para>
+
+ <section>
+ <title>Test coverage</title>
+
+<para>The following list describes the test files included and the features that each file covers:
+
+<itemizedlist>
+<listitem>
+<para>
+<filename>bind_tests_simple.cpp</filename> : Bind expressions of different arities and types of target functions: function pointers, function objects and member functions.
+Function composition with bind expressions.</para>
+</listitem>
+
+<listitem>
+<para><filename>bind_tests_simple_function_references.cpp</filename> :
+Repeats all tests from <filename moreinfo="none">bind_tests_simple.cpp</filename> where the target function is a function pointer, but uses function references instead.
+</para></listitem>
+
+
+<listitem>
+<para><filename>bind_tests_advanced.cpp</filename> : Contains tests for nested bind expressions, <literal>unlambda</literal>, <literal>protect</literal>, <literal>const_parameters</literal> and <literal>break_const</literal>.
+Tests passing lambda functors as actual arguments to other lambda functors, currying, and using the <literal>sig</literal> template to specify the return type of a function object.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>operator_tests_simple.cpp</filename> :
+Tests using all operators that are overloaded for lambda expressions, that is, unary and binary arithmetic,
+bitwise,
+comparison,
+logical,
+increment and decrement,
+compound,
+assignment,
+subscrict,
+address of,
+dereference, and comma operators.
+The streaming nature of shift operators is tested, as well as pointer arithmetic with plus and minus operators.
+</para>
+</listitem>
+
+<listitem>
+<para><filename>member_pointer_test.cpp</filename> : The pointer to member operator is complex enough to warrant a separate test file.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>control_structures.cpp</filename> :
+Tests for the looping and if constructs.
+</para></listitem>
+
+<listitem>
+<para>
+<filename>switch_construct.cpp</filename> :
+Includes tests for all supported arities of the switch statement, both with and without the default case.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>exception_test.cpp</filename> :
+Includes tests for throwing exceptions and for try/catch constructs with varying number of catch blocks.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>constructor_tests.cpp</filename> :
+Contains tests for <literal>constructor</literal>, <literal>destructor</literal>, <literal>new_ptr</literal>, <literal>delete_ptr</literal>, <literal>new_array</literal> and <literal>delete_array</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>cast_test.cpp</filename> : Tests for the four cast expressions, as well as <filename>typeid</filename> and <literal>sizeof</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>extending_return_type_traits.cpp</filename> : Tests extending the return type deduction system for user defined types.
+Contains several user defined operators and the corresponding specializations for the return type deduction templates.
+</para>
+</listitem>
+
+<listitem>
+<para>
+<filename>is_instance_of_test.cpp</filename> : Includes tests for an internally used traits template, which can detect whether a given type is an instance of a certain template or not.
+</para></listitem>
+
+<listitem>
+<para>
+<filename>bll_and_function.cpp</filename> :
+Contains tests for using <literal>boost::function</literal> together with lambda functors.
+</para></listitem>
+
+ </itemizedlist>
+
+</para>
+
+ </section>
+
+ </section>
+
+
+</section>
+
+
+<section>
+<title>Relation to other Boost libraries</title>
+
+<section>
+<title>Boost Function</title>
+
+<para>Sometimes it is convenient to store lambda functors in variables.
+However, the types of even the simplest lambda functors are long and unwieldy, and it is in general unfeasible to declare variables with lambda functor types.
+<emphasis>The Boost Function library</emphasis> <xref linkend="cit:boost::function"/> defines wrappers for arbitrary function objects, for example
+lambda functors; and these wrappers have types that are easy to type out.
+
+For example:
+
+<programlisting>
+<![CDATA[boost::function<int(int, int)> f = _1 + _2;
+boost::function<int&(int&)> g = (_1 += 10);
+int i = 1, j = 2;
+f(i, j); // returns 3
+g(i); // sets i to = 11;]]>
+</programlisting>
+
+The return and parameter types of the wrapped function object must be written explicilty as the template argument to the wrapper template <literal>boost::function</literal>; even when lambda functors, which otherwise have generic parameters, are wrapped.
+Wrapping a function object with <literal>boost::function</literal> introduces a performance cost comparable to virtual function dispatch, though virtual functions are not actually used.
+
+Note that storing lambda functors inside <literal>boost::function</literal>
+introduces a danger.
+Certain types of lambda functors may store references to the bound
+arguments, instead as taking copies of the arguments of the lambda expression.
+When temporary lambda functor objects are used
+in STL algorithm invocations this is always safe, as the lambda functor gets
+destructed immediately after the STL algortihm invocation is completed.
+
+However, a lambda functor wrapped inside <literal>boost::function</literal>
+may continue to exist longer, creating the possibility of dangling references.
+For example:
+
+<programlisting>
+<![CDATA[int* sum = new int();
+*sum = 0;
+boost::function<int&(int)> counter = *sum += _1;
+counter(5); // ok, *sum = 5;
+delete sum;
+counter(3); // error, *sum does not exist anymore]]>
+</programlisting>
+
+</para>
+
+</section>
+
+<section>
+<title>Boost Bind</title>
+<para>
+<emphasis>The Boost Bind</emphasis> <xref linkend="cit:boost::bind"/> library has partially overlapping functionality with the BLL.
+Basically, the Boost Bind library (BB in the sequel) implements the bind expression part of BLL.
+There are, however, some semantical differerences.
+</para>
+<para>
+The BLL and BB evolved separately, and have different implementations.
+This means that the bind expressions from the BB cannot be used within
+bind expressions, or within other type of lambda expressions, of the BLL.
+The same holds for using BLL bind expressions in the BB.
+The libraries can coexist, however, as
+the names of the BB library are in <literal>boost</literal> namespace,
+whereas the BLL names are in <literal>boost::lambda</literal> namespace.
+</para>
+
+<para>
+The BLL requires a compiler that is reasonably conformant to the
+C++ standard, whereas the BB library is more portable, and works with
+a larger set of compilers.
+</para>
+
+<para>
+The following two sections describe what are the semantic differences
+between the bind expressions in BB and BLL.
+</para>
+
+
+
+
+<section>
+<title>First argument of bind expression</title>
+
+In BB the first argument of the bind expression, the target function,
+is treated differently from the other arguments,
+as no argument substitution takes place within that argument.
+In BLL the first argument is not a special case in this respect.
+
+For example:
+
+<programlisting>
+<![CDATA[template<class F>
+int foo(const F& f) {
+ int x;
+ ..
+ bind(f, _1)(x);
+ ...
+}]]>
+</programlisting>
+
+<programlisting>
+<![CDATA[int bar(int, int);
+nested(bind(bar, 1, _1));]]>
+</programlisting>
+
+The bind expression inside <literal>foo</literal> becomes:
+<programlisting>
+bind(bind(bar, 1, _1), _1)(x)
+</programlisting>
+
+The BLL interpretes this as:
+<programlisting>
+bar(1, x)(x)
+</programlisting>
+whereas the BB library as
+<programlisting>
+bar(1, x)
+</programlisting>
+
+To get this functionality in BLL, the bind expression inside the <literal moreinfo="none">foo</literal> function can be written as:
+<programlisting>
+bind(unlambda(f), _1)(x);
+</programlisting>
+as explained in <xref linkend = "lambda.unlambda"/>.
+
+</section>
+
+
+
+
+<para>
+The BB library supports up to nine placeholders, while the BLL
+defines only three placeholders.
+The rationale for not providing more, is that the highest arity of the
+function objects accepted by any STL algorithm is two.
+The placeholder count is easy to increase in the BB library.
+In BLL it is possible, but more laborous.
+The BLL currently passes the actual arguments to the lambda functors
+internally just as they are and does not wrap them inside a tuple object.
+The reason for this is that some widely used compilers are not capable
+of optimizing the intermediate tuple objects away.
+The creation of the intermediate tuples would cause a significant
+performance hit, particularly for the simplest (and thus the most common)
+lambda functors.
+We are working on a hybrid approach, which will allow more placeholders
+but not compromise the performance of simple lambda functors.
+</para>
+
+</section>
+
+ </section>
+
+
+<section>
+<title>Contributors</title>
+
+The main body of the library was written by Jaakko Järvi and Gary Powell.
+We've got outside help, suggestions and ideas from Jeremy Siek, Peter Higley, Peter Dimov, Valentin Bonnard, William Kempf.
+We would particularly like to mention Joel de Guzmann and his work with
+Phoenix which has influenced BLL significantly, making it considerably simpler
+to extend the library with new features.
+
+</section>
+
+
+
+<section>
+<title>Rationale for some of the design decisions</title>
+
+<section id="lambda.why_weak_arity">
+<title>
+Lambda functor arity
+</title>
+
+<para>
+The highest placeholder index in a lambda expression determines the arity of the resulting function object.
+However, this is just the minimal arity, as the function object can take arbitrarily many arguments; those not needed are discarded.
+Consider the two bind expressions and their invocations below:
+
+<programlisting>
+bind(g, _3, _3, _3)(x, y, z);
+bind(g, _1, _1, _1)(x, y, z);
+</programlisting>
+
+This first line discards arguments <literal>x</literal> and
+<literal>y</literal>, and makes the call:
+<programlisting>
+g(z, z, z)
+</programlisting>
+whereas the second line discards arguments <literal>y</literal> and
+<literal>z</literal>, and calls:
+<programlisting>
+g(x, x, x)
+</programlisting>
+In earlier versions of the library, the latter line resulted in a compile
+time error.
+
+This is basically a tradeoff between safety and flexibility, and the issue
+was extensively discussed during the Boost review period of the library.
+The main points for the <emphasis>strict arity</emphasis> checking
+was that it might
+catch a programming error at an earlier time and that a lambda expression that
+explicitly discards its arguments is easy to write:
+<programlisting>
+(_3, bind(g, _1, _1, _1))(x, y, z);
+</programlisting>
+This lambda expression takes three arguments.
+The left-hand argument of the comma operator does nothing, and as comma
+returns the result of evaluating the right-hand argument we end up with
+the call
+<literal>g(x, x, x)</literal>
+even with the strict arity.
+</para>
+
+<para>
+The main points against the strict arity checking were that the need to
+discard arguments is commonplace, and should therefore be straightforward,
+and that strict arity checking does not really buy that much more safety,
+particularly as it is not symmetric.
+For example, if the programmer wanted to write the expression
+<literal>_1 + _2</literal> but mistakenly wrote <literal>_1 + 2</literal>,
+with strict arity checking, the complier would spot the error.
+However, if the erroneous expression was <literal>1 + _2</literal> instead,
+the error would go unnoticed.
+Furthermore, weak arity checking simplifies the implementation a bit.
+Following the recommendation of the Boost review, strict arity checking
+was dropped.
+</para>
+
+</section>
+
+</section>
+
+
+
+<bibliography>
+
+<biblioentry id="cit:stepanov:94">
+<abbrev>STL94</abbrev>
+<authorgroup>
+<author>
+<surname>Stepanov</surname>
+<firstname>A. A.</firstname>
+</author>
+<author>
+<surname>Lee</surname>
+<firstname>M.</firstname>
+</author>
+</authorgroup>
+<title>The Standard Template Library</title>
+<orgname>Hewlett-Packard Laboratories</orgname>
+<pubdate>1994</pubdate>
+<bibliomisc>
+<ulink url="http://www.hpl.hp.com/techreports">www.hpl.hp.com/techreports</ulink>
+</bibliomisc>
+</biblioentry>
+
+<biblioentry id="cit:sgi:02">
+<abbrev>SGI02</abbrev>
+<title>The SGI Standard Template Library</title>
+<pubdate>2002</pubdate>
+<bibliomisc><ulink url="http://www.sgi.com/tech/stl/">www.sgi.com/tech/stl/</ulink></bibliomisc>
+
+</biblioentry>
+
+<biblioentry id="cit:c++:98">
+<abbrev>C++98</abbrev>
+<title>International Standard, Programming Languages &ndash; C++</title>
+<subtitle>ISO/IEC:14882</subtitle>
+<pubdate>1998</pubdate>
+</biblioentry>
+
+
+<biblioentry id="cit:jarvi:99">
+<abbrev>Jär99</abbrev>
+
+<articleinfo>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<title>C++ Function Object Binders Made Easy</title>
+</articleinfo>
+
+<title>Lecture Notes in Computer Science</title>
+<volumenum>1977</volumenum>
+<publishername>Springer</publishername>
+
+<pubdate>2000</pubdate>
+</biblioentry>
+
+
+
+<biblioentry id="cit:jarvi:00">
+<abbrev>Jär00</abbrev>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+<title>The Lambda Library : Lambda Abstraction in C++</title>
+ <orgname>Turku Centre for Computer Science</orgname>
+<bibliomisc>Technical Report </bibliomisc>
+ <issuenum>378</issuenum>
+<pubdate>2000</pubdate>
+<bibliomisc><ulink url="http://www.tucs.fi/Publications/techreports/TR378.php">www.tucs.fi/publications</ulink></bibliomisc>
+
+
+</biblioentry>
+
+
+<biblioentry id="cit:jarvi:01">
+<abbrev>Jär01</abbrev>
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+<title>The Lambda Library : Lambda Abstraction in C++</title>
+ <confgroup>
+ <conftitle>Second Workshop on C++ Template Programming</conftitle>
+ <address>Tampa Bay, OOPSLA'01</address>
+ </confgroup>
+<pubdate>2001</pubdate>
+<bibliomisc><ulink url="http://www.oonumerics.org/tmpw01/">www.oonumerics.org/tmpw01/</ulink></bibliomisc>
+</biblioentry>
+
+<biblioentry id="cit:jarvi:03">
+<abbrev>Jär03</abbrev>
+
+<articleinfo>
+
+<author>
+<surname>Järvi</surname>
+<firstname>Jaakko</firstname>
+</author>
+
+<author>
+<firstname>Gary</firstname>
+<surname>Powell</surname>
+</author>
+
+<author>
+<firstname>Andrew</firstname>
+<surname>Lumsdaine</surname>
+</author>
+<title>The Lambda Library : unnamed functions in C++</title>
+
+</articleinfo>
+
+<title>Software - Practice and Expreience</title>
+<volumenum>33:259-291</volumenum>
+
+
+<pubdate>2003</pubdate>
+</biblioentry>
+
+
+<biblioentry id="cit:boost::tuple">
+<abbrev>tuple</abbrev>
+<title>The Boost Tuple Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html">www.boost.org/libs/tuple/doc/tuple_users_guide.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::type_traits">
+<abbrev>type_traits</abbrev>
+<title>The Boost type_traits</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/type_traits/index.htm">www.boost.org/libs/type_traits/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::ref">
+<abbrev>ref</abbrev>
+<title>Boost ref</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/bind/ref.html">www.boost.org/libs/bind/ref.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::bind">
+<abbrev>bind</abbrev>
+<title>Boost Bind Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/bind/bind.html">www.boost.org/libs/bind/bind.html</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:boost::function">
+<abbrev>function</abbrev>
+<title>Boost Function Library</title>
+<bibliomisc><ulink url="http://www.boost.org/libs/function/">www.boost.org/libs/function/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+<biblioentry id="cit:fc++">
+<abbrev>fc++</abbrev>
+<title>The FC++ library: Functional Programming in C++</title>
+<author>
+<surname>Smaragdakis</surname>
+<firstname>Yannis</firstname>
+</author>
+<author>
+<firstname>Brian</firstname>
+<surname>McNamara</surname>
+</author>
+<bibliomisc><ulink url="http://www.cc.gatech.edu/~yannis/fc++/">www.cc.gatech.edu/~yannis/fc++/</ulink>
+</bibliomisc>
+<pubdate>2002</pubdate>
+</biblioentry>
+
+
+</bibliography>
+
+
+</library>
diff --git a/libs/lambda/index.html b/libs/lambda/index.html
new file mode 100644
index 000000000..788ea5cba
--- /dev/null
+++ b/libs/lambda/index.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=../../doc/html/lambda.html">
+</head>
+<body>
+Automatic redirection failed, please go to <a href="../../doc/html/lambda.html">www.boost.org/doc/html/lambda.html</a>&nbsp;<hr>
+<p>© Copyright Beman Dawes, 2001</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
+at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/libs/lambda/test/Jamfile b/libs/lambda/test/Jamfile
new file mode 100644
index 000000000..7e1a5a7e2
--- /dev/null
+++ b/libs/lambda/test/Jamfile
@@ -0,0 +1,35 @@
+# Lambda library
+
+# Copyright (C) 2001-2003 Jaakko Järvi
+
+# Use, modification and distribution is subject to 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)
+
+# For more information, see http://www.boost.org/
+
+import testing ;
+
+project
+ : requirements <toolset>msvc:<asynch-exceptions>on
+ ;
+
+test-suite lambda
+ : [ run algorithm_test.cpp ]
+ [ run bind_tests_simple.cpp ]
+ [ run bind_tests_advanced.cpp ]
+ [ run bind_tests_simple_f_refs.cpp ]
+ [ run bll_and_function.cpp ]
+ [ run cast_test.cpp : : : : lambda_cast_test ]
+ [ run constructor_tests.cpp ]
+ [ run control_structures.cpp ]
+ [ run exception_test.cpp ]
+ [ run extending_rt_traits.cpp ]
+ [ run is_instance_of_test.cpp ]
+ [ run member_pointer_test.cpp ]
+ [ run operator_tests_simple.cpp ]
+ [ run phoenix_control_structures.cpp ]
+ [ run switch_construct.cpp ]
+ [ run result_of_tests.cpp ]
+ [ run ret_test.cpp ]
+ ;
diff --git a/libs/lambda/test/Makefile b/libs/lambda/test/Makefile
new file mode 100644
index 000000000..f25b5e4ff
--- /dev/null
+++ b/libs/lambda/test/Makefile
@@ -0,0 +1,89 @@
+BOOST = ../../..
+
+CXX = g++
+EXTRAFLAGS = -pedantic -Wno-long-long -Wno-long-double -ftemplate-depth-50
+LIBS = -lstdc++
+
+#CXX = KCC
+#EXTRAFLAGS = --strict --display_error_number --diag_suppress 450 --max_pending_instantiations 50
+#LIBS =
+
+INCLUDES = -I$(BOOST)
+
+
+
+CXXFLAGS = $(INCLUDES) $(EXTRAFLAGS)
+
+LIBFLAGS = $(LIBS)
+
+
+AR = ar
+
+.SUFFIXES: .cpp .o
+
+SOURCES = \
+is_instance_of_test.cpp \
+operator_tests_simple.cpp \
+member_pointer_test.cpp \
+control_structures.cpp \
+switch_construct.cpp \
+bind_tests_simple.cpp \
+bind_tests_advanced.cpp \
+bll_and_function.cpp \
+constructor_tests.cpp \
+extending_rt_traits.cpp \
+bind_tests_simple_f_refs.cpp \
+cast_test.cpp \
+phoenix_control_structures.cpp \
+exception_test.cpp \
+
+
+# Create lists of object files from the source file lists.
+
+OBJECTS = ${SOURCES:.cpp=.o}
+
+TARGETS = ${SOURCES:.cpp=.exe}
+
+all: $(TARGETS)
+
+%.exe: %.o
+ $(CXX) $(LIBFLAGS) $(CXXFLAGS) -o $@ $<
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -o $@ -c $<
+
+%.dep: %.cpp
+ set -e; $(CXX) -M $(INCLUDES) -c $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
+ [ -s $@ ] || rm -f $@
+
+DEP_FILES = $(SOURCES:.cpp=.dep)
+
+include $(DEP_FILES)
+
+clean:
+ /bin/rm -rf $(TARGETS) $(OBJECTS) $(DEP_FILES)
+
+run:
+ ./is_instance_of_test.exe
+ ./member_pointer_test.exe
+ ./operator_tests_simple.exe
+ ./control_structures.exe
+ ./switch_construct.exe
+ ./extending_rt_traits.exe
+ ./constructor_tests.exe
+ ./cast_test.exe
+ ./bind_tests_simple.exe
+ ./bind_tests_advanced.exe
+ ./bll_and_function.exe
+ ./bind_tests_simple_f_refs.exe
+ ./phoenix_control_structures.exe
+ ./exception_test.exe
+
+
+
+
+
+
+
+
diff --git a/libs/lambda/test/README_gcc2.9x_users b/libs/lambda/test/README_gcc2.9x_users
new file mode 100644
index 000000000..5ecec2e51
--- /dev/null
+++ b/libs/lambda/test/README_gcc2.9x_users
@@ -0,0 +1,6 @@
+gcc 2.96
+cannot compile
+
+exception_test.cpp (internal compiler error)
+
+
diff --git a/libs/lambda/test/algorithm_test.cpp b/libs/lambda/test/algorithm_test.cpp
new file mode 100644
index 000000000..079b771d2
--- /dev/null
+++ b/libs/lambda/test/algorithm_test.cpp
@@ -0,0 +1,60 @@
+// bll_and_function.cpp - The Boost Lambda Library -----------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// test using BLL and boost::function
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/bind.hpp"
+#include "boost/lambda/algorithm.hpp"
+
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+#include <iostream>
+
+
+
+void test_foreach() {
+ using namespace boost::lambda;
+
+ int a[10][20];
+ int sum = 0;
+
+ std::for_each(a, a + 10,
+ bind(ll::for_each(), _1, _1 + 20,
+ protect((_1 = var(sum), ++var(sum)))));
+
+ sum = 0;
+ std::for_each(a, a + 10,
+ bind(ll::for_each(), _1, _1 + 20,
+ protect((sum += _1))));
+
+ BOOST_CHECK(sum == (199 + 1)/ 2 * 199);
+}
+
+// More tests needed (for all algorithms)
+
+int test_main(int, char *[]) {
+
+ test_foreach();
+
+ return 0;
+}
+
+
+
+
+
+
diff --git a/libs/lambda/test/bind_tests_advanced.cpp b/libs/lambda/test/bind_tests_advanced.cpp
new file mode 100644
index 000000000..d696e4999
--- /dev/null
+++ b/libs/lambda/test/bind_tests_advanced.cpp
@@ -0,0 +1,420 @@
+// bind_tests_advanced.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+// Copyright (C) 2010 Steven Watanabe
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/bind.hpp"
+
+
+#include "boost/any.hpp"
+#include "boost/type_traits/is_reference.hpp"
+#include "boost/mpl/assert.hpp"
+#include "boost/mpl/if.hpp"
+
+#include <iostream>
+
+#include <functional>
+
+#include <algorithm>
+
+
+using namespace boost::lambda;
+namespace bl = boost::lambda;
+
+int sum_0() { return 0; }
+int sum_1(int a) { return a; }
+int sum_2(int a, int b) { return a+b; }
+
+int product_2(int a, int b) { return a*b; }
+
+// unary function that returns a pointer to a binary function
+typedef int (*fptr_type)(int, int);
+fptr_type sum_or_product(bool x) {
+ return x ? sum_2 : product_2;
+}
+
+// a nullary functor that returns a pointer to a unary function that
+// returns a pointer to a binary function.
+struct which_one {
+ typedef fptr_type (*result_type)(bool x);
+ template <class T> struct sig { typedef result_type type; };
+
+ result_type operator()() const { return sum_or_product; }
+};
+
+void test_nested_binds()
+{
+ int j = 2; int k = 3;
+
+// bind calls can be nested (the target function can be a lambda functor)
+// The interpretation is, that the innermost lambda functor returns something
+// that is bindable (another lambda functor, function pointer ...)
+ bool condition;
+
+ condition = true;
+ BOOST_CHECK(bind(bind(&sum_or_product, _1), 1, 2)(condition)==3);
+ BOOST_CHECK(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==5);
+
+ condition = false;
+ BOOST_CHECK(bind(bind(&sum_or_product, _1), 1, 2)(condition)==2);
+ BOOST_CHECK(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==6);
+
+
+ which_one wo;
+ BOOST_CHECK(bind(bind(bind(wo), _1), _2, _3)(condition, j, k)==6);
+
+
+ return;
+}
+
+
+// unlambda -------------------------------------------------
+
+ // Sometimes it may be necessary to prevent the argument substitution of
+ // taking place. For example, we may end up with a nested bind expression
+ // inadvertently when using the target function is received as a parameter
+
+template<class F>
+int call_with_100(const F& f) {
+
+
+
+ // bind(f, _1)(make_const(100));
+ // This would result in;
+ // bind(_1 + 1, _1)(make_const(100)) , which would be a compile time error
+
+ return bl::bind(unlambda(f), _1)(make_const(100));
+
+ // for other functors than lambda functors, unlambda has no effect
+ // (except for making them const)
+}
+
+template<class F>
+int call_with_101(const F& f) {
+
+ return bind(unlambda(f), _1)(make_const(101));
+
+}
+
+
+void test_unlambda() {
+
+ int i = 1;
+
+ BOOST_CHECK(unlambda(_1 + _2)(i, i) == 2);
+ BOOST_CHECK(unlambda(++var(i))() == 2);
+ BOOST_CHECK(call_with_100(_1 + 1) == 101);
+
+
+ BOOST_CHECK(call_with_101(_1 + 1) == 102);
+
+ BOOST_CHECK(call_with_100(bl::bind(std_functor(std::bind1st(std::plus<int>(), 1)), _1)) == 101);
+
+ // std_functor insturcts LL that the functor defines a result_type typedef
+ // rather than a sig template.
+ bl::bind(std_functor(std::plus<int>()), _1, _2)(i, i);
+}
+
+
+
+
+// protect ------------------------------------------------------------
+
+// protect protects a lambda functor from argument substitution.
+// protect is useful e.g. with nested stl algorithm calls.
+
+namespace ll {
+
+struct for_each {
+
+ // note, std::for_each returns it's last argument
+ // We want the same behaviour from our ll::for_each.
+ // However, the functor can be called with any arguments, and
+ // the return type thus depends on the argument types.
+
+ // 1. Provide a sig class member template:
+
+ // The return type deduction system instantiate this class as:
+ // sig<Args>::type, where Args is a boost::tuples::cons-list
+ // The head type is the function object type itself
+ // cv-qualified (so it is possilbe to provide different return types
+ // for differently cv-qualified operator()'s.
+
+ // The tail type is the list of the types of the actual arguments the
+ // function was called with.
+ // So sig should contain a typedef type, which defines a mapping from
+ // the operator() arguments to its return type.
+ // Note, that it is possible to provide different sigs for the same functor
+ // if the functor has several operator()'s, even if they have different
+ // number of arguments.
+
+ // Note, that the argument types in Args are guaranteed to be non-reference
+ // types, but they can have cv-qualifiers.
+
+ template <class Args>
+ struct sig {
+ typedef typename boost::remove_const<
+ typename boost::tuples::element<3, Args>::type
+ >::type type;
+ };
+
+ template <class A, class B, class C>
+ C
+ operator()(const A& a, const B& b, const C& c) const
+ { return std::for_each(a, b, c);}
+};
+
+} // end of ll namespace
+
+void test_protect()
+{
+ int i = 0;
+ int b[3][5];
+ int* a[3];
+
+ for(int j=0; j<3; ++j) a[j] = b[j];
+
+ std::for_each(a, a+3,
+ bind(ll::for_each(), _1, _1 + 5, protect(_1 = ++var(i))));
+
+ // This is how you could output the values (it is uncommented, no output
+ // from a regression test file):
+ // std::for_each(a, a+3,
+ // bind(ll::for_each(), _1, _1 + 5,
+ // std::cout << constant("\nLine ") << (&_1 - a) << " : "
+ // << protect(_1)
+ // )
+ // );
+
+ int sum = 0;
+
+ std::for_each(a, a+3,
+ bind(ll::for_each(), _1, _1 + 5,
+ protect(sum += _1))
+ );
+ BOOST_CHECK(sum == (1+15)*15/2);
+
+ sum = 0;
+
+ std::for_each(a, a+3,
+ bind(ll::for_each(), _1, _1 + 5,
+ sum += 1 + protect(_1)) // add element count
+ );
+ BOOST_CHECK(sum == (1+15)*15/2 + 15);
+
+ (1 + protect(_1))(sum);
+
+ int k = 0;
+ ((k += constant(1)) += protect(constant(2)))();
+ BOOST_CHECK(k==1);
+
+ k = 0;
+ ((k += constant(1)) += protect(constant(2)))()();
+ BOOST_CHECK(k==3);
+
+ // note, the following doesn't work:
+
+ // ((var(k) = constant(1)) = protect(constant(2)))();
+
+ // (var(k) = constant(1))() returns int& and thus the
+ // second assignment fails.
+
+ // We should have something like:
+ // bind(var, var(k) = constant(1)) = protect(constant(2)))();
+ // But currently var is not bindable.
+
+ // The same goes with ret. A bindable ret could be handy sometimes as well
+ // (protect(std::cout << _1), std::cout << _1)(i)(j); does not work
+ // because the comma operator tries to store the result of the evaluation
+ // of std::cout << _1 as a copy (and you can't copy std::ostream).
+ // something like this:
+ // (protect(std::cout << _1), bind(ref, std::cout << _1))(i)(j);
+
+
+ // the stuff below works, but we do not want extra output to
+ // cout, must be changed to stringstreams but stringstreams do not
+ // work due to a bug in the type deduction. Will be fixed...
+#if 0
+ // But for now, ref is not bindable. There are other ways around this:
+
+ int x = 1, y = 2;
+ (protect(std::cout << _1), (std::cout << _1, 0))(x)(y);
+
+ // added one dummy value to make the argument to comma an int
+ // instead of ostream&
+
+ // Note, the same problem is more apparent without protect
+ // (std::cout << 1, std::cout << constant(2))(); // does not work
+
+ (boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
+
+#endif
+
+}
+
+
+void test_lambda_functors_as_arguments_to_lambda_functors() {
+
+// lambda functor is a function object, and can therefore be used
+// as an argument to another lambda functors function call object.
+
+ // Note however, that the argument/type substitution is not entered again.
+ // This means, that something like this will not work:
+
+ (_1 + _2)(_1, make_const(7));
+ (_1 + _2)(bind(&sum_0), make_const(7));
+
+ // or it does work, but the effect is not to call
+ // sum_0() + 7, but rather
+ // bind(sum_0) + 7, which results in another lambda functor
+ // (lambda functor + int) and can be called again
+ BOOST_CHECK((_1 + _2)(bind(&sum_0), make_const(7))() == 7);
+
+ int i = 3, j = 12;
+ BOOST_CHECK((_1 - _2)(_2, _1)(i, j) == j - i);
+
+ // also, note that lambda functor are no special case for bind if received
+ // as a parameter. In oder to be bindable, the functor must
+ // defint the sig template, or then
+ // the return type must be defined within the bind call. Lambda functors
+ // do define the sig template, so if the return type deduction system
+ // covers the case, there is no need to specify the return type
+ // explicitly.
+
+ int a = 5, b = 6;
+
+ // Let type deduction find out the return type
+ BOOST_CHECK(bind(_1, _2, _3)(unlambda(_1 + _2), a, b) == 11);
+
+ //specify it yourself:
+ BOOST_CHECK(bind(_1, _2, _3)(ret<int>(_1 + _2), a, b) == 11);
+ BOOST_CHECK(ret<int>(bind(_1, _2, _3))(_1 + _2, a, b) == 11);
+ BOOST_CHECK(bind<int>(_1, _2, _3)(_1 + _2, a, b) == 11);
+
+ bind(_1,1.0)(_1+_1);
+ return;
+
+}
+
+
+void test_const_parameters() {
+
+ // (_1 + _2)(1, 2); // this would fail,
+
+ // Either make arguments const:
+ BOOST_CHECK((_1 + _2)(make_const(1), make_const(2)) == 3);
+
+ // Or use const_parameters:
+ BOOST_CHECK(const_parameters(_1 + _2)(1, 2) == 3);
+
+
+
+}
+
+void test_rvalue_arguments()
+{
+ // Not quite working yet.
+ // Problems with visual 7.1
+ // BOOST_CHECK((_1 + _2)(1, 2) == 3);
+}
+
+void test_break_const()
+{
+
+ // break_const is currently unnecessary, as LL supports perfect forwarding
+ // for up to there argument lambda functors, and LL does not support
+ // lambda functors with more than 3 args.
+
+ // I'll keep the test case around anyway, if more arguments will be supported
+ // in the future.
+
+
+
+ // break_const breaks constness! Be careful!
+ // You need this only if you need to have side effects on some argument(s)
+ // and some arguments are non-const rvalues and your lambda functors
+ // take more than 3 arguments.
+
+
+ int i = 1;
+ // OLD COMMENT: (_1 += _2)(i, 2) // fails, 2 is a non-const rvalue
+ // OLD COMMENT: const_parameters(_1 += _2)(i, 2) // fails, side-effect to i
+ break_const(_1 += _2)(i, 2); // ok
+ BOOST_CHECK(i == 3);
+}
+
+template<class T>
+struct func {
+ template<class Args>
+ struct sig {
+ typedef typename boost::tuples::element<1, Args>::type arg1;
+ // If the argument type is not the same as the expected type,
+ // return void, which will cause an error. Note that we
+ // can't just assert that the types are the same, because
+ // both const and non-const versions can be instantiated
+ // even though only one is ultimately used.
+ typedef typename boost::mpl::if_<boost::is_same<arg1, T>,
+ typename boost::remove_const<arg1>::type,
+ void
+ >::type type;
+ };
+ template<class U>
+ U operator()(const U& arg) const {
+ return arg;
+ }
+};
+
+void test_sig()
+{
+ int i = 1;
+ BOOST_CHECK(bind(func<int>(), 1)() == 1);
+ BOOST_CHECK(bind(func<const int>(), _1)(static_cast<const int&>(i)) == 1);
+ BOOST_CHECK(bind(func<int>(), _1)(i) == 1);
+}
+
+class base {
+public:
+ virtual int foo() = 0;
+};
+
+class derived : public base {
+public:
+ virtual int foo() {
+ return 1;
+ }
+};
+
+void test_abstract()
+{
+ derived d;
+ base& b = d;
+ BOOST_CHECK(bind(&base::foo, var(b))() == 1);
+ BOOST_CHECK(bind(&base::foo, *_1)(&b) == 1);
+}
+
+int test_main(int, char *[]) {
+
+ test_nested_binds();
+ test_unlambda();
+ test_protect();
+ test_lambda_functors_as_arguments_to_lambda_functors();
+ test_const_parameters();
+ test_rvalue_arguments();
+ test_break_const();
+ test_sig();
+ test_abstract();
+ return 0;
+}
diff --git a/libs/lambda/test/bind_tests_simple.cpp b/libs/lambda/test/bind_tests_simple.cpp
new file mode 100644
index 000000000..1e63d6958
--- /dev/null
+++ b/libs/lambda/test/bind_tests_simple.cpp
@@ -0,0 +1,187 @@
+// bind_tests_simple.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/bind.hpp"
+
+#include <iostream>
+
+using namespace boost::lambda;
+
+
+int sum_of_args_0() { return 0; }
+int sum_of_args_1(int a) { return a; }
+int sum_of_args_2(int a, int b) { return a+b; }
+int sum_of_args_3(int a, int b, int c) { return a+b+c; }
+int sum_of_args_4(int a, int b, int c, int d) { return a+b+c+d; }
+int sum_of_args_5(int a, int b, int c, int d, int e) { return a+b+c+d+e; }
+int sum_of_args_6(int a, int b, int c, int d, int e, int f) { return a+b+c+d+e+f; }
+int sum_of_args_7(int a, int b, int c, int d, int e, int f, int g) { return a+b+c+d+e+f+g; }
+int sum_of_args_8(int a, int b, int c, int d, int e, int f, int g, int h) { return a+b+c+d+e+f+g+h; }
+int sum_of_args_9(int a, int b, int c, int d, int e, int f, int g, int h, int i) { return a+b+c+d+e+f+g+h+i; }
+
+
+// ----------------------------
+
+class A {
+ int i;
+public:
+ A(int n) : i(n) {};
+ int add(const int& j) { return i + j; }
+ int add2(int a1, int a2) { return i + a1 + a2; }
+ int add3(int a1, int a2, int a3) { return i + a1 + a2 + a3; }
+ int add4(int a1, int a2, int a3, int a4) { return i + a1 + a2 + a3 + a4; }
+ int add5(int a1, int a2, int a3, int a4, int a5)
+ { return i + a1 + a2 + a3 + a4 + a5; }
+ int add6(int a1, int a2, int a3, int a4, int a5, int a6)
+ { return i + a1 + a2 + a3 + a4 + a5 + a6; }
+ int add7(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
+ { return i + a1 + a2 + a3 + a4 + a5 + a6 + a7; }
+ int add8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8)
+ { return i + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8; }
+
+};
+
+void test_member_functions()
+{
+ using boost::ref;
+ A a(10);
+ int i = 1;
+
+
+
+
+ BOOST_CHECK(bind(&A::add, ref(a), _1)(i) == 11);
+ BOOST_CHECK(bind(&A::add, &a, _1)(i) == 11);
+ BOOST_CHECK(bind(&A::add, _1, 1)(a) == 11);
+ BOOST_CHECK(bind(&A::add, _1, 1)(make_const(&a)) == 11);
+
+ BOOST_CHECK(bind(&A::add2, _1, 1, 1)(a) == 12);
+ BOOST_CHECK(bind(&A::add3, _1, 1, 1, 1)(a) == 13);
+ BOOST_CHECK(bind(&A::add4, _1, 1, 1, 1, 1)(a) == 14);
+ BOOST_CHECK(bind(&A::add5, _1, 1, 1, 1, 1, 1)(a) == 15);
+ BOOST_CHECK(bind(&A::add6, _1, 1, 1, 1, 1, 1, 1)(a) == 16);
+ BOOST_CHECK(bind(&A::add7, _1, 1, 1, 1, 1, 1, 1, 1)(a) == 17);
+ BOOST_CHECK(bind(&A::add8, _1, 1, 1, 1, 1, 1, 1, 1, 1)(a) == 18);
+
+ // This should fail, as lambda functors store arguments as const
+ // bind(&A::add, a, _1);
+}
+
+struct B {
+ B(int n) : i(n) {};
+ int i;
+};
+
+void test_data_members()
+{
+ using boost::ref;
+ B b(10);
+ BOOST_CHECK(bind(&B::i, ref(b))() == 10);
+ BOOST_CHECK(bind(&B::i, b)() == 10);
+ BOOST_CHECK(bind(&B::i, _1)(b) == 10);
+ BOOST_CHECK(bind(&B::i, _1)(B(11)) == 11);
+ bind(&B::i, ref(b))() = 1;
+ BOOST_CHECK(b.i == 1);
+}
+
+int test_main(int, char *[]) {
+
+ int i = 1; int j = 2; int k = 3;
+ int result;
+
+ // bind all parameters
+ BOOST_CHECK(bind(&sum_of_args_0)()==0);
+ BOOST_CHECK(bind(&sum_of_args_1, 1)()==1);
+ BOOST_CHECK(bind(&sum_of_args_2, 1, 2)()==3);
+ BOOST_CHECK(bind(&sum_of_args_3, 1, 2, 3)()==6);
+ BOOST_CHECK(bind(&sum_of_args_4, 1, 2, 3, 4)()==10);
+ BOOST_CHECK(bind(&sum_of_args_5, 1, 2, 3, 4, 5)()==15);
+ BOOST_CHECK(bind(&sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
+ BOOST_CHECK(bind(&sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
+ BOOST_CHECK(bind(&sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
+ BOOST_CHECK(bind(&sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
+
+ // first parameter open
+ BOOST_CHECK(bind(&sum_of_args_0)()==0);
+ BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(&sum_of_args_2, _1, 2)(i)==3);
+ BOOST_CHECK(bind(&sum_of_args_3, _1, 2, 3)(i)==6);
+ BOOST_CHECK(bind(&sum_of_args_4, _1, 2, 3, 4)(i)==10);
+ BOOST_CHECK(bind(&sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
+ BOOST_CHECK(bind(&sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
+ BOOST_CHECK(bind(&sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
+ BOOST_CHECK(bind(&sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
+ BOOST_CHECK(bind(&sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
+
+ // two open arguments
+ BOOST_CHECK(bind(&sum_of_args_0)()==0);
+ BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(&sum_of_args_2, _1, _2)(i, j)==3);
+ BOOST_CHECK(bind(&sum_of_args_3, _1, _2, 3)(i, j)==6);
+ BOOST_CHECK(bind(&sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
+ BOOST_CHECK(bind(&sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
+ BOOST_CHECK(bind(&sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
+ BOOST_CHECK(bind(&sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
+ BOOST_CHECK(bind(&sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
+ BOOST_CHECK(bind(&sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
+
+ // three open arguments
+ BOOST_CHECK(bind(&sum_of_args_0)()==0);
+ BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(&sum_of_args_2, _1, _2)(i, j)==3);
+ BOOST_CHECK(bind(&sum_of_args_3, _1, _2, _3)(i, j, k)==6);
+ BOOST_CHECK(bind(&sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
+ BOOST_CHECK(bind(&sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
+ BOOST_CHECK(bind(&sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
+ BOOST_CHECK(bind(&sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
+ BOOST_CHECK(bind(&sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
+ BOOST_CHECK(bind(&sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
+
+ // function compositions with bind
+ BOOST_CHECK(bind(&sum_of_args_3, bind(&sum_of_args_2, _1, 2), 2, 3)(i)==8);
+ BOOST_CHECK(
+ bind(&sum_of_args_9,
+ bind(&sum_of_args_0), // 0
+ bind(&sum_of_args_1, _1), // 1
+ bind(&sum_of_args_2, _1, _2), // 3
+ bind(&sum_of_args_3, _1, _2, _3), // 6
+ bind(&sum_of_args_4, _1, _2, _3, 4), // 10
+ bind(&sum_of_args_5, _1, _2, _3, 4, 5), // 15
+ bind(&sum_of_args_6, _1, _2, _3, 4, 5, 6), // 21
+ bind(&sum_of_args_7, _1, _2, _3, 4, 5, 6, 7), // 28
+ bind(&sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8) // 36
+ )(i, j, k) == 120);
+
+ // deeper nesting
+ result =
+ bind(&sum_of_args_1, // 12
+ bind(&sum_of_args_4, // 12
+ bind(&sum_of_args_2, // 3
+ bind(&sum_of_args_1, // 1
+ bind(&sum_of_args_1, _1) // 1
+ ),
+ _2),
+ _2,
+ _3,
+ 4)
+ )(i, j, k);
+ BOOST_CHECK(result == 12);
+
+ test_member_functions();
+
+
+ return 0;
+}
diff --git a/libs/lambda/test/bind_tests_simple_f_refs.cpp b/libs/lambda/test/bind_tests_simple_f_refs.cpp
new file mode 100644
index 000000000..df601d79e
--- /dev/null
+++ b/libs/lambda/test/bind_tests_simple_f_refs.cpp
@@ -0,0 +1,148 @@
+// bind_tests_simple.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/bind.hpp"
+
+#include <iostream>
+
+using namespace boost::lambda;
+
+
+int sum_of_args_0() { return 0; }
+int sum_of_args_1(int a) { return a; }
+int sum_of_args_2(int a, int b) { return a+b; }
+int sum_of_args_3(int a, int b, int c) { return a+b+c; }
+int sum_of_args_4(int a, int b, int c, int d) { return a+b+c+d; }
+int sum_of_args_5(int a, int b, int c, int d, int e) { return a+b+c+d+e; }
+int sum_of_args_6(int a, int b, int c, int d, int e, int f) { return a+b+c+d+e+f; }
+int sum_of_args_7(int a, int b, int c, int d, int e, int f, int g) { return a+b+c+d+e+f+g; }
+int sum_of_args_8(int a, int b, int c, int d, int e, int f, int g, int h) { return a+b+c+d+e+f+g+h; }
+int sum_of_args_9(int a, int b, int c, int d, int e, int f, int g, int h, int i) { return a+b+c+d+e+f+g+h+i; }
+
+
+// ----------------------------
+
+class A {
+ int i;
+public:
+ A(int n) : i(n) {};
+ int add(const int& j) { return i + j; }
+};
+
+void test_member_functions()
+{
+ using boost::ref;
+ A a(10);
+ int i = 1;
+
+ BOOST_CHECK(bind(&A::add, ref(a), _1)(i) == 11);
+ BOOST_CHECK(bind(&A::add, &a, _1)(i) == 11);
+ BOOST_CHECK(bind(&A::add, _1, 1)(a) == 11);
+ BOOST_CHECK(bind(&A::add, _1, 1)(make_const(&a)) == 11);
+
+ // This should fail, as lambda functors store arguments as const
+ // bind(&A::add, a, _1);
+}
+
+int test_main(int, char *[]) {
+
+ int i = 1; int j = 2; int k = 3;
+ int result;
+
+
+ // bind all parameters
+ BOOST_CHECK(bind(sum_of_args_0)()==0);
+ BOOST_CHECK(bind(sum_of_args_1, 1)()==1);
+ BOOST_CHECK(bind(sum_of_args_2, 1, 2)()==3);
+ BOOST_CHECK(bind(sum_of_args_3, 1, 2, 3)()==6);
+ BOOST_CHECK(bind(sum_of_args_4, 1, 2, 3, 4)()==10);
+ BOOST_CHECK(bind(sum_of_args_5, 1, 2, 3, 4, 5)()==15);
+ BOOST_CHECK(bind(sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
+ BOOST_CHECK(bind(sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
+ BOOST_CHECK(bind(sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
+ BOOST_CHECK(bind(sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
+
+ // first parameter open
+ BOOST_CHECK(bind(sum_of_args_0)()==0);
+ BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(sum_of_args_2, _1, 2)(i)==3);
+ BOOST_CHECK(bind(sum_of_args_3, _1, 2, 3)(i)==6);
+ BOOST_CHECK(bind(sum_of_args_4, _1, 2, 3, 4)(i)==10);
+ BOOST_CHECK(bind(sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
+ BOOST_CHECK(bind(sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
+ BOOST_CHECK(bind(sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
+ BOOST_CHECK(bind(sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
+ BOOST_CHECK(bind(sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
+
+ // two open arguments
+ BOOST_CHECK(bind(sum_of_args_0)()==0);
+ BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(sum_of_args_2, _1, _2)(i, j)==3);
+ BOOST_CHECK(bind(sum_of_args_3, _1, _2, 3)(i, j)==6);
+ BOOST_CHECK(bind(sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
+ BOOST_CHECK(bind(sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
+ BOOST_CHECK(bind(sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
+ BOOST_CHECK(bind(sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
+ BOOST_CHECK(bind(sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
+ BOOST_CHECK(bind(sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
+
+ // three open arguments
+ BOOST_CHECK(bind(sum_of_args_0)()==0);
+ BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
+ BOOST_CHECK(bind(sum_of_args_2, _1, _2)(i, j)==3);
+ BOOST_CHECK(bind(sum_of_args_3, _1, _2, _3)(i, j, k)==6);
+ BOOST_CHECK(bind(sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
+ BOOST_CHECK(bind(sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
+ BOOST_CHECK(bind(sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
+ BOOST_CHECK(bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
+ BOOST_CHECK(bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
+ BOOST_CHECK(bind(sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
+
+ // function compositions with bind
+ BOOST_CHECK(bind(sum_of_args_3, bind(sum_of_args_2, _1, 2), 2, 3)(i)==8);
+ BOOST_CHECK(
+ bind(sum_of_args_9,
+ bind(sum_of_args_0), // 0
+ bind(sum_of_args_1, _1), // 1
+ bind(sum_of_args_2, _1, _2), // 3
+ bind(sum_of_args_3, _1, _2, _3), // 6
+ bind(sum_of_args_4, _1, _2, _3, 4), // 10
+ bind(sum_of_args_5, _1, _2, _3, 4, 5), // 15
+ bind(sum_of_args_6, _1, _2, _3, 4, 5, 6), // 21
+ bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7), // 28
+ bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8) // 36
+ )(i, j, k) == 120);
+
+ // deeper nesting
+ result =
+ bind(sum_of_args_1, // 12
+ bind(sum_of_args_4, // 12
+ bind(sum_of_args_2, // 3
+ bind(sum_of_args_1, // 1
+ bind(sum_of_args_1, _1) // 1
+ ),
+ _2),
+ _2,
+ _3,
+ 4)
+ )(i, j, k);
+ BOOST_CHECK(result == 12);
+
+ test_member_functions();
+
+
+ return 0;
+}
diff --git a/libs/lambda/test/bll_and_function.cpp b/libs/lambda/test/bll_and_function.cpp
new file mode 100644
index 000000000..03bcc3ec2
--- /dev/null
+++ b/libs/lambda/test/bll_and_function.cpp
@@ -0,0 +1,68 @@
+// bll_and_function.cpp - The Boost Lambda Library -----------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// test using BLL and boost::function
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+
+#include "boost/function.hpp"
+
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+
+using namespace boost::lambda;
+
+using namespace std;
+
+void test_function() {
+
+ boost::function<int (int, int)> f;
+ f = _1 + _2;
+
+ BOOST_CHECK(f(1, 2)== 3);
+
+ int i=1; int j=2;
+ boost::function<int& (int&, int)> g = _1 += _2;
+ g(i, j);
+ BOOST_CHECK(i==3);
+
+
+
+ int* sum = new int();
+ *sum = 0;
+ boost::function<int& (int)> counter = *sum += _1;
+ counter(5); // ok, sum* = 5;
+ BOOST_CHECK(*sum == 5);
+ delete sum;
+
+ // The next statement would lead to a dangling reference
+ // counter(3); // error, *sum does not exist anymore
+
+}
+
+
+int test_main(int, char *[]) {
+
+ test_function();
+
+ return 0;
+}
+
+
+
+
+
+
diff --git a/libs/lambda/test/cast_test.cpp b/libs/lambda/test/cast_test.cpp
new file mode 100644
index 000000000..eba4300ab
--- /dev/null
+++ b/libs/lambda/test/cast_test.cpp
@@ -0,0 +1,107 @@
+// cast_tests.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+
+#include "boost/lambda/lambda.hpp"
+
+#include "boost/lambda/casts.hpp"
+
+#include <string>
+
+using namespace boost::lambda;
+using namespace std;
+
+class base {
+ int x;
+public:
+ virtual std::string class_name() const { return "const base"; }
+ virtual std::string class_name() { return "base"; }
+ virtual ~base() {}
+};
+
+class derived : public base {
+ int y[100];
+public:
+ virtual std::string class_name() const { return "const derived"; }
+ virtual std::string class_name() { return "derived"; }
+};
+
+
+
+
+void do_test() {
+
+ derived *p_derived = new derived;
+ base *p_base = new base;
+
+ base *b = 0;
+ derived *d = 0;
+
+ (var(b) = ll_static_cast<base *>(p_derived))();
+ (var(d) = ll_static_cast<derived *>(b))();
+
+ BOOST_CHECK(b->class_name() == "derived");
+ BOOST_CHECK(d->class_name() == "derived");
+
+ (var(b) = ll_dynamic_cast<derived *>(b))();
+ BOOST_CHECK(b != 0);
+ BOOST_CHECK(b->class_name() == "derived");
+
+ (var(d) = ll_dynamic_cast<derived *>(p_base))();
+ BOOST_CHECK(d == 0);
+
+
+
+ const derived* p_const_derived = p_derived;
+
+ BOOST_CHECK(p_const_derived->class_name() == "const derived");
+ (var(d) = ll_const_cast<derived *>(p_const_derived))();
+ BOOST_CHECK(d->class_name() == "derived");
+
+ int i = 10;
+ char* cp = reinterpret_cast<char*>(&i);
+
+ int* ip;
+ (var(ip) = ll_reinterpret_cast<int *>(cp))();
+ BOOST_CHECK(*ip == 10);
+
+
+ // typeid
+
+ BOOST_CHECK(string(ll_typeid(d)().name()) == string(typeid(d).name()));
+
+
+ // sizeof
+
+ BOOST_CHECK(ll_sizeof(_1)(p_derived) == sizeof(p_derived));
+ BOOST_CHECK(ll_sizeof(_1)(*p_derived) == sizeof(*p_derived));
+ BOOST_CHECK(ll_sizeof(_1)(p_base) == sizeof(p_base));
+ BOOST_CHECK(ll_sizeof(_1)(*p_base) == sizeof(*p_base));
+
+ int an_array[100];
+ BOOST_CHECK(ll_sizeof(_1)(an_array) == 100 * sizeof(int));
+
+ delete p_derived;
+ delete p_base;
+
+
+}
+
+int test_main(int, char *[]) {
+
+ do_test();
+ return 0;
+}
diff --git a/libs/lambda/test/constructor_tests.cpp b/libs/lambda/test/constructor_tests.cpp
new file mode 100644
index 000000000..8cef0cb4e
--- /dev/null
+++ b/libs/lambda/test/constructor_tests.cpp
@@ -0,0 +1,265 @@
+// constructor_tests.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/bind.hpp"
+
+#include "boost/lambda/construct.hpp"
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#ifdef BOOST_MSVC
+#pragma warning(disable:4512)
+#endif
+
+using namespace boost::lambda;
+namespace bl = boost::lambda;
+
+template<class T>
+bool check_tuple(int n, const T& t)
+{
+ return (t.get_head() == n) && check_tuple(n+1, t.get_tail());
+}
+
+template <>
+bool check_tuple(int /*n*/, const null_type& ) { return true; }
+
+
+void constructor_all_lengths()
+{
+ bool ok;
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int> >(),
+ 1)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int> >(),
+ 1, 2)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int> >(),
+ 1, 2, 3)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int> >(),
+ 1, 2, 3, 4)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7, 8)()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ bind(constructor<tuple<int, int, int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7, 8, 9)()
+ );
+ BOOST_CHECK(ok);
+
+}
+
+void new_ptr_all_lengths()
+{
+ bool ok;
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int> >(),
+ 1))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int> >(),
+ 1, 2))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int> >(),
+ 1, 2, 3))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int> >(),
+ 1, 2, 3, 4))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7, 8))()
+ );
+ BOOST_CHECK(ok);
+
+ ok = check_tuple(
+ 1,
+ *(bind(new_ptr<tuple<int, int, int, int, int, int, int, int, int> >(),
+ 1, 2, 3, 4, 5, 6, 7, 8, 9))()
+ );
+ BOOST_CHECK(ok);
+
+}
+
+class is_destructor_called {
+ bool& b;
+public:
+ is_destructor_called(bool& bb) : b(bb) { b = false; }
+ ~is_destructor_called() { b = true; }
+};
+
+void test_destructor ()
+{
+ char space[sizeof(is_destructor_called)];
+ bool flag = false;
+
+ is_destructor_called* idc = new(space) is_destructor_called(flag);
+ BOOST_CHECK(flag == false);
+ bind(destructor(), _1)(idc);
+ BOOST_CHECK(flag == true);
+
+ idc = new(space) is_destructor_called(flag);
+ BOOST_CHECK(flag == false);
+ bind(destructor(), _1)(*idc);
+ BOOST_CHECK(flag == true);
+}
+
+
+class count_deletes {
+public:
+ static int count;
+ ~count_deletes() { ++count; }
+};
+
+int count_deletes::count = 0;
+
+void test_news_and_deletes ()
+{
+ int* i[10];
+ std::for_each(i, i+10, _1 = bind(new_ptr<int>(), 2));
+ int count_errors = 0;
+
+ std::for_each(i, i+10, (*_1 == 2) || ++var(count_errors));
+ BOOST_CHECK(count_errors == 0);
+
+
+ count_deletes* ct[10];
+ std::for_each(ct, ct+10, _1 = bind(new_ptr<count_deletes>()));
+ count_deletes::count = 0;
+ std::for_each(ct, ct+10, bind(delete_ptr(), _1));
+ BOOST_CHECK(count_deletes::count == 10);
+
+}
+
+void test_array_new_and_delete()
+{
+ count_deletes* c;
+ (_1 = bind(new_array<count_deletes>(), 5))(c);
+ count_deletes::count = 0;
+
+ bind(delete_array(), _1)(c);
+ BOOST_CHECK(count_deletes::count == 5);
+}
+
+
+void delayed_construction()
+{
+ std::vector<int> x(3);
+ std::vector<int> y(3);
+
+ std::fill(x.begin(), x.end(), 0);
+ std::fill(y.begin(), y.end(), 1);
+
+ std::vector<std::pair<int, int> > v;
+
+ std::transform(x.begin(), x.end(), y.begin(), std::back_inserter(v),
+ bl::bind(constructor<std::pair<int, int> >(), _1, _2) );
+}
+
+int test_main(int, char *[]) {
+
+ constructor_all_lengths();
+ new_ptr_all_lengths();
+ delayed_construction();
+ test_destructor();
+ test_news_and_deletes();
+ test_array_new_and_delete();
+
+ return 0;
+}
diff --git a/libs/lambda/test/control_structures.cpp b/libs/lambda/test/control_structures.cpp
new file mode 100644
index 000000000..12eabf8d3
--- /dev/null
+++ b/libs/lambda/test/control_structures.cpp
@@ -0,0 +1,123 @@
+// -- control_structures.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/if.hpp"
+#include "boost/lambda/loops.hpp"
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+using namespace boost;
+
+using boost::lambda::constant;
+using boost::lambda::_1;
+using boost::lambda::_2;
+using boost::lambda::_3;
+using boost::lambda::make_const;
+using boost::lambda::for_loop;
+using boost::lambda::while_loop;
+using boost::lambda::do_while_loop;
+using boost::lambda::if_then;
+using boost::lambda::if_then_else;
+using boost::lambda::if_then_else_return;
+
+// 2 container for_each
+template <class InputIter1, class InputIter2, class Function>
+Function for_each(InputIter1 first, InputIter1 last,
+ InputIter2 first2, Function f) {
+ for ( ; first != last; ++first, ++first2)
+ f(*first, *first2);
+ return f;
+}
+
+void simple_loops() {
+
+ // for loops ---------------------------------------------------------
+ int i;
+ int arithmetic_series = 0;
+ for_loop(_1 = 0, _1 < 10, _1++, arithmetic_series += _1)(i);
+ BOOST_CHECK(arithmetic_series == 45);
+
+ // no body case
+ for_loop(boost::lambda::var(i) = 0, boost::lambda::var(i) < 100, ++boost::lambda::var(i))();
+ BOOST_CHECK(i == 100);
+
+ // while loops -------------------------------------------------------
+ int a = 0, b = 0, c = 0;
+
+ while_loop((_1 + _2) >= (_1 * _2), (++_1, ++_2, ++_3))(a, b, c);
+ BOOST_CHECK(c == 3);
+
+ int count;
+ count = 0; i = 0;
+ while_loop(_1++ < 10, ++boost::lambda::var(count))(i);
+ BOOST_CHECK(count == 10);
+
+ // note that the first parameter of do_while_loop is the condition
+ count = 0; i = 0;
+ do_while_loop(_1++ < 10, ++boost::lambda::var(count))(i);
+ BOOST_CHECK(count == 11);
+
+ a = 0;
+ do_while_loop(constant(false), _1++)(a);
+ BOOST_CHECK(a == 1);
+
+ // no body cases
+ a = 40; b = 30;
+ while_loop(--_1 > _2)(a, b);
+ BOOST_CHECK(a == b);
+
+ // (the no body case for do_while_loop is pretty redundant)
+ a = 40; b = 30;
+ do_while_loop(--_1 > _2)(a, b);
+ BOOST_CHECK(a == b);
+
+
+}
+
+void simple_ifs () {
+
+ int value = 42;
+ if_then(_1 < 0, _1 = 0)(value);
+ BOOST_CHECK(value == 42);
+
+ value = -42;
+ if_then(_1 < 0, _1 = -_1)(value);
+ BOOST_CHECK(value == 42);
+
+ int min;
+ if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
+ (make_const(1), make_const(2));
+ BOOST_CHECK(min == 1);
+
+ if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
+ (make_const(5), make_const(3));
+ BOOST_CHECK(min == 3);
+
+ int x, y;
+ x = -1; y = 1;
+ BOOST_CHECK(if_then_else_return(_1 < _2, _2, _1)(x, y) == (std::max)(x ,y));
+ BOOST_CHECK(if_then_else_return(_1 < _2, _2, _1)(y, x) == (std::max)(x ,y));
+}
+
+
+int test_main(int, char *[])
+{
+ simple_loops();
+ simple_ifs();
+ return 0;
+}
diff --git a/libs/lambda/test/exception_test.cpp b/libs/lambda/test/exception_test.cpp
new file mode 100644
index 000000000..ee906668b
--- /dev/null
+++ b/libs/lambda/test/exception_test.cpp
@@ -0,0 +1,621 @@
+// -- exception_test.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+
+#include "boost/lambda/exceptions.hpp"
+
+#include "boost/lambda/bind.hpp"
+
+#include<iostream>
+#include<algorithm>
+#include <cstdlib>
+
+#include <iostream>
+
+using namespace boost::lambda;
+using namespace std;
+
+// to prevent unused variables warnings
+template <class T> void dummy(const T&) {}
+
+void erroneous_exception_related_lambda_expressions() {
+
+ int i = 0;
+ dummy(i);
+
+ // Uncommenting any of the below code lines should result in a compile
+ // time error
+
+ // this should fail (a rethrow binder outside of catch
+ // rethrow()();
+
+ // this should fail too for the same reason
+ // try_catch(rethrow(), catch_all(cout << constant("Howdy")))();
+
+ // this fails too (_e outside of catch_exception)
+ // (_1 + _2 + _e)(i, i, i);
+
+ // and this (_e outside of catch_exception)
+ // try_catch( throw_exception(1), catch_all(cout << _e));
+
+ // and this (_3 in catch_exception
+ // try_catch( throw_exception(1), catch_exception<int>(cout << _3));
+}
+
+
+class A1 {};
+class A2 {};
+class A3 {};
+class A4 {};
+class A5 {};
+class A6 {};
+class A7 {};
+class A8 {};
+class A9 {};
+
+void throw_AX(int j) {
+ int i = j;
+ switch(i) {
+ case 1: throw A1();
+ case 2: throw A2();
+ case 3: throw A3();
+ case 4: throw A4();
+ case 5: throw A5();
+ case 6: throw A6();
+ case 7: throw A7();
+ case 8: throw A8();
+ case 9: throw A9();
+ }
+}
+
+void test_different_number_of_catch_blocks() {
+
+ int ecount;
+
+// no catch(...) cases
+
+
+ ecount = 0;
+ for(int i=1; i<=1; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 1);
+
+ ecount = 0;
+ for(int i=1; i<=2; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 2);
+
+ ecount = 0;
+ for(int i=1; i<=3; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 3);
+
+ ecount = 0;
+ for(int i=1; i<=4; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 4);
+
+ ecount = 0;
+ for(int i=1; i<=5; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 5);
+
+ ecount = 0;
+ for(int i=1; i<=6; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 6);
+
+ ecount = 0;
+ for(int i=1; i<=7; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_exception<A7>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 7);
+
+ ecount = 0;
+ for(int i=1; i<=8; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_exception<A7>(
+ var(ecount)++
+ ),
+ catch_exception<A8>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 8);
+
+ ecount = 0;
+ for(int i=1; i<=9; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_exception<A7>(
+ var(ecount)++
+ ),
+ catch_exception<A8>(
+ var(ecount)++
+ ),
+ catch_exception<A9>(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 9);
+
+
+ // with catch(...) blocks
+
+ ecount = 0;
+ for(int i=1; i<=1; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 1);
+
+ ecount = 0;
+ for(int i=1; i<=2; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 2);
+
+ ecount = 0;
+ for(int i=1; i<=3; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 3);
+
+ ecount = 0;
+ for(int i=1; i<=4; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 4);
+
+ ecount = 0;
+ for(int i=1; i<=5; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 5);
+
+ ecount = 0;
+ for(int i=1; i<=6; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 6);
+
+ ecount = 0;
+ for(int i=1; i<=7; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 7);
+
+ ecount = 0;
+ for(int i=1; i<=8; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_exception<A7>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 8);
+
+ ecount = 0;
+ for(int i=1; i<=9; i++)
+ {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>(
+ var(ecount)++
+ ),
+ catch_exception<A2>(
+ var(ecount)++
+ ),
+ catch_exception<A3>(
+ var(ecount)++
+ ),
+ catch_exception<A4>(
+ var(ecount)++
+ ),
+ catch_exception<A5>(
+ var(ecount)++
+ ),
+ catch_exception<A6>(
+ var(ecount)++
+ ),
+ catch_exception<A7>(
+ var(ecount)++
+ ),
+ catch_exception<A8>(
+ var(ecount)++
+ ),
+ catch_all(
+ var(ecount)++
+ )
+ )(i);
+ }
+ BOOST_CHECK(ecount == 9);
+}
+
+void test_empty_catch_blocks() {
+ try_catch(
+ bind(throw_AX, _1),
+ catch_exception<A1>()
+ )(make_const(1));
+
+ try_catch(
+ bind(throw_AX, _1),
+ catch_all()
+ )(make_const(1));
+
+}
+
+
+void return_type_matching() {
+
+// Rules for return types of the lambda functors in try and catch parts:
+// 1. The try part dictates the return type of the whole
+// try_catch lambda functor
+// 2. If return type of try part is void, catch parts can return anything,
+// but the return types are ignored
+// 3. If the return type of the try part is A, then each catch return type
+// must be implicitly convertible to A, or then it must throw for sure
+
+
+ int i = 1;
+
+ BOOST_CHECK(
+
+ try_catch(
+ _1 + 1,
+ catch_exception<int>((&_1, rethrow())), // no match, but ok since throws
+ catch_exception<char>(_e) // ok, char convertible to int
+ )(i)
+
+ == 2
+ );
+
+ // note that while e.g. char is convertible to int, it is not convertible
+ // to int&, (some lambda functors return references)
+
+ // try_catch(
+ // _1 += 1,
+ // catch_exception<char>(_e) // NOT ok, char not convertible to int&
+ // )(i);
+
+ // if you don't care about the return type, you can use make_void
+ try_catch(
+ make_void(_1 += 1),
+ catch_exception<char>(_e) // since try is void, catch can return anything
+ )(i);
+ BOOST_CHECK(i == 2);
+
+ try_catch(
+ (_1 += 1, throw_exception('a')),
+ catch_exception<char>(_e) // since try throws, it is void,
+ // so catch can return anything
+ )(i);
+ BOOST_CHECK(i == 3);
+
+ char a = 'a';
+ try_catch(
+ try_catch(
+ throw_exception(1),
+ catch_exception<int>(throw_exception('b'))
+ ),
+ catch_exception<char>( _1 = _e )
+ )(a);
+ BOOST_CHECK(a == 'b');
+}
+
+int test_main(int, char *[]) {
+
+ try
+ {
+ test_different_number_of_catch_blocks();
+ return_type_matching();
+ test_empty_catch_blocks();
+ }
+ catch (int)
+ {
+ BOOST_CHECK(false);
+ }
+ catch(...)
+ {
+ BOOST_CHECK(false);
+ }
+
+
+ return EXIT_SUCCESS;
+}
+
+
+
+
diff --git a/libs/lambda/test/extending_rt_traits.cpp b/libs/lambda/test/extending_rt_traits.cpp
new file mode 100644
index 000000000..56916ab51
--- /dev/null
+++ b/libs/lambda/test/extending_rt_traits.cpp
@@ -0,0 +1,394 @@
+// extending_return_type_traits.cpp -- The Boost Lambda Library --------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/bind.hpp"
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/detail/suppress_unused.hpp"
+
+#include <iostream>
+
+#include <functional>
+
+#include <algorithm>
+
+using boost::lambda::detail::suppress_unused_variable_warnings;
+
+class A {};
+class B {};
+
+using namespace boost::lambda;
+
+
+B operator--(const A&, int) { return B(); }
+B operator--(A&) { return B(); }
+B operator++(const A&, int) { return B(); }
+B operator++(A&) { return B(); }
+B operator-(const A&) { return B(); }
+B operator+(const A&) { return B(); }
+
+B operator!(const A&) { return B(); }
+
+B operator&(const A&) { return B(); }
+B operator*(const A&) { return B(); }
+
+namespace boost {
+namespace lambda {
+
+ // unary + and -
+template<class Act>
+struct plain_return_type_1<unary_arithmetic_action<Act>, A > {
+ typedef B type;
+};
+
+ // post incr/decr
+template<class Act>
+struct plain_return_type_1<post_increment_decrement_action<Act>, A > {
+ typedef B type;
+};
+
+ // pre incr/decr
+template<class Act>
+struct plain_return_type_1<pre_increment_decrement_action<Act>, A > {
+ typedef B type;
+};
+ // !
+template<>
+struct plain_return_type_1<logical_action<not_action>, A> {
+ typedef B type;
+};
+ // &
+template<>
+struct plain_return_type_1<other_action<addressof_action>, A> {
+ typedef B type;
+};
+ // *
+template<>
+struct plain_return_type_1<other_action<contentsof_action>, A> {
+ typedef B type;
+};
+
+
+} // lambda
+} // boost
+
+void ok(B /*b*/) {}
+
+void test_unary_operators()
+{
+ A a; int i = 1;
+ ok((++_1)(a));
+ ok((--_1)(a));
+ ok((_1++)(a));
+ ok((_1--)(a));
+ ok((+_1)(a));
+ ok((-_1)(a));
+ ok((!_1)(a));
+ ok((&_1)(a));
+ ok((*_1)(a));
+
+ BOOST_CHECK((*_1)(make_const(&i)) == 1);
+}
+
+class X {};
+class Y {};
+class Z {};
+
+Z operator+(const X&, const Y&) { return Z(); }
+Z operator-(const X&, const Y&) { return Z(); }
+X operator*(const X&, const Y&) { return X(); }
+
+Z operator/(const X&, const Y&) { return Z(); }
+Z operator%(const X&, const Y&) { return Z(); }
+
+class XX {};
+class YY {};
+class ZZ {};
+class VV {};
+
+// it is possible to support differently cv-qualified versions
+YY operator*(XX&, YY&) { return YY(); }
+ZZ operator*(const XX&, const YY&) { return ZZ(); }
+XX operator*(volatile XX&, volatile YY&) { return XX(); }
+VV operator*(const volatile XX&, const volatile YY&) { return VV(); }
+
+// the traits can be more complex:
+template <class T>
+class my_vector {};
+
+template<class A, class B>
+my_vector<typename return_type_2<arithmetic_action<plus_action>, A&, B&>::type>
+operator+(const my_vector<A>& /*a*/, const my_vector<B>& /*b*/)
+{
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
+ return my_vector<res_type>();
+}
+
+
+
+// bitwise ops:
+X operator<<(const X&, const Y&) { return X(); }
+Z operator>>(const X&, const Y&) { return Z(); }
+Z operator&(const X&, const Y&) { return Z(); }
+Z operator|(const X&, const Y&) { return Z(); }
+Z operator^(const X&, const Y&) { return Z(); }
+
+// comparison ops:
+
+X operator<(const X&, const Y&) { return X(); }
+Z operator>(const X&, const Y&) { return Z(); }
+Z operator<=(const X&, const Y&) { return Z(); }
+Z operator>=(const X&, const Y&) { return Z(); }
+Z operator==(const X&, const Y&) { return Z(); }
+Z operator!=(const X&, const Y&) { return Z(); }
+
+// logical
+
+X operator&&(const X&, const Y&) { return X(); }
+Z operator||(const X&, const Y&) { return Z(); }
+
+// arithh assignment
+
+Z operator+=( X&, const Y&) { return Z(); }
+Z operator-=( X&, const Y&) { return Z(); }
+Y operator*=( X&, const Y&) { return Y(); }
+Z operator/=( X&, const Y&) { return Z(); }
+Z operator%=( X&, const Y&) { return Z(); }
+
+// bitwise assignment
+Z operator<<=( X&, const Y&) { return Z(); }
+Z operator>>=( X&, const Y&) { return Z(); }
+Y operator&=( X&, const Y&) { return Y(); }
+Z operator|=( X&, const Y&) { return Z(); }
+Z operator^=( X&, const Y&) { return Z(); }
+
+// assignment
+class Assign {
+public:
+ void operator=(const Assign& /*a*/) {}
+ X operator[](const int& /*i*/) { return X(); }
+};
+
+
+
+namespace boost {
+namespace lambda {
+
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
+ typedef X type;
+};
+
+ // if you want to make a distinction between differently cv-qualified
+ // types, you need to specialize on a different level:
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
+ typedef YY type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
+ typedef ZZ type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
+ typedef XX type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
+ typedef VV type;
+};
+
+ // the mapping can be more complex:
+template<class A, class B>
+struct plain_return_type_2<arithmetic_action<plus_action>, my_vector<A>, my_vector<B> > {
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
+ typedef my_vector<res_type> type;
+};
+
+ // bitwise binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<bitwise_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<bitwise_action<leftshift_action>, X, Y> {
+ typedef X type;
+};
+
+ // comparison binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<relational_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<relational_action<less_action>, X, Y> {
+ typedef X type;
+};
+
+ // logical binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<logical_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<logical_action<and_action>, X, Y> {
+ typedef X type;
+};
+
+ // arithmetic assignment :
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<arithmetic_assignment_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<arithmetic_assignment_action<multiply_action>, X, Y> {
+ typedef Y type;
+};
+
+ // arithmetic assignment :
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<bitwise_assignment_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<bitwise_assignment_action<and_action>, X, Y> {
+ typedef Y type;
+};
+
+ // assignment
+template<>
+struct plain_return_type_2<other_action<assignment_action>, Assign, Assign> {
+ typedef void type;
+};
+ // subscript
+template<>
+struct plain_return_type_2<other_action<subscript_action>, Assign, int> {
+ typedef X type;
+};
+
+
+} // end lambda
+} // end boost
+
+
+
+void test_binary_operators() {
+
+ X x; Y y;
+ (_1 + _2)(x, y);
+ (_1 - _2)(x, y);
+ (_1 * _2)(x, y);
+ (_1 / _2)(x, y);
+ (_1 % _2)(x, y);
+
+
+ // make a distinction between differently cv-qualified operators
+ XX xx; YY yy;
+ const XX& cxx = xx;
+ const YY& cyy = yy;
+ volatile XX& vxx = xx;
+ volatile YY& vyy = yy;
+ const volatile XX& cvxx = xx;
+ const volatile YY& cvyy = yy;
+
+ ZZ dummy1 = (_1 * _2)(cxx, cyy);
+ YY dummy2 = (_1 * _2)(xx, yy);
+ XX dummy3 = (_1 * _2)(vxx, vyy);
+ VV dummy4 = (_1 * _2)(cvxx, cvyy);
+
+ suppress_unused_variable_warnings(dummy1);
+ suppress_unused_variable_warnings(dummy2);
+ suppress_unused_variable_warnings(dummy3);
+ suppress_unused_variable_warnings(dummy4);
+
+ my_vector<int> v1; my_vector<double> v2;
+ my_vector<double> d = (_1 + _2)(v1, v2);
+
+ suppress_unused_variable_warnings(d);
+
+ // bitwise
+
+ (_1 << _2)(x, y);
+ (_1 >> _2)(x, y);
+ (_1 | _2)(x, y);
+ (_1 & _2)(x, y);
+ (_1 ^ _2)(x, y);
+
+ // comparison
+
+ (_1 < _2)(x, y);
+ (_1 > _2)(x, y);
+ (_1 <= _2)(x, y);
+ (_1 >= _2)(x, y);
+ (_1 == _2)(x, y);
+ (_1 != _2)(x, y);
+
+ // logical
+
+ (_1 || _2)(x, y);
+ (_1 && _2)(x, y);
+
+ // arithmetic assignment
+ (_1 += _2)(x, y);
+ (_1 -= _2)(x, y);
+ (_1 *= _2)(x, y);
+ (_1 /= _2)(x, y);
+ (_1 %= _2)(x, y);
+
+ // bitwise assignment
+ (_1 <<= _2)(x, y);
+ (_1 >>= _2)(x, y);
+ (_1 |= _2)(x, y);
+ (_1 &= _2)(x, y);
+ (_1 ^= _2)(x, y);
+
+}
+
+
+int test_main(int, char *[]) {
+ test_unary_operators();
+ test_binary_operators();
+ return 0;
+}
+
+
+
+
+
+
diff --git a/libs/lambda/test/is_instance_of_test.cpp b/libs/lambda/test/is_instance_of_test.cpp
new file mode 100644
index 000000000..d1c57b364
--- /dev/null
+++ b/libs/lambda/test/is_instance_of_test.cpp
@@ -0,0 +1,79 @@
+// is_instance_of_test.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+
+#include "boost/lambda/detail/is_instance_of.hpp"
+
+#include <iostream>
+
+template <class T1> struct A1 {};
+template <class T1, class T2> struct A2 {};
+template <class T1, class T2, class T3> struct A3 {};
+template <class T1, class T2, class T3, class T4> struct A4 {};
+
+class B1 : public A1<int> {};
+class B2 : public A2<int,int> {};
+class B3 : public A3<int,int,int> {};
+class B4 : public A4<int,int,int,int> {};
+
+// classes that are convertible to classes that derive from A instances
+// This is not enough to make the test succeed
+
+class C1 { public: operator A1<int>() { return A1<int>(); } };
+class C2 { public: operator B2() { return B2(); } };
+class C3 { public: operator B3() { return B3(); } };
+class C4 { public: operator B4() { return B4(); } };
+
+// test that the result is really a constant
+// (in an alternative implementation, gcc 3.0.2. claimed that it was
+// a non-constant)
+template <bool b> class X {};
+// this should compile
+X<boost::lambda::is_instance_of_2<int, A2>::value> x;
+
+
+int test_main(int, char *[]) {
+
+using boost::lambda::is_instance_of_1;
+using boost::lambda::is_instance_of_2;
+using boost::lambda::is_instance_of_3;
+using boost::lambda::is_instance_of_4;
+
+
+BOOST_CHECK((is_instance_of_1<B1, A1>::value == true));
+BOOST_CHECK((is_instance_of_1<A1<float>, A1>::value == true));
+BOOST_CHECK((is_instance_of_1<int, A1>::value == false));
+BOOST_CHECK((is_instance_of_1<C1, A1>::value == false));
+
+BOOST_CHECK((is_instance_of_2<B2, A2>::value == true));
+BOOST_CHECK((is_instance_of_2<A2<int, float>, A2>::value == true));
+BOOST_CHECK((is_instance_of_2<int, A2>::value == false));
+BOOST_CHECK((is_instance_of_2<C2, A2>::value == false));
+
+BOOST_CHECK((is_instance_of_3<B3, A3>::value == true));
+BOOST_CHECK((is_instance_of_3<A3<int, float, char>, A3>::value == true));
+BOOST_CHECK((is_instance_of_3<int, A3>::value == false));
+BOOST_CHECK((is_instance_of_3<C3, A3>::value == false));
+
+BOOST_CHECK((is_instance_of_4<B4, A4>::value == true));
+BOOST_CHECK((is_instance_of_4<A4<int, float, char, double>, A4>::value == true));
+BOOST_CHECK((is_instance_of_4<int, A4>::value == false));
+BOOST_CHECK((is_instance_of_4<C4, A4>::value == false));
+
+return 0;
+
+}
+
diff --git a/libs/lambda/test/istreambuf_test.cpp b/libs/lambda/test/istreambuf_test.cpp
new file mode 100644
index 000000000..6db0842cf
--- /dev/null
+++ b/libs/lambda/test/istreambuf_test.cpp
@@ -0,0 +1,30 @@
+// istreambuf_test - test lambda function objects with istreambuf_iterator
+//
+// Copyright (c) 2007 Peter Dimov
+//
+// 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
+
+#include <boost/lambda/lambda.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <iterator>
+#include <sstream>
+#include <algorithm>
+
+int main()
+{
+ using namespace boost::lambda;
+
+ std::stringstream is( "ax2" );
+
+ std::istreambuf_iterator<char> b2( is );
+ std::istreambuf_iterator<char> e2;
+
+ std::istreambuf_iterator<char> i = std::find_if( b2, e2, _1 == 'x' );
+
+ BOOST_TEST( *i == 'x' );
+ BOOST_TEST( std::distance( i, e2 ) == 2 );
+
+ return boost::report_errors();
+}
diff --git a/libs/lambda/test/member_pointer_test.cpp b/libs/lambda/test/member_pointer_test.cpp
new file mode 100644
index 000000000..e8121d564
--- /dev/null
+++ b/libs/lambda/test/member_pointer_test.cpp
@@ -0,0 +1,192 @@
+// member_pointer_test.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/bind.hpp"
+
+#include <string>
+
+using namespace boost::lambda;
+using namespace std;
+
+
+struct my_struct {
+my_struct(int x) : mem(x) {};
+
+ int mem;
+
+ int fooc() const { return mem; }
+ int foo() { return mem; }
+ int foo1c(int y) const { return y + mem; }
+ int foo1(int y) { return y + mem; }
+ int foo2c(int y, int x) const { return y + x + mem; }
+ int foo2(int y, int x) { return y + x + mem; }
+ int foo3c(int y, int x, int z) const { return y + x + z + mem; }
+ int foo3(int y, int x, int z ){ return y + x + z + mem; }
+ int foo4c(int a1, int a2, int a3, int a4) const { return a1+a2+a3+a4+mem; }
+ int foo4(int a1, int a2, int a3, int a4){ return a1+a2+a3+a4+mem; }
+
+ int foo3default(int y = 1, int x = 2, int z = 3) { return y + x + z + mem; }
+};
+
+my_struct x(3);
+
+void pointer_to_data_member_tests() {
+
+ // int i = 0;
+ my_struct *y = &x;
+
+ BOOST_CHECK((_1 ->* &my_struct::mem)(y) == 3);
+
+ (_1 ->* &my_struct::mem)(y) = 4;
+ BOOST_CHECK(x.mem == 4);
+
+ ((_1 ->* &my_struct::mem) = 5)(y);
+ BOOST_CHECK(x.mem == 5);
+
+ // &my_struct::mem is a temporary, must be constified
+ ((y ->* _1) = 6)(make_const(&my_struct::mem));
+ BOOST_CHECK(x.mem == 6);
+
+ ((_1 ->* _2) = 7)(y, make_const(&my_struct::mem));
+ BOOST_CHECK(x.mem == 7);
+
+}
+
+void pointer_to_member_function_tests() {
+
+ my_struct *y = new my_struct(1);
+ BOOST_CHECK( (_1 ->* &my_struct::foo)(y)() == (y->mem));
+ BOOST_CHECK( (_1 ->* &my_struct::fooc)(y)() == (y->mem));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo))() == (y->mem));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::fooc))() == (y->mem));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo))() == (y->mem));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::fooc))() == (y->mem));
+
+ BOOST_CHECK( (_1 ->* &my_struct::foo1)(y)(1) == (y->mem+1));
+ BOOST_CHECK( (_1 ->* &my_struct::foo1c)(y)(1) == (y->mem+1));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1))(1) == (y->mem+1));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1c))(1) == (y->mem+1));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1))(1) == (y->mem+1));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1c))(1) == (y->mem+1));
+
+ BOOST_CHECK( (_1 ->* &my_struct::foo2)(y)(1,2) == (y->mem+1+2));
+ BOOST_CHECK( (_1 ->* &my_struct::foo2c)(y)(1,2) == (y->mem+1+2));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
+
+ BOOST_CHECK( (_1 ->* &my_struct::foo3)(y)(1,2,3) == (y->mem+1+2+3));
+ BOOST_CHECK( (_1 ->* &my_struct::foo3c)(y)(1,2,3) == (y->mem+1+2+3));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
+
+ BOOST_CHECK( (_1 ->* &my_struct::foo4)(y)(1,2,3,4) == (y->mem+1+2+3+4));
+ BOOST_CHECK( (_1 ->* &my_struct::foo4c)(y)(1,2,3,4) == (y->mem+1+2+3+4));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
+ BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
+ BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
+
+
+
+ // member functions with default values do not work (inherent language issue)
+ // BOOST_CHECK( (_1 ->* &my_struct::foo3default)(y)() == (y->mem+1+2+3));
+
+}
+
+class A {};
+class B {};
+class C {};
+class D {};
+
+// ->* can be overloaded to do anything
+bool operator->*(A /*a*/, B /*b*/) {
+ return false;
+}
+
+bool operator->*(B /*b*/, A /*a*/) {
+ return true;
+}
+
+// let's provide specializations to take care of the return type deduction.
+// Note, that you need to provide all four cases for non-const and const
+// or use the plain_return_type_2 template.
+namespace boost {
+namespace lambda {
+
+template <>
+struct return_type_2<other_action<member_pointer_action>, B, A> {
+ typedef bool type;
+};
+
+template<>
+struct return_type_2<other_action<member_pointer_action>, const B, A> {
+ typedef bool type;
+};
+
+template<>
+struct return_type_2<other_action<member_pointer_action>, B, const A> {
+ typedef bool type;
+};
+
+template<>
+struct return_type_2<other_action<member_pointer_action>, const B, const A> {
+ typedef bool type;
+};
+
+
+
+
+} // lambda
+} // boost
+
+void test_overloaded_pointer_to_member()
+{
+ A a; B b;
+
+ // this won't work, can't deduce the return type
+ // BOOST_CHECK((_1->*_2)(a, b) == false);
+
+ // ret<bool> gives the return type
+ BOOST_CHECK(ret<bool>(_1->*_2)(a, b) == false);
+ BOOST_CHECK(ret<bool>(a->*_1)(b) == false);
+ BOOST_CHECK(ret<bool>(_1->*b)(a) == false);
+ BOOST_CHECK((ret<bool>((var(a))->*b))() == false);
+ BOOST_CHECK((ret<bool>((var(a))->*var(b)))() == false);
+
+
+ // this is ok without ret<bool> due to the return_type_2 spcialization above
+ BOOST_CHECK((_1->*_2)(b, a) == true);
+ BOOST_CHECK((b->*_1)(a) == true);
+ BOOST_CHECK((_1->*a)(b) == true);
+ BOOST_CHECK((var(b)->*a)() == true);
+ return;
+}
+
+
+int test_main(int, char *[]) {
+
+ pointer_to_data_member_tests();
+ pointer_to_member_function_tests();
+ test_overloaded_pointer_to_member();
+ return 0;
+}
+
diff --git a/libs/lambda/test/operator_tests_simple.cpp b/libs/lambda/test/operator_tests_simple.cpp
new file mode 100644
index 000000000..34711fbbc
--- /dev/null
+++ b/libs/lambda/test/operator_tests_simple.cpp
@@ -0,0 +1,431 @@
+// operator_tests_simple.cpp -- The Boost Lambda Library ---------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+
+#include "boost/lambda/detail/suppress_unused.hpp"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+#include <iostream>
+
+#ifndef BOOST_NO_STRINGSTREAM
+#include <sstream>
+#endif
+
+using namespace std;
+using namespace boost;
+
+using namespace boost::lambda;
+
+
+class unary_plus_tester {};
+unary_plus_tester operator+(const unary_plus_tester& a) { return a; }
+
+void cout_tests()
+{
+#ifndef BOOST_NO_STRINGSTREAM
+ using std::cout;
+ ostringstream os;
+ int i = 10;
+ (os << _1)(i);
+
+ (os << constant("FOO"))();
+
+ BOOST_CHECK(os.str() == std::string("10FOO"));
+
+
+ istringstream is("ABC 1");
+ std::string s;
+ int k;
+
+ is >> s;
+ is >> k;
+
+ BOOST_CHECK(s == std::string("ABC"));
+ BOOST_CHECK(k == 1);
+ // test for constant, constant_ref and var
+ i = 5;
+ constant_type<int>::type ci(constant(i));
+ var_type<int>::type vi(var(i));
+
+ (vi = _1)(make_const(100));
+ BOOST_CHECK((ci)() == 5);
+ BOOST_CHECK(i == 100);
+
+ int a;
+ constant_ref_type<int>::type cr(constant_ref(i));
+ (++vi, var(a) = cr)();
+ BOOST_CHECK(i == 101);
+#endif
+}
+
+void arithmetic_operators() {
+ int i = 1; int j = 2; int k = 3;
+
+ using namespace std;
+ using namespace boost::lambda;
+
+ BOOST_CHECK((_1 + 1)(i)==2);
+ BOOST_CHECK(((_1 + 1) * _2)(i, j)==4);
+ BOOST_CHECK((_1 - 1)(i)==0);
+
+ BOOST_CHECK((_1 * 2)(j)==4);
+ BOOST_CHECK((_1 / 2)(j)==1);
+
+ BOOST_CHECK((_1 % 2)(k)==1);
+
+ BOOST_CHECK((-_1)(i) == -1);
+ BOOST_CHECK((+_1)(i) == 1);
+
+ // test that unary plus really does something
+ unary_plus_tester u;
+ unary_plus_tester up = (+_1)(u);
+
+ boost::lambda::detail::suppress_unused_variable_warnings(up);
+}
+
+void bitwise_operators() {
+ unsigned int ui = 2;
+
+ BOOST_CHECK((_1 << 1)(ui)==(2 << 1));
+ BOOST_CHECK((_1 >> 1)(ui)==(2 >> 1));
+
+ BOOST_CHECK((_1 & 1)(ui)==(2 & 1));
+ BOOST_CHECK((_1 | 1)(ui)==(2 | 1));
+ BOOST_CHECK((_1 ^ 1)(ui)==(2 ^ 1));
+ BOOST_CHECK((~_1)(ui)==~2u);
+}
+
+void comparison_operators() {
+ int i = 0, j = 1;
+
+ BOOST_CHECK((_1 < _2)(i, j) == true);
+ BOOST_CHECK((_1 <= _2)(i, j) == true);
+ BOOST_CHECK((_1 == _2)(i, j) == false);
+ BOOST_CHECK((_1 != _2)(i, j) == true);
+ BOOST_CHECK((_1 > _2)(i, j) == false);
+ BOOST_CHECK((_1 >= _2)(i, j) == false);
+
+ BOOST_CHECK((!(_1 < _2))(i, j) == false);
+ BOOST_CHECK((!(_1 <= _2))(i, j) == false);
+ BOOST_CHECK((!(_1 == _2))(i, j) == true);
+ BOOST_CHECK((!(_1 != _2))(i, j) == false);
+ BOOST_CHECK((!(_1 > _2))(i, j) == true);
+ BOOST_CHECK((!(_1 >= _2))(i, j) == true);
+}
+
+void logical_operators() {
+
+ bool t = true, f = false;
+ BOOST_CHECK((_1 && _2)(t, t) == true);
+ BOOST_CHECK((_1 && _2)(t, f) == false);
+ BOOST_CHECK((_1 && _2)(f, t) == false);
+ BOOST_CHECK((_1 && _2)(f, f) == false);
+
+ BOOST_CHECK((_1 || _2)(t, t) == true);
+ BOOST_CHECK((_1 || _2)(t, f) == true);
+ BOOST_CHECK((_1 || _2)(f, t) == true);
+ BOOST_CHECK((_1 || _2)(f, f) == false);
+
+ BOOST_CHECK((!_1)(t) == false);
+ BOOST_CHECK((!_1)(f) == true);
+
+ // test short circuiting
+ int i=0;
+
+ (false && ++_1)(i);
+ BOOST_CHECK(i==0);
+ i = 0;
+
+ (true && ++_1)(i);
+ BOOST_CHECK(i==1);
+ i = 0;
+
+ (false || ++_1)(i);
+ BOOST_CHECK(i==1);
+ i = 0;
+
+ (true || ++_1)(i);
+ BOOST_CHECK(i==0);
+ i = 0;
+}
+
+void unary_incs_and_decs() {
+ int i = 0;
+
+ BOOST_CHECK(_1++(i) == 0);
+ BOOST_CHECK(i == 1);
+ i = 0;
+
+ BOOST_CHECK(_1--(i) == 0);
+ BOOST_CHECK(i == -1);
+ i = 0;
+
+ BOOST_CHECK((++_1)(i) == 1);
+ BOOST_CHECK(i == 1);
+ i = 0;
+
+ BOOST_CHECK((--_1)(i) == -1);
+ BOOST_CHECK(i == -1);
+ i = 0;
+
+ // the result of prefix -- and ++ are lvalues
+ (++_1)(i) = 10;
+ BOOST_CHECK(i==10);
+ i = 0;
+
+ (--_1)(i) = 10;
+ BOOST_CHECK(i==10);
+ i = 0;
+}
+
+void compound_operators() {
+
+ int i = 1;
+
+ // normal variable as the left operand
+ (i += _1)(make_const(1));
+ BOOST_CHECK(i == 2);
+
+ (i -= _1)(make_const(1));
+ BOOST_CHECK(i == 1);
+
+ (i *= _1)(make_const(10));
+ BOOST_CHECK(i == 10);
+
+ (i /= _1)(make_const(2));
+ BOOST_CHECK(i == 5);
+
+ (i %= _1)(make_const(2));
+ BOOST_CHECK(i == 1);
+
+ // lambda expression as a left operand
+ (_1 += 1)(i);
+ BOOST_CHECK(i == 2);
+
+ (_1 -= 1)(i);
+ BOOST_CHECK(i == 1);
+
+ (_1 *= 10)(i);
+ BOOST_CHECK(i == 10);
+
+ (_1 /= 2)(i);
+ BOOST_CHECK(i == 5);
+
+ (_1 %= 2)(i);
+ BOOST_CHECK(i == 1);
+
+ // lambda expression as a left operand with rvalue on RHS
+ (_1 += (0 + 1))(i);
+ BOOST_CHECK(i == 2);
+
+ (_1 -= (0 + 1))(i);
+ BOOST_CHECK(i == 1);
+
+ (_1 *= (0 + 10))(i);
+ BOOST_CHECK(i == 10);
+
+ (_1 /= (0 + 2))(i);
+ BOOST_CHECK(i == 5);
+
+ (_1 %= (0 + 2))(i);
+ BOOST_CHECK(i == 1);
+
+ // shifts
+ unsigned int ui = 2;
+ (_1 <<= 1)(ui);
+ BOOST_CHECK(ui==(2 << 1));
+
+ ui = 2;
+ (_1 >>= 1)(ui);
+ BOOST_CHECK(ui==(2 >> 1));
+
+ ui = 2;
+ (ui <<= _1)(make_const(1));
+ BOOST_CHECK(ui==(2 << 1));
+
+ ui = 2;
+ (ui >>= _1)(make_const(1));
+ BOOST_CHECK(ui==(2 >> 1));
+
+ // and, or, xor
+ ui = 2;
+ (_1 &= 1)(ui);
+ BOOST_CHECK(ui==(2 & 1));
+
+ ui = 2;
+ (_1 |= 1)(ui);
+ BOOST_CHECK(ui==(2 | 1));
+
+ ui = 2;
+ (_1 ^= 1)(ui);
+ BOOST_CHECK(ui==(2 ^ 1));
+
+ ui = 2;
+ (ui &= _1)(make_const(1));
+ BOOST_CHECK(ui==(2 & 1));
+
+ ui = 2;
+ (ui |= _1)(make_const(1));
+ BOOST_CHECK(ui==(2 | 1));
+
+ ui = 2;
+ (ui ^= _1)(make_const(1));
+ BOOST_CHECK(ui==(2 ^ 1));
+
+}
+
+void assignment_and_subscript() {
+
+ // assignment and subscript need to be defined as member functions.
+ // Hence, if you wish to use a normal variable as the left hand argument,
+ // you must wrap it with var to turn it into a lambda expression
+
+ using std::string;
+ string s;
+
+ (_1 = "one")(s);
+ BOOST_CHECK(s == string("one"));
+
+ (var(s) = "two")();
+ BOOST_CHECK(s == string("two"));
+
+ BOOST_CHECK((var(s)[_1])(make_const(2)) == 'o');
+ BOOST_CHECK((_1[2])(s) == 'o');
+ BOOST_CHECK((_1[_2])(s, make_const(2)) == 'o');
+
+ // subscript returns lvalue
+ (var(s)[_1])(make_const(1)) = 'o';
+ BOOST_CHECK(s == "too");
+
+ (_1[1])(s) = 'a';
+ BOOST_CHECK(s == "tao");
+
+ (_1[_2])(s, make_const(0)) = 'm';
+ BOOST_CHECK(s == "mao");
+
+ // TODO: tests for vector, set, map, multimap
+}
+
+class A {};
+
+void address_of_and_dereference() {
+
+ A a; int i = 42;
+
+ BOOST_CHECK((&_1)(a) == &a);
+ BOOST_CHECK((*&_1)(i) == 42);
+
+ std::vector<int> vi; vi.push_back(1);
+ std::vector<int>::iterator it = vi.begin();
+
+ (*_1 = 7)(it);
+ BOOST_CHECK(vi[0] == 7);
+ const std::vector<int>::iterator cit(it);
+ (*_1 = 8)(cit);
+ BOOST_CHECK(vi[0] == 8);
+
+ // TODO: Add tests for more complex iterator types
+
+ boost::shared_ptr<int> ptr(new int(0));
+ (*_1 = 7)(ptr);
+ BOOST_CHECK(*ptr == 7);
+ const boost::shared_ptr<int> cptr(ptr);
+ (*_1 = 8)(cptr);
+ BOOST_CHECK(*ptr == 8);
+}
+
+
+
+void comma() {
+
+ int i = 100;
+ BOOST_CHECK((_1 = 10, 2 * _1)(i) == 20);
+
+ // TODO: that the return type is the exact type of the right argument
+ // (that r/l valueness is preserved)
+
+}
+
+void pointer_arithmetic() {
+
+ int ia[4] = { 1, 2, 3, 4 };
+ int* ip = ia;
+ int* ia_last = &ia[3];
+
+ const int cia[4] = { 1, 2, 3, 4 };
+ const int* cip = cia;
+ const int* cia_last = &cia[3];
+
+
+ // non-const array
+ BOOST_CHECK((*(_1 + 1))(ia) == 2);
+
+ // non-const pointer
+ BOOST_CHECK((*(_1 + 1))(ip) == 2);
+
+ BOOST_CHECK((*(_1 - 1))(ia_last) == 3);
+
+ // const array
+ BOOST_CHECK((*(_1 + 1))(cia) == 2);
+ // const pointer
+ BOOST_CHECK((*(_1 + 1))(cip) == 2);
+ BOOST_CHECK((*(_1 - 1))(cia_last) == 3);
+
+ // pointer arithmetic should not make non-consts const
+ (*(_1 + 2))(ia) = 0;
+ (*(_1 + 3))(ip) = 0;
+
+ BOOST_CHECK(ia[2] == 0);
+ BOOST_CHECK(ia[3] == 0);
+
+ // pointer - pointer
+ BOOST_CHECK((_1 - _2)(ia_last, ia) == 3);
+ BOOST_CHECK((_1 - _2)(cia_last, cia) == 3);
+ BOOST_CHECK((ia_last - _1)(ia) == 3);
+ BOOST_CHECK((cia_last - _1)(cia) == 3);
+ BOOST_CHECK((cia_last - _1)(cip) == 3);
+
+}
+
+int test_main(int, char *[]) {
+
+ arithmetic_operators();
+ bitwise_operators();
+ comparison_operators();
+ logical_operators();
+ unary_incs_and_decs();
+ compound_operators();
+ assignment_and_subscript();
+ address_of_and_dereference();
+ comma();
+ pointer_arithmetic();
+ cout_tests();
+ return 0;
+}
+
+
+
+
+
+
diff --git a/libs/lambda/test/phoenix_control_structures.cpp b/libs/lambda/test/phoenix_control_structures.cpp
new file mode 100644
index 000000000..722a74f91
--- /dev/null
+++ b/libs/lambda/test/phoenix_control_structures.cpp
@@ -0,0 +1,148 @@
+// phoenix_style_control_structures.cpp -- The Boost Lambda Library ------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/if.hpp"
+#include "boost/lambda/loops.hpp"
+
+#include <iostream>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <cmath>
+#include <cassert>
+#include <functional>
+
+
+
+using namespace boost::lambda;
+using namespace std;
+
+
+
+// If-else, while, do-while, for statements
+
+
+int test_main(int, char *[]) {
+
+ vector<int> v;
+ v.clear();
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(3);
+ v.push_back(4);
+ v.push_back(5);
+ v.push_back(6);
+ v.push_back(7);
+ v.push_back(8);
+ v.push_back(9);
+ v.push_back(10);
+
+ int sum = 0;
+ //////////////////////////////////
+ for_each(v.begin(), v.end(),
+ if_(_1 > 3 && _1 <= 8)
+ [
+ sum += _1
+ ]
+ );
+
+ BOOST_CHECK(sum == 4+5+6+7+8);
+
+ int gt = 0, eq = 0, lt = 0;
+ //////////////////////////////////
+ for_each(v.begin(), v.end(),
+ if_(_1 > 5)
+ [
+ ++var(gt)
+ ]
+ .else_
+ [
+ if_(_1 == 5)
+ [
+ ++var(eq)
+ ]
+ .else_
+ [
+ ++var(lt)
+ ]
+ ]
+ );
+
+ BOOST_CHECK(lt==4);
+ BOOST_CHECK(eq==1);
+ BOOST_CHECK(gt==5);
+
+ vector<int> t = v;
+
+ int counta = 0;
+ int countb = 0;
+ //////////////////////////////////
+ for_each(v.begin(), v.end(),
+ (
+ while_(_1--)
+ [
+ ++var(counta)
+ ],
+ ++var(countb)
+ )
+ );
+
+ BOOST_CHECK(counta == 55);
+ BOOST_CHECK(countb == 10);
+
+
+ v = t;
+
+ counta = 0; countb = 0;
+ //////////////////////////////////
+ for_each(v.begin(), v.end(),
+ (
+ do_
+ [
+ ++var(counta)
+ ]
+ .while_(_1--),
+ ++var(countb)
+ )
+ );
+
+ BOOST_CHECK(counta == (2+11)*10/2);
+ BOOST_CHECK(countb == 10);
+
+
+ v = t;
+ counta = 0; countb = 0;
+ //////////////////////////////////
+ int iii;
+ for_each(v.begin(), v.end(),
+ (
+ for_(var(iii) = 0, var(iii) < _1, ++var(iii))
+ [
+ ++var(counta)
+ ],
+ ++var(countb)
+ )
+ );
+
+ BOOST_CHECK(counta == (1+10)*10/2);
+ BOOST_CHECK(countb == 10);
+
+ v = t;
+
+ return 0;
+}
+
diff --git a/libs/lambda/test/result_of_tests.cpp b/libs/lambda/test/result_of_tests.cpp
new file mode 100644
index 000000000..c8da3297e
--- /dev/null
+++ b/libs/lambda/test/result_of_tests.cpp
@@ -0,0 +1,314 @@
+// result_of_tests.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2010 Steven Watanabe
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+struct with_result_type {
+ typedef int result_type;
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+struct with_result_template_value {
+ template<class Sig>
+ struct result;
+ template<class This>
+ struct result<This()> {
+ typedef int type;
+ };
+ template<class This, class A1>
+ struct result<This(A1)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2>
+ struct result<This(A1, A2)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3>
+ struct result<This(A1, A2, A3)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4>
+ struct result<This(A1, A2, A3, A4)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5>
+ struct result<This(A1, A2, A3, A4, A5)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
+ struct result<This(A1, A2, A3, A4, A5, A6)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A9, int>));
+ typedef int type;
+ };
+
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+struct with_result_template_reference {
+ template<class Sig>
+ struct result;
+ template<class This>
+ struct result<This()> {
+ typedef int type;
+ };
+ template<class This, class A1>
+ struct result<This(A1)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2>
+ struct result<This(A1, A2)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3>
+ struct result<This(A1, A2, A3)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4>
+ struct result<This(A1, A2, A3, A4)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5>
+ struct result<This(A1, A2, A3, A4, A5)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
+ struct result<This(A1, A2, A3, A4, A5, A6)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A9, int&>));
+ typedef int type;
+ };
+
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+template<class F>
+typename boost::result_of<F()>::type apply0(F f) {
+ return f();
+}
+template<class A, class F>
+typename boost::result_of<F(A)>::type apply1(F f, A a) {
+ return f(a);
+}
+template<class A, class B, class F>
+typename boost::result_of<F(A, B)>::type apply2(F f, A a, B b) {
+ return f(a, b);
+}
+template<class A, class B, class C, class F>
+typename boost::result_of<F(A, B, C)>::type apply3(F f, A a, B b, C c) {
+ return f(a, b, c);
+}
+
+using namespace boost::lambda;
+
+int test_main(int, char *[]) {
+ BOOST_CHECK(boost::lambda::bind(with_result_type())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1)() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2)() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3)() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4)() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5)() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6)() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7)() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
+
+ // Nullary result_of fails
+ //BOOST_CHECK(boost::lambda::bind(with_result_template_value())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1)() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2)() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3)() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4)() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5)() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6)() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7)() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
+
+ int one = 1,
+ two = 2,
+ three = 3,
+ four = 4,
+ five = 5,
+ six = 6,
+ seven = 7,
+ eight = 8,
+ nine = 9;
+
+ // Nullary result_of fails
+ //BOOST_CHECK(boost::lambda::bind(with_result_template_reference())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one))() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two))() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three))() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four))() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five))() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six))() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven))() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight))() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight), var(nine))() == 9);
+
+ // Check using result_of with lambda functors
+ BOOST_CHECK(apply0(constant(0)) == 0);
+ BOOST_CHECK(apply1<int>(_1, one) == 1);
+ BOOST_CHECK(apply1<int&>(_1, one) == 1);
+ BOOST_CHECK(apply1<const int&>(_1, one) == 1);
+ BOOST_CHECK((apply2<int, int>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply2<int&, int&>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply2<const int&, const int&>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply3<int, int, int>(_1 + _2 + _3, one, two, three) == 6));
+ BOOST_CHECK((apply3<int&, int&, int&>(_1 + _2 + _3, one, two, three) == 6));
+ BOOST_CHECK((apply3<const int&, const int&, const int&>(_1 + _2 + _3, one, two, three) == 6));
+
+ return 0;
+}
diff --git a/libs/lambda/test/ret_test.cpp b/libs/lambda/test/ret_test.cpp
new file mode 100644
index 000000000..82c947f04
--- /dev/null
+++ b/libs/lambda/test/ret_test.cpp
@@ -0,0 +1,53 @@
+// ret_test.cpp - The Boost Lambda Library -----------------------
+//
+// Copyright (C) 2009 Steven Watanabe
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+#include <boost/test/minimal.hpp>
+
+#include <boost/lambda/lambda.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+template<class R, class F>
+void test_ret(R r, F f) {
+ typename F::result_type x = f();
+ BOOST_MPL_ASSERT((boost::is_same<R, typename F::result_type>));
+ BOOST_CHECK(x == r);
+}
+
+template<class R, class F, class T1>
+void test_ret(R r, F f, T1& t1) {
+ typename F::result_type x = f(t1);
+ BOOST_MPL_ASSERT((boost::is_same<R, typename F::result_type>));
+ BOOST_CHECK(x == r);
+}
+
+class add_result {
+public:
+ add_result(int i = 0) : value(i) {}
+ friend bool operator==(const add_result& lhs, const add_result& rhs) {
+ return(lhs.value == rhs.value);
+ }
+private:
+ int value;
+};
+
+class addable {};
+add_result operator+(addable, addable) {
+ return add_result(7);
+}
+
+int test_main(int, char*[]) {
+ addable test;
+ test_ret(add_result(7), boost::lambda::ret<add_result>(boost::lambda::_1 + test), test);
+ test_ret(8.0, boost::lambda::ret<double>(boost::lambda::constant(7) + 1));
+
+ return 0;
+}
diff --git a/libs/lambda/test/rvalue_test.cpp b/libs/lambda/test/rvalue_test.cpp
new file mode 100644
index 000000000..37351855d
--- /dev/null
+++ b/libs/lambda/test/rvalue_test.cpp
@@ -0,0 +1,57 @@
+// rvalue_test - test lambda function objects with rvalue arguments
+//
+// Copyright (c) 2007 Peter Dimov
+//
+// 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
+
+#include <boost/lambda/lambda.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::lambda;
+
+ int x = 0;
+ int const y = 1;
+ int const z = 2;
+
+ BOOST_TEST( _1( x ) == 0 );
+ BOOST_TEST( _1( y ) == 1 );
+ BOOST_TEST( _1( 2 ) == 2 );
+
+ BOOST_TEST( _2( x, x ) == 0 );
+ BOOST_TEST( _2( x, y ) == 1 );
+ BOOST_TEST( _2( x, 2 ) == 2 );
+
+ BOOST_TEST( _2( 4, x ) == 0 );
+ BOOST_TEST( _2( 4, y ) == 1 );
+ BOOST_TEST( _2( 4, 2 ) == 2 );
+
+ (_1 = _2)( x, y );
+ BOOST_TEST( x == y );
+
+ (_1 = _2)( x, 3 );
+ BOOST_TEST( x == 3 );
+
+ (_2 = _1)( z, x );
+ BOOST_TEST( x == z );
+
+ (_2 = _1)( 4, x );
+ BOOST_TEST( x == 4 );
+
+ BOOST_TEST( _3( x, x, x ) == x );
+ BOOST_TEST( _3( x, x, y ) == y );
+ BOOST_TEST( _3( x, x, 2 ) == 2 );
+
+ BOOST_TEST( _3( x, 5, x ) == x );
+ BOOST_TEST( _3( x, 5, y ) == y );
+ BOOST_TEST( _3( x, 5, 2 ) == 2 );
+
+ BOOST_TEST( _3( 9, 5, x ) == x );
+ BOOST_TEST( _3( 9, 5, y ) == y );
+ BOOST_TEST( _3( 9, 5, 2 ) == 2 );
+
+ return boost::report_errors();
+}
diff --git a/libs/lambda/test/switch_construct.cpp b/libs/lambda/test/switch_construct.cpp
new file mode 100644
index 000000000..a0599fe12
--- /dev/null
+++ b/libs/lambda/test/switch_construct.cpp
@@ -0,0 +1,392 @@
+// switch_test.cpp -- The Boost Lambda Library --------------------------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/if.hpp"
+#include "boost/lambda/switch.hpp"
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <string>
+
+
+
+// Check that elements 0 -- index are 1, and the rest are 0
+bool check(const std::vector<int>& v, int index) {
+ using namespace boost::lambda;
+ int counter = 0;
+ std::vector<int>::const_iterator
+ result = std::find_if(v.begin(), v.end(),
+ ! if_then_else_return(
+ var(counter)++ <= index,
+ _1 == 1,
+ _1 == 0)
+ );
+ return result == v.end();
+}
+
+
+
+void do_switch_no_defaults_tests() {
+
+ using namespace boost::lambda;
+
+ int i = 0;
+ std::vector<int> v,w;
+
+ // elements from 0 to 9
+ std::generate_n(std::back_inserter(v),
+ 10,
+ var(i)++);
+ std::fill_n(std::back_inserter(w), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 0));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 1));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 2));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 3));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 4));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 5));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ case_statement<6>(++var(w[6]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 6));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ case_statement<6>(++var(w[6])),
+ case_statement<7>(++var(w[7]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 7));
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ case_statement<6>(++var(w[6])),
+ case_statement<7>(++var(w[7])),
+ case_statement<8>(++var(w[8]))
+ )
+ );
+
+ BOOST_CHECK(check(w, 8));
+ std::fill_n(w.begin(), 10, 0);
+
+}
+
+
+void do_switch_yes_defaults_tests() {
+
+ using namespace boost::lambda;
+
+ int i = 0;
+ std::vector<int> v,w;
+
+ // elements from 0 to 9
+ std::generate_n(std::back_inserter(v),
+ 10,
+ var(i)++);
+ std::fill_n(std::back_inserter(w), 10, 0);
+
+ int default_count;
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, -1));
+ BOOST_CHECK(default_count == 10);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 0));
+ BOOST_CHECK(default_count == 9);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 1));
+ BOOST_CHECK(default_count == 8);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 2));
+ BOOST_CHECK(default_count == 7);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 3));
+ BOOST_CHECK(default_count == 6);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 4));
+ BOOST_CHECK(default_count == 5);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 5));
+ BOOST_CHECK(default_count == 4);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ case_statement<6>(++var(w[6])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 6));
+ BOOST_CHECK(default_count == 3);
+ std::fill_n(w.begin(), 10, 0);
+
+ // ---
+ default_count = 0;
+ std::for_each(v.begin(), v.end(),
+ switch_statement(
+ _1,
+ case_statement<0>(++var(w[0])),
+ case_statement<1>(++var(w[1])),
+ case_statement<2>(++var(w[2])),
+ case_statement<3>(++var(w[3])),
+ case_statement<4>(++var(w[4])),
+ case_statement<5>(++var(w[5])),
+ case_statement<6>(++var(w[6])),
+ case_statement<7>(++var(w[7])),
+ default_statement(++var(default_count))
+ )
+ );
+
+ BOOST_CHECK(check(w, 7));
+ BOOST_CHECK(default_count == 2);
+ std::fill_n(w.begin(), 10, 0);
+
+}
+
+void test_empty_cases() {
+
+ using namespace boost::lambda;
+
+ // ---
+ switch_statement(
+ _1,
+ default_statement()
+ )(make_const(1));
+
+ switch_statement(
+ _1,
+ case_statement<1>()
+ )(make_const(1));
+
+}
+
+int test_main(int, char* []) {
+
+ do_switch_no_defaults_tests();
+ do_switch_yes_defaults_tests();
+
+ test_empty_cases();
+
+ return EXIT_SUCCESS;
+
+}
+