2
0
mirror of https://github.com/boostorg/lambda.git synced 2026-01-21 04:52:25 +00:00

Compare commits

..

47 Commits

Author SHA1 Message Date
nobody
1e9cfcebf7 This commit was manufactured by cvs2svn to create branch 'SPIRIT_1_6'.
[SVN r23968]
2004-07-23 02:16:28 +00:00
Jaakko Järvi
5031c63f73 .
[SVN r23654]
2004-07-16 22:56:09 +00:00
Jaakko Järvi
a7ac9a8991 Back to minimal.hpp
[SVN r23653]
2004-07-16 22:05:56 +00:00
Jaakko Järvi
8a19479625 modernizing...
[SVN r23640]
2004-07-16 17:30:45 +00:00
Jaakko Järvi
4add858581 temporarily backing out from previous changes, problems with VC7.1
[SVN r23475]
2004-07-13 01:16:43 +00:00
Jaakko Järvi
14b8227ca6 adding overloads to cope with rvalue temporaries
[SVN r23401]
2004-07-07 20:31:02 +00:00
Jaakko Järvi
5ecd79ed2e .
[SVN r23397]
2004-07-07 20:02:29 +00:00
Jaakko Järvi
d718b75da3 Converting to boostbook
[SVN r23396]
2004-07-07 19:43:52 +00:00
Jaakko Järvi
f9689cc6a4 Converting to Boost Book
[SVN r23384]
2004-07-06 20:56:36 +00:00
Eric Niebler
a80b8a59a0 remove std_min and std_max, update minmax coding guidelines
[SVN r23162]
2004-06-23 04:49:48 +00:00
Jaakko Järvi
b99048eab3 Fix for gcc 3.4
[SVN r22673]
2004-04-20 18:05:05 +00:00
Jaakko Järvi
ec6cc563b1 patch for gcc3.4
[SVN r22575]
2004-04-01 00:00:55 +00:00
Jaakko Järvi
0196c57a0a A few typos
[SVN r22414]
2004-03-01 14:13:05 +00:00
Eric Niebler
282825b784 remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros
[SVN r22394]
2004-02-26 18:27:02 +00:00
Jaakko Järvi
b8d328c0fc Now BLL supports result_type too, Thanks Peter D.!
[SVN r22380]
2004-02-24 22:06:14 +00:00
Peter Dimov
c5704cd6e3 Enable ::result_type recognition
[SVN r22379]
2004-02-24 20:03:32 +00:00
Peter Dimov
6f607b3eef *_1 support for smart pointers
[SVN r22376]
2004-02-24 13:13:03 +00:00
Jaakko Järvi
8bb8820adb fixed a small typo in destructor example
[SVN r22304]
2004-02-17 15:53:35 +00:00
Jaakko Järvi
89fb84d751 supressed some gcc3.4 warnings, making it more explicit that a few
template functions return void


[SVN r21503]
2004-01-05 15:34:29 +00:00
Rene Rivera
be2b0df062 Fix tabs in file.
[SVN r21399]
2003-12-26 23:26:49 +00:00
Jaakko Järvi
666a3eca2d patch by Jim Apple to fix things here and there
[SVN r21213]
2003-12-10 19:15:05 +00:00
Jaakko Järvi
95d865285e new test for algorithms
[SVN r21212]
2003-12-10 19:12:06 +00:00
Jaakko Järvi
ec38046886 added a citation
[SVN r20326]
2003-10-09 19:30:59 +00:00
Jaakko Järvi
c713dc5e0c fixed a typo, thanks Dave A
[SVN r20295]
2003-10-07 20:55:29 +00:00
Jaakko Järvi
ff04032656 a typo fix
[SVN r18993]
2003-07-09 14:35:19 +00:00
Jaakko Järvi
6f63b3770f fixed a bad example
[SVN r18616]
2003-05-30 19:26:56 +00:00
Jaakko Järvi
22e7b9c779 fixed empty args to macros warnings
[SVN r18501]
2003-05-22 21:00:48 +00:00
Jaakko Järvi
68be6f6563 a fix for gcc 2.95.2
[SVN r18500]
2003-05-22 18:27:40 +00:00
Jaakko Järvi
02314ab550 typo
[SVN r17652]
2003-02-26 05:11:50 +00:00
Jaakko Järvi
9f032a7301 licences were missing, now added
[SVN r17236]
2003-02-05 15:47:51 +00:00
Jaakko Järvi
da56b773a0 licence fixes ...
[SVN r17235]
2003-02-05 15:41:29 +00:00
Jaakko Järvi
cd605ff48d licence fixe
[SVN r17234]
2003-02-05 15:40:23 +00:00
Jaakko Järvi
641babedf8 added a link
[SVN r17232]
2003-02-05 14:58:37 +00:00
Jaakko Järvi
f9a6b38845 remvoded tabs
[SVN r16828]
2003-01-09 14:15:09 +00:00
Jaakko Järvi
846a406b7a bugfix, added a missing sig template
[SVN r16094]
2002-11-04 16:25:33 +00:00
Jaakko Järvi
29794ee654 added more tests for different arities of member functions
[SVN r16093]
2002-11-04 16:24:38 +00:00
Jaakko Järvi
f74aae1241 bugfixes
[SVN r16025]
2002-10-30 21:10:03 +00:00
Jaakko Järvi
624a204462 a bug fixed
[SVN r15886]
2002-10-10 22:03:49 +00:00
Jaakko Järvi
b635d13d2c a typo fix
[SVN r15656]
2002-10-02 22:43:10 +00:00
Jaakko Järvi
403d82da66 changed a list to a vector (sort requires random access iterator) in one example
[SVN r15575]
2002-09-30 20:28:27 +00:00
Jaakko Järvi
0f29970c8b changing to the new boost::function style
[SVN r15510]
2002-09-25 16:56:06 +00:00
Jaakko Järvi
05b9bd64c4 converting to the new boost::function style
[SVN r15508]
2002-09-25 16:46:42 +00:00
Jaakko Järvi
e1b36955b7 changed <include> to <sysinclude>
[SVN r15306]
2002-09-13 16:46:08 +00:00
Paul Mensonides
c6030ac58d pp-lib update
[SVN r15214]
2002-09-08 22:03:22 +00:00
Beman Dawes
e6edfdf997 Initial commit
[SVN r14896]
2002-08-15 17:47:47 +00:00
Jaakko Järvi
aabd832db1 added a Jamfile to run tests locally
[SVN r14856]
2002-08-14 20:56:59 +00:00
Jaakko Järvi
2aec95e806 added a forgotten sig-template to 9-argument case
[SVN r14837]
2002-08-14 14:59:24 +00:00
49 changed files with 390 additions and 11590 deletions

View File

@@ -1,61 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>A. Rationale for some of the design decisions</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s09.html" title="9. Contributors"><link rel="next" href="bi01.html" title="Bibliography"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">A. Rationale for some of the design decisions</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s09.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="bi01.html">Next</a></td></tr></table><hr></div><div class="appendix"><h2 class="title" style="clear: both"><a name="id2808832"></a>A. Rationale for some of the design decisions</h2><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:why_weak_arity"></a>1.
Lambda functor arity
</h3></div></div><p>
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:
<pre class="programlisting">
bind(g, _3, _3, _3)(x, y, z);
bind(g, _1, _1, _1)(x, y, z);
</pre>
This first line discards arguments <tt>x</tt> and
<tt>y</tt>, and makes the call:
<pre class="programlisting">
g(z, z, z)
</pre>
whereas the second line discards arguments <tt>y</tt> and
<tt>z</tt>, and calls:
<pre class="programlisting">
g(x, x, x)
</pre>
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 <span class="emphasis"><i>strict arity</i></span> 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:
<pre class="programlisting">
(_3, bind(g, _1, _1, _1))(x, y, z);
</pre>
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
<tt>g(x, x, x)</tt>
even with the strict arity.
</p><p>
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
<tt>_1 + _2</tt> but mistakenly wrote <tt>_1 + 2</tt>,
with strict arity checking, the complier would spot the error.
However, if the erroneous expression was <tt>1 + _2</tt> 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.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s09.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="bi01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Contributors </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Bibliography</td></tr></table></div></body></html>

View File

@@ -1,57 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>2. Getting Started</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="next" href="ar01s03.html" title="3. Introduction"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. Getting Started</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s03.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:getting_started"></a>2. Getting Started</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2790109"></a>2.1. Installing the library</h3></div></div><p>
The library consists of include files only, hence there is no
installation procedure. The <tt>boost</tt> include directory
must be on the include path.
There are a number of include files that give different functionality:
<div class="itemizedlist"><ul type="disc"><li><p>
<tt>lambda/lambda.hpp</tt> defines lambda expressions for different C++
operators, see <a href="ar01s05.html#sect:operator_expressions" title="5.2. Operator expressions">Section 5.2</a>.
</p></li><li><p>
<tt>lambda/bind.hpp</tt> defines <tt>bind</tt> functions for up to 9 arguments, see <a href="ar01s05.html#sect:bind_expressions" title="5.3. Bind expressions">Section 5.3</a>.</p></li><li><p>
<tt>lambda/if.hpp</tt> defines lambda function equivalents for if statements and the conditional operator, see <a href="ar01s05.html#sect:lambda_expressions_for_control_structures" title="5.6. Lambda expressions for control structures">Section 5.6</a> (includes <tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/loops.hpp</tt> defines lambda function equivalent for looping constructs, see <a href="ar01s05.html#sect:lambda_expressions_for_control_structures" title="5.6. Lambda expressions for control structures">Section 5.6</a>.
</p></li><li><p>
<tt>lambda/switch.hpp</tt> defines lambda function equivalent for the switch statement, see <a href="ar01s05.html#sect:lambda_expressions_for_control_structures" title="5.6. Lambda expressions for control structures">Section 5.6</a>.
</p></li><li><p>
<tt>lambda/construct.hpp</tt> provides tools for writing lambda expressions with constructor, destructor, new and delete invocations, see <a href="ar01s05.html#sect:construction_and_destruction" title="5.8. Construction and destruction">Section 5.8</a> (includes <tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/casts.hpp</tt> provides lambda versions of different casts, as well as <tt>sizeof</tt> and <tt>typeid</tt>, see <a href="ar01s05.html#sect:cast_expressions" title="5.10.1.
Cast expressions
">Section 5.10.1</a>.
</p></li><li><p>
<tt>lambda/exceptions.hpp</tt> gives tools for throwing and catching
exceptions within lambda functions, <a href="ar01s05.html#sect:exceptions" title="5.7. Exceptions">Section 5.7</a> (includes
<tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/algorithm.hpp</tt> and <tt>lambda/numeric.hpp</tt> (cf. standard <tt>algortihm</tt> and <tt>numeric</tt> headers) allow nested STL algorithm invocations, see <a href="ar01s05.html#sect:nested_stl_algorithms" title="5.11. Nesting STL algorithm invocations">Section 5.11</a>.
</p></li></ul></div>
Any other header files in the package are for internal use.
Additionally, the library depends on two other Boost Libraries, the
<span class="emphasis"><i>Tuple</i></span> [<a href="bi01.html#cit:boost::tuple" title="[tuple]">tuple</a>] and the <span class="emphasis"><i>type_traits</i></span> [<a href="bi01.html#cit:boost::type_traits" title="[type_traits]">type_traits</a>] libraries, and on the <tt>boost/ref.hpp</tt> header.
</p><p>
All definitions are placed in the namespace <tt>boost::lambda</tt> and its subnamespaces.
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2741935"></a>2.2. Conventions used in this document</h3></div></div><p>In most code examples, we omit the namespace prefixes for names in the <tt>std</tt> and <tt>boost::lambda</tt> namespaces.
Implicit using declarations
<pre class="programlisting">
using namespace std;
using namespace boost::lambda;
</pre>
are assumed to be in effect.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s03.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">
C++ BOOST
The Boost Lambda Library </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Introduction</td></tr></table></div></body></html>

View File

@@ -1,175 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>3. Introduction</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s02.html" title="2. Getting Started"><link rel="next" href="ar01s04.html" title="4. Using the library"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s02.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s04.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2741982"></a>3. Introduction</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2741989"></a>3.1. Motivation</h3></div></div><p>The Standard Template Library (STL)
[<a href="bi01.html#cit:stepanov:94" title="[STL94]">STL94</a>], now part of the C++ Standard Library [<a href="bi01.html#cit:c++:98" title="[C++98]">C++98</a>], is a generic container and algorithm library.
Typically STL algorithms operate on container elements via <span class="emphasis"><i>function objects</i></span>. These function objects are passed as arguments to the algorithms.
</p><p>
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 <tt>plus</tt>, <tt>less</tt> and <tt>not1</tt>).
As an example, one possible implementation for the standard <tt>plus</tt> template is:
<pre class="programlisting">
template &lt;class T&gt; : public binary_function&lt;T, T, T&gt;
struct plus {
T operator()(const T&amp; i, const T&amp; j) const {
return i + j;
}
};
</pre>
The base class <tt>binary_function&lt;T, T, T&gt;</tt> contains typedefs for the argument and return types of the function object, which are needed to make the function object <span class="emphasis"><i>adaptable</i></span>.
</p><p>
In addition to the basic function object classes, such as the one above,
the STL contains <span class="emphasis"><i>binder</i></span> 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:
<pre class="programlisting">
class plus_1 {
int _i;
public:
plus_1(const int&amp; i) : _i(i) {}
int operator()(const int&amp; j) { return _i + j; }
};
</pre>
the equivalent functionality can be achieved with the <tt>plus</tt> template and one of the binder templates (<tt>bind1st</tt>).
E.g., the following two expressions create function objects with identical functionalities;
when invoked, both return the result of adding <tt>1</tt> to the argument of the function object:
<pre class="programlisting">
plus_1(1)
bind1st(plus&lt;int&gt;(), 1)
</pre>
The subexpression <tt>plus&lt;int&gt;()</tt> in the latter line is a binary function object which computes the sum of two integers, and <tt>bind1st</tt> invokes this function object partially binding the first argument to <tt>1</tt>.
As an example of using the above function object, the following code adds <tt>1</tt> to each element of some container <tt>a</tt> and outputs the results into the standard output stream <tt>cout</tt>.
<pre class="programlisting">
transform(a.begin(), a.end(), ostream_iterator&lt;int&gt;(cout),
bind1st(plus&lt;int&gt;(), 1));
</pre>
</p><p>
To make the binder templates more generally applicable, the STL contains <span class="emphasis"><i>adaptors</i></span> 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 [<a href="bi01.html#cit:sgi:02" title="[SGI02]">SGI02</a>].
</p><p>
All these tools aim at one goal: to make it possible to specify
<span class="emphasis"><i>unnamed functions</i></span> 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.
</p><p>
The Boost Lambda Library provides solutions for the problems described above:
<div class="itemizedlist"><ul type="disc"><li><p>
Unnamed functions can be created easily with an intuitive syntax.
The above example can be written as:
<pre class="programlisting">
transform(a.begin(), a.end(), ostream_iterator&lt;int&gt;(cout),
1 + _1);
</pre>
or even more intuitively:
<pre class="programlisting">
for_each(a.begin(), a.end(), cout &lt;&lt; (1 + _1));
</pre>
</p></li><li><p>
Most of the restrictions in argument binding are removed,
arbitrary arguments of practically any C++ function can be bound.
</p></li><li><p>
Separate function composition operations are not needed,
as function composition is supported implicitly.
</p></li></ul></div>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2742784"></a>3.2. Introduction to lambda expressions</h3></div></div><p>
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:
<pre class="programlisting">
lambda x<sub>1</sub> ... x<sub>n</sub>.e
</pre>
A lambda expression defines an unnamed function and consists of:
<div class="itemizedlist"><ul type="disc"><li><p>
the parameters of this function: <tt>x<sub>1</sub> ... x<sub>n</sub></tt>.
</p></li><li><p>the expression e which computes the value of the function in terms of the parameters <tt>x<sub>1</sub> ... x<sub>n</sub></tt>.
</p></li></ul></div>
A simple example of a lambda expression is
<pre class="programlisting">
lambda x y.x+y
</pre>
Applying the lambda function means substituting the formal parameters with the actual arguments:
<pre class="programlisting">
(lambda x y.x+y) 2 3 = 2 + 3 = 5
</pre>
</p><p>
In the C++ version of lambda expressions the <tt>lambda x<sub>1</sub> ... x<sub>n</sub></tt> 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 <span class="emphasis"><i>placeholders</i></span>:
<tt>_1</tt>, <tt>_2</tt> and <tt>_3</tt>.
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
<pre class="programlisting">lambda x y.x+y</pre>
is
<pre class="programlisting">_1 + _2</pre>
</p><p>
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 <tt>bind</tt> function.
As an example, consider the lambda expression:
<pre class="programlisting">lambda x y.foo(x,y)</pre>
Rather than <tt>foo(_1, _2)</tt>, the C++ counterpart for this expression is:
<pre class="programlisting">bind(foo, _1, _2)</pre>
We refer to this type of C++ lambda expressions as <span class="emphasis"><i>bind expressions</i></span>.
</p><p>A lambda expression defines a C++ function object, hence function application syntax is like calling any other function object, for instance: <tt>(_1 + _2)(i, j)</tt>.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:partial_function_application"></a>3.2.1. Partial function application</h4></div></div><p>
A bind expression is in effect a <span class="emphasis"><i>partial function application</i></span>.
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.
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:terminology"></a>3.2.2. Terminology</h4></div></div><p>
A lambda expression defines a function. A C++ lambda expression concretely constructs a function object, <span class="emphasis"><i>a functor</i></span>, when evaluated. We use the name <span class="emphasis"><i>lambda functor</i></span> to refer to such a function object.
Hence, in the terminology adopted here, the result of evaluating a lambda expression is a lambda functor.
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Getting Started </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Using the library</td></tr></table></div></body></html>

View File

@@ -1,213 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>4. Using the library</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s03.html" title="3. Introduction"><link rel="next" href="ar01s05.html" title="5. Lambda expressions in details"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Using the library</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:using_library"></a>4. Using the library</h2></div></div><p>
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.
</p><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:introductory_examples"></a>4.1. Introductory Examples</h3></div></div><p>
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 <tt>list</tt>, to the value <tt>1</tt>:
<pre class="programlisting">
list&lt;int&gt; v(10);
for_each(v.begin(), v.end(), _1 = 1);</pre>
The expression <tt>_1 = 1</tt> creates a lambda functor which assigns the value <tt>1</tt> to every element in <tt>v</tt>.<sup>[<a name="id2739587" href="#ftn.id2739587">1</a>]</sup>
</p><p>
Next, we create a container of pointers and make them point to the elements in the first container <tt>v</tt>:
<pre class="programlisting">
list&lt;int*&gt; vp(10);
transform(v.begin(), v.end(), vp.begin(), &amp;_1);</pre>
The expression <tt>&amp;_1</tt> creates a function object for getting the address of each element in <tt>v</tt>.
The addresses get assigned to the corresponding elements in <tt>vp</tt>.
</p><p>
The next code fragment changes the values in <tt>v</tt>.
For each element, the function <tt>foo</tt> is called.
The original value of the element is passed as an argument to <tt>foo</tt>.
The result of <tt>foo</tt> is assigned back to the element:
<pre class="programlisting">
int foo(int);
for_each(v.begin(), v.end(), _1 = bind(foo, _1));</pre>
</p><p>
The next step is to sort the elements of <tt>vp</tt>:
<pre class="programlisting">sort(vp.begin(), vp.end(), *_1 &gt; *_2);</pre>
In this call to <tt>sort</tt>, we are sorting the elements by their contents in descending order.
</p><p>
Finally, the following <tt>for_each</tt> call outputs the sorted content of <tt>vp</tt> separated by line breaks:
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; *_1 &lt;&lt; '\n');
</pre>
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
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; '\n' &lt;&lt; *_1);
</pre>
the subexpression <tt>cout &lt;&lt; '\n'</tt> is evaluated immediately and the effect is to output a single line break, followed by the elements of <tt>vp</tt>.
The BLL provides functions <tt>constant</tt> and <tt>var</tt> to turn constants and, respectively, variables into lambda expressions, and can be used to prevent the immediate evaluation of subexpressions:
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; constant('\n') &lt;&lt; *_1);
</pre>
These functions are described more thoroughly in <a href="ar01s05.html#sect:delaying_constants_and_variables" title="5.5. Delaying constants and variables">Section 5.5</a>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:parameter_and_return_types"></a>4.2. Parameter and return types of lambda functors</h3></div></div><p>
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
<tt>_1 + _2</tt> creates a binary lambda functor.
It can be called with two objects of any types <tt>A</tt> and <tt>B</tt> for which <tt>operator+(A,B)</tt> is defined (and for which BLL knows the return type of the operator, see below).
</p><p>
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.
</p><p>
There are, however, cases when the return type cannot be deduced. For example, suppose you have defined:
<pre class="programlisting">C operator+(A, B);</pre>
The following lambda function invocation fails, since the return type cannot be deduced:
<pre class="programlisting">A a; B b; (_1 + _2)(a, b);</pre>
</p><p>
There are two alternative solutions to this.
The first is to extend the BLL type deduction system to cover your own types (see <a href="ar01s06.html#sect:extending_return_type_system" title="6. Extending return type deduction system">Section 6</a>).
The second is to use a special lambda expression (<tt>ret</tt>) which defines the return type in place (see <a href="ar01s05.html#sect:overriding_deduced_return_type" title="5.4. Overriding the deduced return type">Section 5.4</a>):
<pre class="programlisting">A a; B b; ret&lt;C&gt;(_1 + _2)(a, b);</pre>
</p><p>
For bind expressions, the return type can be defined as a template argument of the bind function as well:
<pre class="programlisting">bind&lt;int&gt;(foo, _1, _2);</pre>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:actual_arguments_to_lambda_functors"></a>4.3. About actual arguments to lambda functors</h3></div></div><p>A general restriction for the actual arguments is that they cannot be non-const rvalues.
For example:
<pre class="programlisting">
int i = 1; int j = 2;
(_1 + _2)(i, j); // ok
(_1 + _2)(1, 2); // error (!)
</pre>
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
<a href="ar01s05.html#sect:rvalues_as_actual_arguments" title="5.9.2. Rvalues as actual arguments to lambda functors">Section 5.9.2</a>.
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:storing_bound_arguments"></a>4.4. Storing bound arguments in lambda functions</h3></div></div><p>
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:
<pre class="programlisting">
int i = 1;
(_1 + i)(i = 2);
</pre>
The value of the expression in the last line is 3, not 4.
In other words, the lambda expression <tt>_1 + i</tt> creates
a lambda function <tt>lambda x.x+1</tt> rather than
<tt>lambda x.x+i</tt>.
</p><p>
As said, this is the default behavior for which there are exceptions.
The exact rules are as follows:
<div class="itemizedlist"><ul type="disc"><li><p>
The programmer can control the storing mechanism with <tt>ref</tt>
and <tt>cref</tt> wrappers [<a href="bi01.html#cit:boost::ref" title="[ref]">ref</a>].
Wrapping an argument with <tt>ref</tt>, or <tt>cref</tt>,
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
<tt>i</tt> with <tt>ref</tt>,
we are creating the lambda expression <tt>lambda x.x+i</tt>
and the value of the expression in the last line will be 4:
<pre class="programlisting">
i = 1;
(_1 + ref(i))(i = 2);
</pre>
Note that <tt>ref</tt> and <tt>cref</tt> are different
from <tt>var</tt> and <tt>constant</tt>.
While the latter ones create lambda functors, the former do not.
For example:
<pre class="programlisting">
int i;
var(i) = 1; // ok
ref(i) = 1; // not ok, ref(i) is not a lambda functor
</pre>
The functions <tt>ref</tt> and <tt>cref</tt> mostly
exist for historical reasons,
and <tt>ref</tt> can always
be replaced with <tt>var</tt>, and <tt>cref</tt> with
<tt>constant_ref</tt>.
See <a href="ar01s05.html#sect:delaying_constants_and_variables" title="5.5. Delaying constants and variables">Section 5.5</a> for details.
The <tt>ref</tt> and <tt>cref</tt> functions are
general purpose utility functions in Boost, and hence defined directly
in the <tt>boost</tt> namespace.
</p></li><li><p>
Array types cannot be copied, they are thus stored as const reference by default.
</p></li><li><p>
For some expressions it makes more sense to store the arguments as references.
For example, the obvious intention of the lambda expression
<tt>i += _1</tt> is that calls to the lambda functor affect the
value of the variable <tt>i</tt>,
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:
<div class="itemizedlist"><ul type="round"><li><p>The left argument of compound assignment operators (<tt>+=</tt>, <tt>*=</tt>, etc.) are stored as references to non-const.</p></li><li><p>If the left argument of <tt>&lt;&lt;</tt> or <tt>&gt;&gt;</tt> operator is derived from an instantiation of <tt>basic_ostream</tt> or respectively from <tt>basic_istream</tt>, the argument is stored as a reference to non-const.
For all other types, the argument is stored as a copy.
</p></li><li><p>
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.
</p></li></ul></div>
</p></li></ul></div>
</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id2739587" href="#id2739587">1</a>] </sup>
Strictly taken, the C++ standard defines <tt>for_each</tt> as a <span class="emphasis"><i>non-modifying sequence operation</i></span>, and the function object passed to <tt>for_each</tt> should not modify its argument.
The requirements for the arguments of <tt>for_each</tt> are unnecessary strict, since as long as the iterators are <span class="emphasis"><i>mutable</i></span>, <tt>for_each</tt> 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<tt>std::for_each</tt> but more fine-grained requirements for its arguments.
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Introduction </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Lambda expressions in details</td></tr></table></div></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,207 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>6. Extending return type deduction system</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s05.html" title="5. Lambda expressions in details"><link rel="next" href="ar01s07.html" title="7. Practical considerations"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Extending return type deduction system</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s05.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s07.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:extending_return_type_system"></a>6. Extending return type deduction system</h2></div></div><p>
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
<tt>bool</tt>, 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.
</p><p>
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
<tt>
plain_return_type_1&lt;Action, A&gt;
</tt>
and
<tt>
return_type_1&lt;Action, A&gt;
</tt>, and
<tt>
plain_return_type_2&lt;Action, A, B&gt;
</tt>
and
<tt>
return_type_2&lt;Action, A, B&gt;
</tt>
respectively for binary functors.
</p><p>
The first parameter (<tt>Action</tt>) to all these templates
is the <span class="emphasis"><i>action</i></span> class, which specifies the operator.
Operators with similar return type rules are grouped together into
<span class="emphasis"><i>action groups</i></span>,
and only the action class and action group together define the operator
unambiguously.
As an example, the action type
<tt>arithmetic_action&lt;plus_action&gt;</tt> stands for
<tt>operator+</tt>.
The complete listing of different action types is shown in
<a href="ar01s06.html#table:actions" title="Table 2. Action types">Table 2</a>.
</p><p>
The latter parameters, <tt>A</tt> in the unary case,
or <tt>A</tt> and <tt>B</tt> in the binary case,
stand for the argument types of the operator call.
The two sets of templates,
<tt>plain_return_type_<i><tt>n</tt></i></tt> and
<tt>return_type_<i><tt>n</tt></i></tt>
(<i><tt>n</tt></i> 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 <tt>return_type_2</tt> specializations.
</p><p>
Suppose the user has overloaded the following operators for some user defined
types <tt>X</tt>, <tt>Y</tt> and <tt>Z</tt>:
<pre class="programlisting">
Z operator+(const X&amp;, const Y&amp;);
Z operator-(const X&amp;, const Y&amp;);
</pre>
Now, one can add a specialization stating, that if the left hand argument
is of type <tt>X</tt>, and the right hand one of type
<tt>Y</tt>, the return type of all such binary arithmetic
operators is <tt>Z</tt>:
<pre class="programlisting">
namespace boost {
namespace lambda {
template&lt;class Act&gt;
struct plain_return_type_2&lt;arithmetic_action&lt;Act&gt;, X, Y&gt; {
typedef Z type;
};
}
}
</pre>
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,
<tt>::boost::lambda</tt>, with the primary template.
For brevity, we do not show the namespace definitions in the examples below.
</p><p>
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 <tt>X</tt>
and <tt>Y</tt>:
<pre class="programlisting">
X operator*(const X&amp;, const Y&amp;);
</pre>
Our first rule for all arithmetic operators specifies that the return
type of this operator is <tt>Z</tt>,
which obviously is not the case.
Hence, we provide a new rule for the multiplication operator:
<pre class="programlisting">
template&lt;&gt;
struct plain_return_type_2&lt;arithmetic_action&lt;multiply_action&gt;, X, Y&gt; {
typedef X type;
};
</pre>
</p><p>
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:
<pre class="programlisting">
template &lt;class T&gt; class my_vector;
</pre>
Suppose the addition operator is defined between any two
<tt>my_vector</tt> instantiations,
as long as the addition operator is defined between their element types.
Furthermore, the element type of the resulting <tt>my_vector</tt>
is the same as the result type of the addition between the element types.
E.g., adding <tt>my_vector&lt;int&gt;</tt> and
<tt>my_vector&lt;double&gt;</tt> results in
<tt>my_vector&lt;double&gt;</tt>.
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:
<pre class="programlisting">
template&lt;class A, class B&gt;
my_vector&lt;typename return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A, B&gt;::type&gt;
operator+(const my_vector&lt;A&gt;&amp; a, const my_vector&lt;B&gt;&amp; b)
{
typedef typename
return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A, B&gt;::type res_type;
return my_vector&lt;res_type&gt;();
}
</pre>
</p><p>
To allow BLL to deduce the type of <tt>my_vector</tt>
additions correctly, we can define:
<pre class="programlisting">
template&lt;class A, class B&gt;
class plain_return_type_2&lt;arithmetic_action&lt;plus_action&gt;,
my_vector&lt;A&gt;, my_vector&lt;B&gt; &gt; {
typedef typename
return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A, B&gt;::type res_type;
public:
typedef my_vector&lt;res_type&gt; type;
};
</pre>
Note, that we are reusing the existing specializations for the
BLL <tt>return_type_2</tt> template,
which require that the argument types are references.
</p><div class="table"><p><a name="table:actions"></a><b>Table 2. Action types</b></p><table summary="Action types" border="1"><colgroup><col><col></colgroup><tbody><tr><td><tt>+</tt></td><td><tt>arithmetic_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-</tt></td><td><tt>arithmetic_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>*</tt></td><td><tt>arithmetic_action&lt;multiply_action&gt;</tt></td></tr><tr><td><tt>/</tt></td><td><tt>arithmetic_action&lt;divide_action&gt;</tt></td></tr><tr><td><tt>%</tt></td><td><tt>arithmetic_action&lt;remainder_action&gt;</tt></td></tr><tr><td><tt>+</tt></td><td><tt>unary_arithmetic_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-</tt></td><td><tt>unary_arithmetic_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>&amp;</tt></td><td><tt>bitwise_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>|</tt></td><td><tt>bitwise_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>~</tt></td><td><tt>bitwise_action&lt;not_action&gt;</tt></td></tr><tr><td><tt>^</tt></td><td><tt>bitwise_action&lt;xor_action&gt;</tt></td></tr><tr><td><tt>&lt;&lt;</tt></td><td><tt>bitwise_action&lt;leftshift_action_no_stream&gt;</tt></td></tr><tr><td><tt>&gt;&gt;</tt></td><td><tt>bitwise_action&lt;rightshift_action_no_stream&gt;</tt></td></tr><tr><td><tt>&amp;&amp;</tt></td><td><tt>logical_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>||</tt></td><td><tt>logical_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>!</tt></td><td><tt>logical_action&lt;not_action&gt;</tt></td></tr><tr><td><tt>&lt;</tt></td><td><tt>relational_action&lt;less_action&gt;</tt></td></tr><tr><td><tt>&gt;</tt></td><td><tt>relational_action&lt;greater_action&gt;</tt></td></tr><tr><td><tt>&lt;=</tt></td><td><tt>relational_action&lt;lessorequal_action&gt;</tt></td></tr><tr><td><tt>&gt;=</tt></td><td><tt>relational_action&lt;greaterorequal_action&gt;</tt></td></tr><tr><td><tt>==</tt></td><td><tt>relational_action&lt;equal_action&gt;</tt></td></tr><tr><td><tt>!=</tt></td><td><tt>relational_action&lt;notequal_action&gt;</tt></td></tr><tr><td><tt>+=</tt></td><td><tt>arithmetic_assignment_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-=</tt></td><td><tt>arithmetic_assignment_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>*=</tt></td><td><tt>arithmetic_assignment_action&lt;multiply_action&gt;</tt></td></tr><tr><td><tt>/=</tt></td><td><tt>arithmetic_assignment_action&lt;divide_action&gt;</tt></td></tr><tr><td><tt>%=</tt></td><td><tt>arithmetic_assignment_action&lt;remainder_action&gt;</tt></td></tr><tr><td><tt>&amp;=</tt></td><td><tt>bitwise_assignment_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>=|</tt></td><td><tt>bitwise_assignment_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>^=</tt></td><td><tt>bitwise_assignment_action&lt;xor_action&gt;</tt></td></tr><tr><td><tt>&lt;&lt;=</tt></td><td><tt>bitwise_assignment_action&lt;leftshift_action&gt;</tt></td></tr><tr><td><tt>&gt;&gt;=</tt></td><td><tt>bitwise_assignment_action&lt;rightshift_action&gt;</tt></td></tr><tr><td><tt>++</tt></td><td><tt>pre_increment_decrement_action&lt;increment_action&gt;</tt></td></tr><tr><td><tt>--</tt></td><td><tt>pre_increment_decrement_action&lt;decrement_action&gt;</tt></td></tr><tr><td><tt>++</tt></td><td><tt>post_increment_decrement_action&lt;increment_action&gt;</tt></td></tr><tr><td><tt>--</tt></td><td><tt>post_increment_decrement_action&lt;decrement_action&gt;</tt></td></tr><tr><td><tt>&amp;</tt></td><td><tt>other_action&lt;address_of_action&gt;</tt></td></tr><tr><td><tt>*</tt></td><td><tt>other_action&lt;contents_of_action&gt;</tt></td></tr><tr><td><tt>,</tt></td><td><tt>other_action&lt;comma_action&gt;</tt></td></tr></tbody></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s05.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Lambda expressions in details </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Practical considerations</td></tr></table></div></body></html>

View File

@@ -1,169 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>7. Practical considerations</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s06.html" title="6. Extending return type deduction system"><link rel="next" href="ar01s08.html" title="8. Relation to other Boost libraries"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. Practical considerations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s06.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s08.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2807558"></a>7. Practical considerations</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2807564"></a>7.1. Performance</h3></div></div><p>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.
</p><p>
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<sup>5</sup>.
The expressions were called inside a <tt>std::transform</tt> loop,
reading the argument from one <tt>std::vector&lt;int&gt;</tt>
and placing the result into another.
The length of the vectors was 100 elements.
The running times are listed in
<a href="ar01s07.html#table:increasing_arithmetic_test" title="Table 3. 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.">Table 3</a>.
We can observe that there is no significant difference between the
two approaches.
</p><p>
In the second test we again used <tt>std::transform</tt> to
perform an operation to each element in a 100-element long vector.
This time the element type of the vectors was <tt>double</tt>
and we started with very simple arithmetic expressions and moved to
more complex ones.
The running times are listed in <a href="ar01s07.html#table:ll_vs_stl_test" title="Table 4. Test 2. CPU time of arithmetic expressions written as lambda
expressions, as classic STL unnamed functions (using compose2, bind1st etc.) and as traditional hand-coded function object classes.
Using BLL terminology,
a and b are bound arguments in the expressions, and x is open.
All variables were of types double.
The running times are expressed in arbitrary units.">Table 4</a>.
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 <a href="ar01s07.html#table:ll_vs_stl_test" title="Table 4. Test 2. CPU time of arithmetic expressions written as lambda
expressions, as classic STL unnamed functions (using compose2, bind1st etc.) and as traditional hand-coded function object classes.
Using BLL terminology,
a and b are bound arguments in the expressions, and x is open.
All variables were of types double.
The running times are expressed in arbitrary units.">Table 4</a> written with
classic STL tools contains 7 calls to <tt>compose2</tt>,
8 calls to <tt>bind1st</tt>
and altogether 14 constructor invocations for creating
<tt>multiplies</tt>, <tt>minus</tt>
and <tt>plus</tt> 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.
</p><p>
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.
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 experiensed
this for some seemingly simple expressions.
<div class="table"><p><a name="table:increasing_arithmetic_test"></a><b>Table 3. 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.</b></p><table summary="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." border="1"><colgroup><col><col><col></colgroup><thead><tr><th>expression</th><th>lambda expression</th><th>hand-coded function object</th></tr></thead><tbody><tr><td>x</td><td>240</td><td>230</td></tr><tr><td>x*x</td><td>340</td><td>350</td></tr><tr><td>x*x*x</td><td>770</td><td>760</td></tr><tr><td>x*x*x*x</td><td>1180</td><td>1210</td></tr><tr><td>x*x*x*x*x</td><td>1950</td><td>1910</td></tr></tbody></table></div>
</p><p>
<div class="table"><p><a name="table:ll_vs_stl_test"></a><b>Table 4. Test 2. CPU time of arithmetic expressions written as lambda
expressions, as classic STL unnamed functions (using <tt>compose2</tt>, <tt>bind1st</tt> etc.) and as traditional hand-coded function object classes.
Using BLL terminology,
<tt>a</tt> and <tt>b</tt> are bound arguments in the expressions, and <tt>x</tt> is open.
All variables were of types <tt>double</tt>.
The running times are expressed in arbitrary units.</b></p><table summary="Test 2. CPU time of arithmetic expressions written as lambda
expressions, as classic STL unnamed functions (using compose2, bind1st etc.) and as traditional hand-coded function object classes.
Using BLL terminology,
a and b are bound arguments in the expressions, and x is open.
All variables were of types double.
The running times are expressed in arbitrary units." border="1"><colgroup><col><col><col><col></colgroup><thead><tr><th>expression</th><th>lambda expression</th><th>classic STL expression</th><th>hand-coded function object</th></tr></thead><tbody><tr><td>ax</td><td>330</td><td>370</td><td>290</td></tr><tr><td>-ax</td><td>350</td><td>370</td><td>310</td></tr><tr><td>ax-(a+x)</td><td>470</td><td>500</td><td>420</td></tr><tr><td>(ax-(a+x))(a+x)</td><td>620</td><td>670</td><td>600</td></tr><tr><td>((ax) - (a+x))(bx - (b+x))(ax - (b+x))(bx - (a+x))</td><td>1660</td><td>1660</td><td>1460</td></tr></tbody></table></div>
</p><p>Some additional performance testing with an earlier version of the
library is described
[<a href="bi01.html#cit:jarvi:00" title="[Jär00]">Jär00</a>].
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2808057"></a>7.2. About compiling</h3></div></div><p>The BLL uses templates rather heavily, performing numerous recursive instantiations of the same templates.
This has (at least) three implications:
<div class="itemizedlist"><ul type="disc"><li><p>
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.
</p></li><li><p>
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 the 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.
</p></li><li><p>
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.
</p></li></ul></div></p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2808118"></a>7.3. Portability</h3></div></div><p>
The BLL works with the following compilers, that is, the compilers are capable of compiling the test cases that are included with the BLL:
<div class="itemizedlist"><ul type="disc"><li>GCC 3.0.4
</li><li>KCC 4.0f with EDG 2.43.1
</li><li>GCC 2.96 (fails with one test case, the <tt>exception_test.cpp</tt> results in an internal compiler error.
)
</li></ul></div>
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2808157"></a>7.3.1. Test coverage</h4></div></div><p>The following list describes the test files included and the features that each file covers:
<div class="itemizedlist"><ul type="disc"><li><p>
<tt>bind_tests_simple.cpp</tt> : Bind expressions of different arities and types of target functions: function pointers, function objects and member functions.
Function composition with bind expressions.</p></li><li><p><tt>bind_tests_simple_function_references.cpp</tt> :
Repeats all tests from <tt>bind_tests_simple.cpp</tt> where the target function is a function pointer, but uses function references instead.
</p></li><li><p><tt>bind_tests_advanced.cpp</tt> : Contains tests for nested bind expressions, <tt>unlambda</tt>, <tt>protect</tt>, <tt>const_parameters</tt> and <tt>break_const</tt>.
Tests passing lambda functors as actual arguments to other lambda functors, currying, and using the <tt>sig</tt> template to specify the return type of a function object.
</p></li><li><p>
<tt>operator_tests_simple.cpp</tt> :
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.
</p></li><li><p><tt>member_pointer_test.cpp</tt> : The pointer to member operator is complex enough to warrant a separate test file.
</p></li><li><p>
<tt>control_structures.cpp</tt> :
Tests for the looping and if constructs.
</p></li><li><p>
<tt>switch_construct.cpp</tt> :
Includes tests for all supported arities of the switch statement, both with and without the default case.
</p></li><li><p>
<tt>exception_test.cpp</tt> :
Includes tests for throwing exceptions and for try/catch constructs with varying number of catch blocks.
</p></li><li><p>
<tt>constructor_tests.cpp</tt> :
Contains tests for <tt>constructor</tt>, <tt>destructor</tt>, <tt>new_ptr</tt>, <tt>delete_ptr</tt>, <tt>new_array</tt> and <tt>delete_array</tt>.
</p></li><li><p>
<tt>cast_test.cpp</tt> : Tests for the four cast expressions, as well as <tt>typeid</tt> and <tt>sizeof</tt>.
</p></li><li><p>
<tt>extending_return_type_traits.cpp</tt> : 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.
</p></li><li><p>
<tt>is_instance_of_test.cpp</tt> : Includes tests for an internally used traits template, which can detect whether a given type is an instance of a certain template or not.
</p></li><li><p>
<tt>bll_and_function.cpp</tt> :
Contains tests for using <tt>boost::function</tt> together with lambda functors.
</p></li></ul></div>
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s06.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s08.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Extending return type deduction system </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 8. Relation to other Boost libraries</td></tr></table></div></body></html>

View File

@@ -1,124 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>8. Relation to other Boost libraries</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s07.html" title="7. Practical considerations"><link rel="next" href="ar01s09.html" title="9. Contributors"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. Relation to other Boost libraries</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s07.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s09.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2808502"></a>8. Relation to other Boost libraries</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2808510"></a>8.1. Boost Function</h3></div></div><p>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.
<span class="emphasis"><i>The Boost Function library</i></span> [<a href="bi01.html#cit:boost::function" title="[function]">function</a>] defines wrappers for arbitrary function objects, for example
lambda functors; and these wrappers have types that are easy to type out.
For example:
<pre class="programlisting">
boost::function&lt;int, int, int&gt; f = _1 + _2;
boost::function&lt;int&amp;, int&amp;&gt; g = unlambda(_1 += 10);
int i = 1, j = 2;
f(i); // returns 3
g(i); // sets i to = 11;
</pre>
The return and parameter types of the wrapped function object must be written explicilty as template arguments to the wrapper template <tt>boost::function</tt>; even when lambda functors, which otherwise have generic parameters, are wrapped.
Wrapping a function object with <tt>boost::function</tt> introduces a performance cost comparable to virtual function dispatch, though virtual functions are not actually used.
Note that storing lambda functors inside <tt>boost::function</tt>
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 <tt>boost::function</tt>
may continue to exist longer, creating the possibility of dangling references.
For example:
<pre class="programlisting">
int* sum = new int();
*sum = 0;
boost::function&lt;int&amp;, int&gt; counter = *sum += _1;
counter(5); // ok, *sum = 5;
delete sum;
counter(3); // error, *sum does not exist anymore
</pre>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2808614"></a>8.2. Boost Bind</h3></div></div><p>
<span class="emphasis"><i>The Boost Bind</i></span> [<a href="bi01.html#cit:boost::bind" title="[bind]">bind</a>] 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.
</p><p>
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 <tt>boost</tt> namespace,
whereas the BLL names are in <tt>boost::lambda</tt> namespace.
</p><p>
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.
</p><p>
The following two sections describe what are the semantic differences
between the bind expressions in BB and BLL.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2808678"></a>8.2.1. First argument of bind expression</h4></div></div>
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:
<pre class="programlisting">
template&lt;class F&gt;
int foo(const F&amp; f) {
int x;
..
bind(f, _1)(x);
...
}
</pre><pre class="programlisting">
int bar(int, int);
nested(bind(bar, 1, _1));
</pre>
The bind expression inside <tt>foo</tt> becomes:
<pre class="programlisting">
bind(bind(bar, 1, _1), _1)(x)
</pre>
The BLL interpretes this as:
<pre class="programlisting">
bar(1, x)(x)
</pre>
whereas the BB library as
<pre class="programlisting">
bar(1, x)
</pre>
To get this functionality in BLL, the bind expression inside the <tt>foo</tt> function can be written as:
<pre class="programlisting">
bind(unlambda(f), _1)(x);
</pre>
as explained in <a href="ar01s05.html#sect:unlambda" title="5.9.1.1. Unlambda">Section 5.9.1.1</a>.
</div><p>
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.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s07.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s09.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Practical considerations </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Contributors</td></tr></table></div></body></html>

View File

@@ -1,16 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>9. Contributors</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s08.html" title="8. Relation to other Boost libraries"><link rel="next" href="apa.html" title="A. Rationale for some of the design decisions"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9. Contributors</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s08.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="apa.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2808810"></a>9. Contributors</h2></div></div>
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.
</div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s08.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="apa.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Relation to other Boost libraries </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> A. Rationale for some of the design decisions</td></tr></table></div></body></html>

View File

@@ -1,19 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Bibliography</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="apa.html" title="A. Rationale for some of the design decisions"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Bibliography</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apa.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div id="id2808984" class="bibliography"><div class="titlepage"><div><h2 class="title"><a name="id2808984"></a>Bibliography</h2></div></div><div class="biblioentry"><a name="cit:stepanov:94"></a><p>[STL94] <span class="authorgroup">A. A. Stepanov and M. Lee. </span><span class="title"><I>The Standard Template Library</I>. </span><span class="orgname">Hewlett-Packard Laboratories. </span><span class="pubdate">1994. </span><span class="bibliomisc">
<a href="http://www.hpl.hp.com/techreports" target="_top">www.hpl.hp.com/techreports</a>
. </span></p></div><div class="biblioentry"><a name="cit:sgi:02"></a><p>[SGI02] <span class="title"><I>The SGI Standard Template Library</I>. </span><span class="pubdate">2002. </span><span class="bibliomisc"><a href="http://www.sgi.com/tech/stl/" target="_top">www.sgi.com/tech/stl/</a>. </span></p></div><div class="biblioentry"><a name="cit:c++:98"></a><p>[C++98] <span class="title"><I>International Standard, Programming Languages &#8211; C++</I>. </span><span class="subtitle">ISO/IEC:14882. </span><span class="pubdate">1998. </span></p></div><div class="biblioentry"><a name="cit:jarvi:99"></a><p>[Jär99] <span class="articleinfo">
<span class="author">Jaakko Järvi. </span>
<span class="title"><I>C++ Function Object Binders Made Easy</I>. </span>
. </span><span class="title"><I>Lecture Notes in Computer Science</I>. </span><span class="volumenum">1977. </span><span class="publishername">Springer. </span><span class="pubdate">2000. </span></p></div><div class="biblioentry"><a name="cit:jarvi:00"></a><p>[Jär00] <span class="author">Jaakko Järvi. </span><span class="author">Gary Powell. </span><span class="title"><I>The Lambda Library : Lambda Abstraction in C++</I>. </span><span class="orgname">Turku Centre for Computer Science. </span><span class="bibliomisc">Technical Report . </span><span class="issuenum">378. </span><span class="pubdate">2000. </span><span class="bibliomisc"><a href="http://www.tucs.fi/Publications/techreports/TR378.php" target="_top">www.tucs.fi/publications</a>. </span></p></div><div class="biblioentry"><a name="cit:jarvi:01"></a><p>[Jär01] <span class="author">Jaakko Järvi. </span><span class="author">Gary Powell. </span><span class="title"><I>The Lambda Library : Lambda Abstraction in C++</I>. </span><span class="confgroup"><span class="conftitle">Second Workshop on C++ Template Programming. </span><span class="address">Tampa Bay, OOPSLA'01. </span>. </span><span class="pubdate">2001. </span><span class="bibliomisc"><a href="http://www.oonumerics.org/tmpw01/" target="_top">www.oonumerics.org/tmpw01/</a>. </span></p></div><div class="biblioentry"><a name="cit:boost::tuple"></a><p>[tuple] <span class="title"><I>The Boost Tuple Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html" target="_top">www.boost.org/libs/tuple/doc/tuple_users_guide.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::type_traits"></a><p>[type_traits] <span class="title"><I>The Boost type_traits</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/type_traits/index.htm" target="_top">www.boost.org/libs/type_traits/</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::ref"></a><p>[ref] <span class="title"><I>Boost ref</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/bind/ref.html" target="_top">www.boost.org/libs/bind/ref.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::bind"></a><p>[bind] <span class="title"><I>Boost Bind Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/bind/bind.html" target="_top">www.boost.org/libs/bind/bind.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::function"></a><p>[function] <span class="title"><I>Boost Function Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/function/" target="_top">www.boost.org/libs/function/</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:fc++"></a><p>[fc++] <span class="title"><I>The FC++ library: Functional Programming in C++</I>. </span><span class="author">Yannis Smaragdakis. </span><span class="author">Brian McNamara. </span><span class="bibliomisc"><a href="http://www.cc.gatech.edu/~yannis/fc++/" target="_top">www.cc.gatech.edu/~yannis/fc++/</a>
. </span><span class="pubdate">2002. </span></p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="apa.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">A. Rationale for some of the design decisions </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>

View File

@@ -1,7 +0,0 @@
- 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.html loads stylesheets that generate one big html-file
(you need to edit the paths in these files to make them work)

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
<?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>

View File

@@ -1,19 +0,0 @@
<?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>

View File

@@ -1,39 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>
C++ BOOST
The Boost Lambda Library</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="next" href="ar01s02.html" title="2. Getting Started"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">
C++ BOOST
The Boost Lambda Library</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s02.html">Next</a></td></tr></table><hr></div><div class="article"><div class="titlepage"><div><h1 class="title"><a name="id2733457"></a>
<span class="inlinemediaobject"><img src="../../../c++boost.gif" alt="C++ BOOST"></span>
The Boost Lambda Library</h1></div><div><p class="copyright">Copyright © 1999-2002 Jaakko Järvi, Gary Powell</p></div><div><div class="legalnotice"><p>
The Boost Lambda Library is free software; Permission to copy,
use, modify and distribute this software and its documentation is granted, provided this copyright
notice appears in all copies.
</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt>1. <a href="index.html#introduction">In a nutshell</a></dt><dt>2. <a href="ar01s02.html">Getting Started</a></dt><dd><dl><dt>2.1. <a href="ar01s02.html#id2790109">Installing the library</a></dt><dt>2.2. <a href="ar01s02.html#id2741935">Conventions used in this document</a></dt></dl></dd><dt>3. <a href="ar01s03.html">Introduction</a></dt><dd><dl><dt>3.1. <a href="ar01s03.html#id2741989">Motivation</a></dt><dt>3.2. <a href="ar01s03.html#id2742784">Introduction to lambda expressions</a></dt></dl></dd><dt>4. <a href="ar01s04.html">Using the library</a></dt><dd><dl><dt>4.1. <a href="ar01s04.html#sect:introductory_examples">Introductory Examples</a></dt><dt>4.2. <a href="ar01s04.html#sect:parameter_and_return_types">Parameter and return types of lambda functors</a></dt><dt>4.3. <a href="ar01s04.html#sect:actual_arguments_to_lambda_functors">About actual arguments to lambda functors</a></dt><dt>4.4. <a href="ar01s04.html#sect:storing_bound_arguments">Storing bound arguments in lambda functions</a></dt></dl></dd><dt>5. <a href="ar01s05.html">Lambda expressions in details</a></dt><dd><dl><dt>5.1. <a href="ar01s05.html#sect:placeholders">Placeholders</a></dt><dt>5.2. <a href="ar01s05.html#sect:operator_expressions">Operator expressions</a></dt><dt>5.3. <a href="ar01s05.html#sect:bind_expressions">Bind expressions</a></dt><dt>5.4. <a href="ar01s05.html#sect:overriding_deduced_return_type">Overriding the deduced return type</a></dt><dt>5.5. <a href="ar01s05.html#sect:delaying_constants_and_variables">Delaying constants and variables</a></dt><dt>5.6. <a href="ar01s05.html#sect:lambda_expressions_for_control_structures">Lambda expressions for control structures</a></dt><dt>5.7. <a href="ar01s05.html#sect:exceptions">Exceptions</a></dt><dt>5.8. <a href="ar01s05.html#sect:construction_and_destruction">Construction and destruction</a></dt><dt>5.9. <a href="ar01s05.html#id2805476">Special lambda expressions</a></dt><dt>5.10. <a href="ar01s05.html#id2806049">Casts, sizeof and typeid</a></dt><dt>5.11. <a href="ar01s05.html#sect:nested_stl_algorithms">Nesting STL algorithm invocations</a></dt></dl></dd><dt>6. <a href="ar01s06.html">Extending return type deduction system</a></dt><dt>7. <a href="ar01s07.html">Practical considerations</a></dt><dd><dl><dt>7.1. <a href="ar01s07.html#id2807564">Performance</a></dt><dt>7.2. <a href="ar01s07.html#id2808057">About compiling</a></dt><dt>7.3. <a href="ar01s07.html#id2808118">Portability</a></dt></dl></dd><dt>8. <a href="ar01s08.html">Relation to other Boost libraries</a></dt><dd><dl><dt>8.1. <a href="ar01s08.html#id2808510">Boost Function</a></dt><dt>8.2. <a href="ar01s08.html#id2808614">Boost Bind</a></dt></dl></dd><dt>9. <a href="ar01s09.html">Contributors</a></dt><dt>A. <a href="apa.html">Rationale for some of the design decisions</a></dt><dd><dl><dt>1. <a href="apa.html#sect:why_weak_arity">
Lambda functor arity
</a></dt></dl></dd><dt><a href="bi01.html">Bibliography</a></dt></dl></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="introduction"></a>1. In a nutshell</h2></div></div><p>
The Boost Lambda Library (BLL in the sequel) is a C++ template
library, which implements form of <span class="emphasis"><i>lambda abstractions</i></span> 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
<tt>a</tt> separated by spaces:
<pre class="programlisting">for_each(a.begin(), a.end(), std::cout &lt;&lt; _1 &lt;&lt; ' ');</pre>
The expression <tt>std::cout &lt;&lt; _1 &lt;&lt; ' '</tt> defines a unary function object.
The variable <tt>_1</tt> is the parameter of this function, a <span class="emphasis"><i>placeholder</i></span> for the actual argument.
Within each iteration of <tt>for_each</tt>, the function is
called with an element of <tt>a</tt> as the actual argument.
This actual argument is substituted for the placeholder, and the &#8216;body&#8217; of the function is evaluated.
</p><p>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.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="ar01s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"> </td><td width="40%" align="right" valign="top"> 2. Getting Started</td></tr></table></div></body></html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
// - casts.hpp -- BLambda Library -------------
//
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy, use, sell and distribute this software is granted

View File

@@ -1,6 +1,6 @@
// - construct.hpp -- Lambda Library -------------
//
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy, use, sell and distribute this software is granted

View File

@@ -1,4 +1,18 @@
// -- core.hpp -- Boost Lambda Library -------------------------------------
//
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// For more information, see www.boost.org
//
// Includes the core of LL, without any real features for client:
//

View File

@@ -1,7 +1,7 @@
// Boost Lambda Library -- control_constructs_common.hpp -------------------
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.

View File

@@ -1,7 +1,7 @@
// Boost Lambda Library -- control_structures_impl.hpp ---------------------
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.

View File

@@ -345,6 +345,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3) const> {
template <class Object, class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3)> {
template<class T> struct sig { typedef Result type; };
template <class RET, class A1, class A2, class A3>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3), Object* o, A1& a1, A2& a2, A3& a3) {
return (o->*func)(a1, a2, a3);
@@ -618,6 +619,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8,
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {
template<class T> struct sig { typedef Result type; };
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9) {
return func(a1, a2, a3, a4, a5, a6, a7, a8, a9);

View File

@@ -43,9 +43,9 @@
// Now we only have one version of is_instance_of templates, which delagate
// all the nasty compiler tricks to is_convertible.
#define BOOST_LAMBDA_CLASS(N,A) BOOST_PP_COMMA_IF(N) class
#define BOOST_LAMBDA_CLASS_ARG(N,A) BOOST_PP_COMMA_IF(N) class A##N
#define BOOST_LAMBDA_ARG(N,A) BOOST_PP_COMMA_IF(N) A##N
#define BOOST_LAMBDA_CLASS(z, N,A) BOOST_PP_COMMA_IF(N) class
#define BOOST_LAMBDA_CLASS_ARG(z, N,A) BOOST_PP_COMMA_IF(N) class A##N
#define BOOST_LAMBDA_ARG(z, N,A) BOOST_PP_COMMA_IF(N) A##N
#define BOOST_LAMBDA_CLASS_LIST(n, NAME) BOOST_PP_REPEAT(n, BOOST_LAMBDA_CLASS, NAME)
@@ -83,7 +83,7 @@ public: \
};
#define BOOST_LAMBDA_HELPER(N, A) BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE( BOOST_PP_INC(N) )
#define BOOST_LAMBDA_HELPER(z, N, A) BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE( BOOST_PP_INC(N) )
// Generate the traits for 1-4 argument templates

View File

@@ -315,7 +315,7 @@ public:
template<class RET, CALL_TEMPLATE_ARGS> RET call(CALL_FORMAL_ARGS) const {
CALL_USE_ARGS;
return CALL_USE_ARGS;
}
template<class SigArgs> struct sig { typedef void type; };

View File

@@ -436,10 +436,10 @@ namespace detail {
template<class RET, class A, class B>
class member_pointer_caller {
A a;
B b;
A a; B b;
public:
member_pointer_caller(A aa, B bb) : a(aa), b(bb) {}
member_pointer_caller(const A& aa, const B& bb) : a(aa), b(bb) {}
RET operator()() const { return (a->*b)(); }
@@ -589,29 +589,24 @@ struct member_pointer_action_helper<false, true> {
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
typedef typename ::boost::remove_cv<B>::type plainB;
typedef typename detail::member_pointer<plainB>::type ret_t;
typedef typename ::boost::remove_cv<A>::type plainA;
// we always add const (it is just the pointer types, not the types
// pointed to) to make the to routes (calling and type deduction)
// we always strip cv:s to
// make the two routes (calling and type deduction)
// to give the same results (and the const does not make any functional
// difference)
return detail::member_pointer_caller<ret_t, const A&, const B&>(a, b);
return detail::member_pointer_caller<ret_t, plainA, plainB>(a, b);
}
template<class A, class B>
struct return_type {
typedef typename detail::remove_reference_and_cv<B>::type plainB;
typedef typename detail::member_pointer<plainB>::type ret_t;
typedef typename detail::remove_reference_and_cv<A>::type plainA;
// we always add const (it is just the pointer types, not the types
// pointed to)
typedef detail::member_pointer_caller<
ret_t,
typename boost::add_reference<const A>::type,
typename boost::add_reference<const B>::type
> type;
typedef detail::member_pointer_caller<ret_t, plainA, plainB> type;
};
};
@@ -621,12 +616,10 @@ template<> class other_action<member_pointer_action> {
public:
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
typedef typename
::boost::remove_cv<B>::type plainB;
return
detail::member_pointer_action_helper<
return detail::member_pointer_action_helper<
boost::is_pointer<A>::value &&
detail::member_pointer<plainB>::is_data_member,
boost::is_pointer<A>::value &&

View File

@@ -19,6 +19,8 @@
#include "boost/lambda/detail/is_instance_of.hpp"
#include "boost/type_traits/same_traits.hpp"
#include "boost/indirect_reference.hpp"
#include <cstddef> // needed for the ptrdiff_t
#include <iosfwd> // for istream and ostream
@@ -221,7 +223,7 @@ namespace detail {
// A is a nonreference type
template <class A> struct contentsof_type {
typedef typename std::iterator_traits<A>::reference type;
typedef typename boost::indirect_reference<A>::type type;
};
// this is since the nullary () in lambda_functor is always instantiated
@@ -492,7 +494,6 @@ struct promotion_of_unsigned_int
{
typedef
detail::IF<sizeof(long) <= sizeof(unsigned int),
// I had the logic reversed but ">" messes up the parsing.
unsigned long,
long>::RET type;
};
@@ -863,13 +864,34 @@ struct return_type_2<other_action<subscript_action>, A, B> {
namespace std {
template <class Key, class T, class Cmp, class Allocator> class map;
template <class Key, class T, class Cmp, class Allocator> class multimap;
template <class T, class Allocator> class vector;
template <class T, class Allocator> class deque;
template <class Char, class Traits, class Allocator> class basic_string;
}
// The GCC 2.95.x uses a non-conformant deque
#if BOOST_WORKAROUND(__GNUC__, == 2) && __GNUC_MINOR__ <= 96
#include <deque>
#else
namespace std {
template <class T, class Allocator> class deque;
}
#endif
#if BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ >=4
#include <vector>
#include <map>
#else
namespace std {
template <class T, class Allocator> class vector;
template <class Key, class T, class Cmp, class Allocator> class map;
template <class Key, class T, class Cmp, class Allocator> class multimap;
}
#endif
namespace boost {
namespace lambda {

View File

@@ -27,22 +27,31 @@ namespace lambda {
#error "Multiple defines of BOOST_LAMBDA_BE1"
#endif
// For all BOOSTA_LAMBDA_BE* macros:
// CONSTA must be either 'A' or 'const A'
// CONSTB must be either 'B' or 'const B'
// It is stupid to have the names A and B as macro arguments, but it avoids
// the need to pass in emtpy macro arguments, which gives warnings on some
// compilers
#define BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
template<class Arg, class B> \
inline const \
lambda_functor< \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB B>::type> \
tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB>::type> \
> \
> \
OPER_NAME (const lambda_functor<Arg>& a, CONSTB B& b) { \
OPER_NAME (const lambda_functor<Arg>& a, CONSTB& b) { \
return \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB B>::type> \
tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB>::type> \
> \
(tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB B>::type>(a, b)); \
(tuple<lambda_functor<Arg>, typename CONVERSION <CONSTB>::type>(a, b)); \
}
@@ -56,16 +65,16 @@ inline const \
lambda_functor< \
lambda_functor_base< \
ACTION, \
tuple<typename CONVERSION <CONSTA A>::type, lambda_functor<Arg> > \
tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
> \
> \
OPER_NAME (CONSTA A& a, const lambda_functor<Arg>& b) { \
OPER_NAME (CONSTA& a, const lambda_functor<Arg>& b) { \
return \
lambda_functor_base< \
ACTION, \
tuple<typename CONVERSION <CONSTA A>::type, lambda_functor<Arg> > \
tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
> \
(tuple<typename CONVERSION <CONSTA A>::type, lambda_functor<Arg> >(a, b)); \
(tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> >(a, b)); \
}
@@ -100,36 +109,37 @@ BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION)
#define BOOST_LAMBDA_EMPTY()
BOOST_LAMBDA_BE(operator+, arithmetic_action<plus_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator-, arithmetic_action<minus_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator*, arithmetic_action<multiply_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator/, arithmetic_action<divide_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator%, arithmetic_action<remainder_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator<<, bitwise_action<leftshift_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator>>, bitwise_action<rightshift_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator&, bitwise_action<and_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator|, bitwise_action<or_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator^, bitwise_action<xor_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator&&, logical_action<and_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator||, logical_action<or_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator<, relational_action<less_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator>, relational_action<greater_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator<=, relational_action<lessorequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator>=, relational_action<greaterorequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator==, relational_action<equal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator!=, relational_action<notequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator+, arithmetic_action<plus_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator-, arithmetic_action<minus_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator*, arithmetic_action<multiply_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator/, arithmetic_action<divide_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator%, arithmetic_action<remainder_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<<, bitwise_action<leftshift_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>>, bitwise_action<rightshift_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator&, bitwise_action<and_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator|, bitwise_action<or_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator^, bitwise_action<xor_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator&&, logical_action<and_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator||, logical_action<or_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<, relational_action<less_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>, relational_action<greater_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<=, relational_action<lessorequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>=, relational_action<greaterorequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator==, relational_action<equal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator!=, relational_action<notequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator+=, arithmetic_assignment_action<plus_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator-=, arithmetic_assignment_action<minus_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator*=, arithmetic_assignment_action<multiply_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator/=, arithmetic_assignment_action<divide_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator%=, arithmetic_assignment_action<remainder_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator<<=, bitwise_assignment_action<leftshift_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator>>=, bitwise_assignment_action<rightshift_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator&=, bitwise_assignment_action<and_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator|=, bitwise_assignment_action<or_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, , const, reference_argument)
BOOST_LAMBDA_BE(operator+=, arithmetic_assignment_action<plus_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator-=, arithmetic_assignment_action<minus_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator*=, arithmetic_assignment_action<multiply_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator/=, arithmetic_assignment_action<divide_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator%=, arithmetic_assignment_action<remainder_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator<<=, bitwise_assignment_action<leftshift_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator>>=, bitwise_assignment_action<rightshift_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator&=, bitwise_assignment_action<and_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator|=, bitwise_assignment_action<or_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, A, const B, reference_argument)
// A special trick for comma operator for correct preprocessing
@@ -139,9 +149,9 @@ BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, , const, refe
#define BOOST_LAMBDA_COMMA_OPERATOR_NAME operator,
BOOST_LAMBDA_BE1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
@@ -197,8 +207,8 @@ template<class T> struct convert_istream_to_ref_others_to_c_plain_by_default {
} // detail
BOOST_LAMBDA_BE2(operator<<, bitwise_action< leftshift_action>, , const, detail::convert_ostream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, , const, detail::convert_istream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BE2(operator<<, bitwise_action< leftshift_action>, A, const B, detail::convert_ostream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, A, const B, detail::convert_istream_to_ref_others_to_c_plain_by_default)
// special case for io_manipulators.
@@ -253,17 +263,17 @@ operator>>(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E1"
#endif
#define BOOST_LAMBDA_PTR_ARITHMETIC_E1(OPER_NAME, ACTION, CONST) \
#define BOOST_LAMBDA_PTR_ARITHMETIC_E1(OPER_NAME, ACTION, CONSTB) \
template<class Arg, int N, class B> \
inline const \
lambda_functor< \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONST B(&)[N]> > \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
> \
OPER_NAME (const lambda_functor<Arg>& a, CONST B(&b)[N]) \
OPER_NAME (const lambda_functor<Arg>& a, CONSTB(&b)[N]) \
{ \
return lambda_functor< \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONST B(&)[N]> > \
>(tuple<lambda_functor<Arg>, CONST B(&)[N]>(a, b)); \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
>(tuple<lambda_functor<Arg>, CONSTB(&)[N]>(a, b)); \
}
@@ -271,31 +281,31 @@ OPER_NAME (const lambda_functor<Arg>& a, CONST B(&b)[N]) \
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E2"
#endif
#define BOOST_LAMBDA_PTR_ARITHMETIC_E2(OPER_NAME, ACTION, CONST) \
#define BOOST_LAMBDA_PTR_ARITHMETIC_E2(OPER_NAME, ACTION, CONSTA) \
template<int N, class A, class Arg> \
inline const \
lambda_functor< \
lambda_functor_base<ACTION, tuple<CONST A(&)[N], lambda_functor<Arg> > > \
lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
> \
OPER_NAME (CONST A(&a)[N], const lambda_functor<Arg>& b) \
OPER_NAME (CONSTA(&a)[N], const lambda_functor<Arg>& b) \
{ \
return \
lambda_functor_base<ACTION, tuple<CONST A(&)[N], lambda_functor<Arg> > > \
(tuple<CONST A(&)[N], lambda_functor<Arg> >(a, b)); \
lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
(tuple<CONSTA(&)[N], lambda_functor<Arg> >(a, b)); \
}
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>,)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>,)
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>,const)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>,const)
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>, B)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>, A)
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>,const B)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>,const A)
//BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator-, arithmetic_action<minus_action>)
// This is not needed, since the result of ptr-ptr is an rvalue anyway
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, )
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, const)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, A)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, const A)
#undef BOOST_LAMBDA_BE1

View File

@@ -257,7 +257,7 @@ const_parameters(const lambda_functor<Arg>& lf)
// the wrapped lambda functor is evaluated, but we just don't do anything
// with the result.
struct voidifier_action {
template<class Ret, class A> static Ret apply(A&) {}
template<class Ret, class A> static void apply(A&) {}
};
template<class Args> struct return_type_N<voidifier_action, Args> {

View File

@@ -17,6 +17,8 @@
#ifndef BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
#define BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
#include "boost/mpl/aux_/has_xxx.hpp"
#include <cstddef> // needed for the ptrdiff_t
namespace boost {
@@ -239,6 +241,25 @@ struct return_type_N<function_action<I, Ret>, Args> {
typedef Ret type;
};
// ::result_type support
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<class F> struct get_result_type
{
typedef typename F::result_type type;
};
template<class F, class A> struct get_sig
{
typedef typename function_adaptor<F>::template sig<A>::type type;
};
} // namespace detail
// Ret is detail::unspecified, so try to deduce return type
template<int I, class Args>
struct return_type_N<function_action<I, detail::unspecified>, Args > {
@@ -251,7 +272,11 @@ struct return_type_N<function_action<I, detail::unspecified>, Args > {
public:
// pass the function to function_adaptor, and get the return type from
// that
typedef typename function_adaptor<plain_Func>::template sig<Args>::type type;
typedef typename detail::IF<
detail::has_result_type<plain_Func>::value,
detail::get_result_type<plain_Func>,
detail::get_sig<plain_Func, Args>
>::RET::type type;
};

View File

@@ -1,7 +1,7 @@
// Boost Lambda Library -- if.hpp ------------------------------------------
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 2001-2002 Joel de Guzman
//
// Permission to copy, use, sell and distribute this software is granted

View File

@@ -1,7 +1,7 @@
// Boost Lambda Library -- loops.hpp ----------------------------------------
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.

View File

@@ -1,6 +1,6 @@
// Boost Lambda Library -- switch.hpp -----------------------------------
//
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy, use, sell and distribute this software is granted
@@ -287,10 +287,10 @@ public:
// BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
#define BOOST_LAMBDA_A_I(i, A) \
#define BOOST_LAMBDA_A_I(z, i, A) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
#define BOOST_LAMBDA_A_I_B(i, T) \
#define BOOST_LAMBDA_A_I_B(z, i, T) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
#define BOOST_LAMBDA_A_I_LIST(i, A) \
@@ -301,7 +301,7 @@ BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B))
// Switch related macros -------------------------------------------
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK(N, A) \
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK(z, N, A) \
case Case##N: \
detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), CALL_ACTUAL_ARGS); \
break;
@@ -414,7 +414,7 @@ switch_statement(const lambda_functor<TestArg>& a1) {
}
#define HELPER(N, FOO) \
#define HELPER(z, N, FOO) \
BOOST_PP_COMMA_IF(N) \
BOOST_PP_CAT( \
const tagged_lambda_functor<detail::switch_case_tag<TagData, \
@@ -463,11 +463,11 @@ BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)
// Use this to avoid case 0, these macros work only from case 1 upwards
#define BOOST_LAMBDA_SWITCH_HELPER(N, A) \
#define BOOST_LAMBDA_SWITCH_HELPER(z, N, A) \
BOOST_LAMBDA_SWITCH( BOOST_PP_INC(N) )
// Use this to avoid cases 0 and 1, these macros work only from case 2 upwards
#define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(N, A) \
#define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(z, N, A) \
BOOST_LAMBDA_SWITCH_STATEMENT(BOOST_PP_INC(N))

View File

@@ -1,89 +0,0 @@
BOOST = ../../..
CXX = gcc
EXTRAFLAGS = -pedantic -Wno-long-long -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

View File

@@ -1,6 +0,0 @@
gcc 2.96
cannot compile
exception_test.cpp (internal compiler error)

View File

@@ -1,347 +0,0 @@
// bind_tests_advanced.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/any.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
using namespace 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_TEST(bind(bind(&sum_or_product, _1), 1, 2)(condition)==3);
BOOST_TEST(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==5);
condition = false;
BOOST_TEST(bind(bind(&sum_or_product, _1), 1, 2)(condition)==2);
BOOST_TEST(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==6);
which_one wo;
BOOST_TEST(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 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_TEST(unlambda(_1 + _2)(i, i) == 2);
BOOST_TEST(unlambda(++var(i))() == 2);
BOOST_TEST(call_with_100(_1 + 1) == 101);
BOOST_TEST(call_with_101(_1 + 1) == 102);
BOOST_TEST(call_with_100(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.
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_TEST(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_TEST(sum == (1+15)*15/2 + 15);
(1 + protect(_1))(sum);
int k = 0;
((k += constant(1)) += protect(constant(2)))();
BOOST_TEST(k==1);
k = 0;
((k += constant(1)) += protect(constant(2)))()();
BOOST_TEST(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_TEST((_1 + _2)(bind(&sum_0), make_const(7))() == 7);
int i = 3, j = 12;
BOOST_TEST((_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_TEST(bind(_1, _2, _3)(unlambda(_1 + _2), a, b) == 11);
//specify it yourself:
BOOST_TEST(bind(_1, _2, _3)(ret<int>(_1 + _2), a, b) == 11);
BOOST_TEST(ret<int>(bind(_1, _2, _3))(_1 + _2, a, b) == 11);
BOOST_TEST(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_TEST((_1 + _2)(make_const(1), make_const(2)) == 3);
// Or use const_parameters:
BOOST_TEST(const_parameters(_1 + _2)(1, 2) == 3);
}
void test_break_const()
{
// 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:
// E.g.
int i = 1;
// (_1 += _2)(i, 2) // fails, 2 is a non-const rvalue
// const_parameters(_1 += _2)(i, 2) // fails, side-effect to i
break_const(_1 += _2)(i, 2); // ok
BOOST_TEST(i == 3);
}
int test_main(int, char *[]) {
test_nested_binds();
test_unlambda();
test_protect();
test_lambda_functors_as_arguments_to_lambda_functors();
test_const_parameters();
test_break_const();
return 0;
}

View File

@@ -1,141 +0,0 @@
// bind_tests_simple.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include <iostream>
using namespace std;
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_TEST(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
BOOST_TEST(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_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, 1)()==1);
BOOST_TEST(bind(&sum_of_args_2, 1, 2)()==3);
BOOST_TEST(bind(&sum_of_args_3, 1, 2, 3)()==6);
BOOST_TEST(bind(&sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_TEST(bind(&sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_TEST(bind(&sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_TEST(bind(&sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_TEST(bind(&sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_TEST(bind(&sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
// first parameter open
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, 2)(i)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
// two open arguments
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
// three open arguments
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
// function compositions with bind
BOOST_TEST(bind(&sum_of_args_3, bind(&sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_TEST(
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_TEST(result == 12);
test_member_functions();
return 0;
}

View File

@@ -1,139 +0,0 @@
// bind_tests_simple.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include <iostream>
using namespace std;
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_TEST(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
BOOST_TEST(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_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, 1)()==1);
BOOST_TEST(bind(sum_of_args_2, 1, 2)()==3);
BOOST_TEST(bind(sum_of_args_3, 1, 2, 3)()==6);
BOOST_TEST(bind(sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_TEST(bind(sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_TEST(bind(sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_TEST(bind(sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_TEST(bind(sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_TEST(bind(sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
// first parameter open
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, 2)(i)==3);
BOOST_TEST(bind(sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_TEST(bind(sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_TEST(bind(sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_TEST(bind(sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_TEST(bind(sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_TEST(bind(sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_TEST(bind(sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
// two open arguments
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_TEST(bind(sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_TEST(bind(sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_TEST(bind(sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_TEST(bind(sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_TEST(bind(sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_TEST(bind(sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
// three open arguments
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_TEST(bind(sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_TEST(bind(sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_TEST(bind(sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_TEST(bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_TEST(bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_TEST(bind(sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
// function compositions with bind
BOOST_TEST(bind(sum_of_args_3, bind(sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_TEST(
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_TEST(result == 12);
test_member_functions();
return 0;
}

View File

@@ -1,60 +0,0 @@
// bll_and_function.cpp --------------------------------
// test using BLL and boost::function
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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_TEST(f(1, 2)== 3);
int i=1; int j=2;
boost::function<int&, int&, int> g = _1 += _2;
g(i, j);
BOOST_TEST(i==3);
int* sum = new int();
*sum = 0;
boost::function<int&, int> counter = *sum += _1;
counter(5); // ok, sum* = 5;
BOOST_TEST(*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;
}

View File

@@ -1,96 +0,0 @@
// cast_tests.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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"; }
};
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_TEST(b->class_name() == "derived");
BOOST_TEST(d->class_name() == "derived");
(var(b) = ll_dynamic_cast<derived *>(b))();
BOOST_TEST(b != 0);
BOOST_TEST(b->class_name() == "derived");
(var(d) = ll_dynamic_cast<derived *>(p_base))();
BOOST_TEST(d == 0);
const derived* p_const_derived = p_derived;
BOOST_TEST(p_const_derived->class_name() == "const derived");
(var(d) = ll_const_cast<derived *>(p_const_derived))();
BOOST_TEST(d->class_name() == "derived");
int i = 10;
char* cp = reinterpret_cast<char*>(&i);
int* ip;
(var(ip) = ll_reinterpret_cast<int *>(cp))();
BOOST_TEST(*ip == 10);
// typeid
BOOST_TEST(string(ll_typeid(d)().name()) == string(typeid(d).name()));
// sizeof
BOOST_TEST(ll_sizeof(_1)(p_derived) == sizeof(p_derived));
BOOST_TEST(ll_sizeof(_1)(*p_derived) == sizeof(*p_derived));
BOOST_TEST(ll_sizeof(_1)(p_base) == sizeof(p_base));
BOOST_TEST(ll_sizeof(_1)(*p_base) == sizeof(*p_base));
int an_array[100];
BOOST_TEST(ll_sizeof(_1)(an_array) == 100 * sizeof(int));
delete p_derived;
delete p_base;
}
int test_main(int, char *[]) {
do_test();
return 0;
}

View File

@@ -1,250 +0,0 @@
// constructor_tests.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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>
using namespace boost::lambda;
using namespace std;
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_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int> >(),
1, 2)()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int> >(),
1, 2, 3)()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int> >(),
1, 2, 3, 4)()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5)()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6)()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7)()
);
BOOST_TEST(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_TEST(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_TEST(ok);
}
void new_ptr_all_lengths()
{
bool ok;
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int> >(),
1))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int> >(),
1, 2))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int> >(),
1, 2, 3))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int> >(),
1, 2, 3, 4))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6))()
);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7))()
);
BOOST_TEST(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_TEST(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_TEST(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;
is_destructor_called* idc = new(space) is_destructor_called(flag);
BOOST_TEST(flag == false);
bind(destructor(), _1)(idc);
BOOST_TEST(flag == true);
idc = new(space) is_destructor_called(flag);
BOOST_TEST(flag == false);
bind(destructor(), _1)(*idc);
BOOST_TEST(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];
for_each(i, i+10, _1 = bind(new_ptr<int>(), 2));
int count_errors = 0;
for_each(i, i+10, (*_1 == 2) || ++var(count_errors));
BOOST_TEST(count_errors == 0);
count_deletes* ct[10];
for_each(ct, ct+10, _1 = bind(new_ptr<count_deletes>()));
count_deletes::count = 0;
for_each(ct, ct+10, bind(delete_ptr(), _1));
BOOST_TEST(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_TEST(count_deletes::count == 5);
}
void delayed_construction()
{
vector<int> x(3);
vector<int> y(3);
fill(x.begin(), x.end(), 0);
fill(y.begin(), y.end(), 1);
vector<pair<int, int> > v;
transform(x.begin(), x.end(), y.begin(), back_inserter(v),
bind(constructor<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;
}

View File

@@ -1,100 +0,0 @@
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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 namespace boost::lambda;
// 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_TEST(arithmetic_series == 45);
// no body case
for_loop(var(i) = 0, var(i) < 100, ++var(i))();
BOOST_TEST(i == 100);
// while loops -------------------------------------------------------
int a = 0, b = 0, c = 0;
while_loop((_1 + _2) >= (_1 * _2), (++_1, ++_2, ++_3))(a, b, c);
BOOST_TEST(c == 3);
int count;
count = 0; i = 0;
while_loop(_1++ < 10, ++var(count))(i);
BOOST_TEST(count == 10);
// note that the first parameter of do_while_loop is the condition
count = 0; i = 0;
do_while_loop(_1++ < 10, ++var(count))(i);
BOOST_TEST(count == 11);
a = 0;
do_while_loop(constant(false), _1++)(a);
BOOST_TEST(a == 1);
// no body cases
a = 40; b = 30;
while_loop(--_1 > _2)(a, b);
BOOST_TEST(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_TEST(a == b);
}
void simple_ifs () {
int value = 42;
if_then(_1 < 0, _1 = 0)(value);
BOOST_TEST(value == 42);
value = -42;
if_then(_1 < 0, _1 = -_1)(value);
BOOST_TEST(value == 42);
int min;
if_then_else(_1 < _2, var(min) = _1, var(min) = _2)
(make_const(1), make_const(2));
BOOST_TEST(min == 1);
if_then_else(_1 < _2, var(min) = _1, var(min) = _2)
(make_const(5), make_const(3));
BOOST_TEST(min == 3);
int x, y;
x = -1; y = 1;
BOOST_TEST(if_then_else_return(_1 < _2, _2, _1)(x, y) == std::max(x ,y));
BOOST_TEST(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;
}

View File

@@ -1,609 +0,0 @@
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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& 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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(
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_TEST(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_TEST(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_TEST(a == 'b');
}
int test_main(int, char *[]) {
try
{
test_different_number_of_catch_blocks();
return_type_matching();
test_empty_catch_blocks();
}
catch (int x)
{
BOOST_TEST(false);
}
catch(...)
{
BOOST_TEST(false);
}
return EXIT_SUCCESS;
}

View File

@@ -1,373 +0,0 @@
// extending_return_type_traits.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/lambda.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
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_TEST((*_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);
my_vector<int> v1; my_vector<double> v2;
my_vector<double> d = (_1 + _2)(v1, v2);
// 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;
}

View File

@@ -1,68 +0,0 @@
// is_convertible_to_template_test.cpp ----------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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_TEST((is_instance_of_1<B1, A1>::value == true));
BOOST_TEST((is_instance_of_1<A1<float>, A1>::value == true));
BOOST_TEST((is_instance_of_1<int, A1>::value == false));
BOOST_TEST((is_instance_of_1<C1, A1>::value == false));
BOOST_TEST((is_instance_of_2<B2, A2>::value == true));
BOOST_TEST((is_instance_of_2<A2<int, float>, A2>::value == true));
BOOST_TEST((is_instance_of_2<int, A2>::value == false));
BOOST_TEST((is_instance_of_2<C2, A2>::value == false));
BOOST_TEST((is_instance_of_3<B3, A3>::value == true));
BOOST_TEST((is_instance_of_3<A3<int, float, char>, A3>::value == true));
BOOST_TEST((is_instance_of_3<int, A3>::value == false));
BOOST_TEST((is_instance_of_3<C3, A3>::value == false));
BOOST_TEST((is_instance_of_4<B4, A4>::value == true));
BOOST_TEST((is_instance_of_4<A4<int, float, char, double>, A4>::value == true));
BOOST_TEST((is_instance_of_4<int, A4>::value == false));
BOOST_TEST((is_instance_of_4<C4, A4>::value == false));
return 0;
}

View File

@@ -1,181 +0,0 @@
// member_pointer_test.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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_TEST((_1 ->* &my_struct::mem)(y) == 3);
(_1 ->* &my_struct::mem)(y) = 4;
BOOST_TEST(x.mem == 4);
((_1 ->* &my_struct::mem) = 5)(y);
BOOST_TEST(x.mem == 5);
// &my_struct::mem is a temporary, must be constified
((y ->* _1) = 6)(make_const(&my_struct::mem));
BOOST_TEST(x.mem == 6);
((_1 ->* _2) = 7)(y, make_const(&my_struct::mem));
BOOST_TEST(x.mem == 7);
}
void pointer_to_member_function_tests() {
my_struct *y = new my_struct(1);
BOOST_TEST( (_1 ->* &my_struct::foo)(y)() == (y->mem));
BOOST_TEST( (_1 ->* &my_struct::fooc)(y)() == (y->mem));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo))() == (y->mem));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::fooc))() == (y->mem));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo))() == (y->mem));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::fooc))() == (y->mem));
BOOST_TEST( (_1 ->* &my_struct::foo1)(y)(1) == (y->mem+1));
BOOST_TEST( (_1 ->* &my_struct::foo1c)(y)(1) == (y->mem+1));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* &my_struct::foo2)(y)(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* &my_struct::foo2c)(y)(1,2) == (y->mem+1+2));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* &my_struct::foo3)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* &my_struct::foo3c)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* &my_struct::foo4)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* &my_struct::foo4c)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_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_TEST( (_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_TEST((_1->*_2)(a, b) == false);
// ret<bool> gives the return type
BOOST_TEST(ret<bool>(_1->*_2)(a, b) == false);
BOOST_TEST(ret<bool>(a->*_1)(b) == false);
BOOST_TEST(ret<bool>(_1->*b)(a) == false);
BOOST_TEST((ret<bool>((var(a))->*b))() == false);
BOOST_TEST((ret<bool>((var(a))->*var(b)))() == false);
// this is ok without ret<bool> due to the return_type_2 spcialization above
BOOST_TEST((_1->*_2)(b, a) == true);
BOOST_TEST((b->*_1)(a) == true);
BOOST_TEST((_1->*a)(b) == true);
BOOST_TEST((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;
}

View File

@@ -1,387 +0,0 @@
// operator_tests_simple.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.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_TEST(os.str() == std::string("10FOO"));
istringstream is("ABC 1");
std::string s;
int k;
is >> s;
is >> k;
BOOST_TEST(s == std::string("ABC"));
BOOST_TEST(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_TEST((ci)() == 5);
BOOST_TEST(i == 100);
int a;
constant_ref_type<int>::type cr(constant_ref(i));
(++vi, var(a) = cr)();
BOOST_TEST(i == 101);
#endif
}
void arithmetic_operators() {
int i = 1; int j = 2; int k = 3;
using namespace std;
using namespace boost::lambda;
BOOST_TEST((_1 + 1)(i)==2);
BOOST_TEST(((_1 + 1) * _2)(i, j)==4);
BOOST_TEST((_1 - 1)(i)==0);
BOOST_TEST((_1 * 2)(j)==4);
BOOST_TEST((_1 / 2)(j)==1);
BOOST_TEST((_1 % 2)(k)==1);
BOOST_TEST((-_1)(i) == -1);
BOOST_TEST((+_1)(i) == 1);
// test that unary plus really does something
unary_plus_tester u;
unary_plus_tester up = (+_1)(u);
}
void bitwise_operators() {
unsigned int ui = 2;
BOOST_TEST((_1 << 1)(ui)==(2 << 1));
BOOST_TEST((_1 >> 1)(ui)==(2 >> 1));
BOOST_TEST((_1 & 1)(ui)==(2 & 1));
BOOST_TEST((_1 | 1)(ui)==(2 | 1));
BOOST_TEST((_1 ^ 1)(ui)==(2 ^ 1));
BOOST_TEST((~_1)(ui)==~2u);
}
void comparison_operators() {
int i = 0, j = 1;
BOOST_TEST((_1 < _2)(i, j) == true);
BOOST_TEST((_1 <= _2)(i, j) == true);
BOOST_TEST((_1 == _2)(i, j) == false);
BOOST_TEST((_1 != _2)(i, j) == true);
BOOST_TEST((_1 > _2)(i, j) == false);
BOOST_TEST((_1 >= _2)(i, j) == false);
BOOST_TEST((!(_1 < _2))(i, j) == false);
BOOST_TEST((!(_1 <= _2))(i, j) == false);
BOOST_TEST((!(_1 == _2))(i, j) == true);
BOOST_TEST((!(_1 != _2))(i, j) == false);
BOOST_TEST((!(_1 > _2))(i, j) == true);
BOOST_TEST((!(_1 >= _2))(i, j) == true);
}
void logical_operators() {
bool t = true, f = false;
BOOST_TEST((_1 && _2)(t, t) == true);
BOOST_TEST((_1 && _2)(t, f) == false);
BOOST_TEST((_1 && _2)(f, t) == false);
BOOST_TEST((_1 && _2)(f, f) == false);
BOOST_TEST((_1 || _2)(t, t) == true);
BOOST_TEST((_1 || _2)(t, f) == true);
BOOST_TEST((_1 || _2)(f, t) == true);
BOOST_TEST((_1 || _2)(f, f) == false);
BOOST_TEST((!_1)(t) == false);
BOOST_TEST((!_1)(f) == true);
// test short circuiting
int i=0;
(false && ++_1)(i);
BOOST_TEST(i==0);
i = 0;
(true && ++_1)(i);
BOOST_TEST(i==1);
i = 0;
(false || ++_1)(i);
BOOST_TEST(i==1);
i = 0;
(true || ++_1)(i);
BOOST_TEST(i==0);
i = 0;
}
void unary_incs_and_decs() {
int i = 0;
BOOST_TEST(_1++(i) == 0);
BOOST_TEST(i == 1);
i = 0;
BOOST_TEST(_1--(i) == 0);
BOOST_TEST(i == -1);
i = 0;
BOOST_TEST((++_1)(i) == 1);
BOOST_TEST(i == 1);
i = 0;
BOOST_TEST((--_1)(i) == -1);
BOOST_TEST(i == -1);
i = 0;
// the result of prefix -- and ++ are lvalues
(++_1)(i) = 10;
BOOST_TEST(i==10);
i = 0;
(--_1)(i) = 10;
BOOST_TEST(i==10);
i = 0;
}
void compound_operators() {
int i = 1;
// normal variable as the left operand
(i += _1)(make_const(1));
BOOST_TEST(i == 2);
(i -= _1)(make_const(1));
BOOST_TEST(i == 1);
(i *= _1)(make_const(10));
BOOST_TEST(i == 10);
(i /= _1)(make_const(2));
BOOST_TEST(i == 5);
(i %= _1)(make_const(2));
BOOST_TEST(i == 1);
// lambda expression as a left operand
(_1 += 1)(i);
BOOST_TEST(i == 2);
(_1 -= 1)(i);
BOOST_TEST(i == 1);
(_1 *= 10)(i);
BOOST_TEST(i == 10);
(_1 /= 2)(i);
BOOST_TEST(i == 5);
(_1 %= 2)(i);
BOOST_TEST(i == 1);
// shifts
unsigned int ui = 2;
(_1 <<= 1)(ui);
BOOST_TEST(ui==(2 << 1));
ui = 2;
(_1 >>= 1)(ui);
BOOST_TEST(ui==(2 >> 1));
ui = 2;
(ui <<= _1)(make_const(1));
BOOST_TEST(ui==(2 << 1));
ui = 2;
(ui >>= _1)(make_const(1));
BOOST_TEST(ui==(2 >> 1));
// and, or, xor
ui = 2;
(_1 &= 1)(ui);
BOOST_TEST(ui==(2 & 1));
ui = 2;
(_1 |= 1)(ui);
BOOST_TEST(ui==(2 | 1));
ui = 2;
(_1 ^= 1)(ui);
BOOST_TEST(ui==(2 ^ 1));
ui = 2;
(ui &= _1)(make_const(1));
BOOST_TEST(ui==(2 & 1));
ui = 2;
(ui |= _1)(make_const(1));
BOOST_TEST(ui==(2 | 1));
ui = 2;
(ui ^= _1)(make_const(1));
BOOST_TEST(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_TEST(s == string("one"));
(var(s) = "two")();
BOOST_TEST(s == string("two"));
BOOST_TEST((var(s)[_1])(make_const(2)) == 'o');
BOOST_TEST((_1[2])(s) == 'o');
BOOST_TEST((_1[_2])(s, make_const(2)) == 'o');
// subscript returns lvalue
(var(s)[_1])(make_const(1)) = 'o';
BOOST_TEST(s == "too");
(_1[1])(s) = 'a';
BOOST_TEST(s == "tao");
(_1[_2])(s, make_const(0)) = 'm';
BOOST_TEST(s == "mao");
// TODO: tests for vector, set, map, multimap
}
class A {};
void address_of_and_dereference() {
A a; int i = 42;
BOOST_TEST((&_1)(a) == &a);
BOOST_TEST((*&_1)(i) == 42);
std::vector<int> vi; vi.push_back(1);
std::vector<int>::iterator it = vi.begin();
(*_1 = 7)(it);
BOOST_TEST(vi[0] == 7);
// TODO: Add tests for more complex iterator types
}
void comma() {
int i = 100;
BOOST_TEST((_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_TEST((*(_1 + 1))(ia) == 2);
// non-const pointer
BOOST_TEST((*(_1 + 1))(ip) == 2);
BOOST_TEST((*(_1 - 1))(ia_last) == 3);
// const array
BOOST_TEST((*(_1 + 1))(cia) == 2);
// const pointer
BOOST_TEST((*(_1 + 1))(cip) == 2);
BOOST_TEST((*(_1 - 1))(cia_last) == 3);
// pointer arithmetic should not make non-consts const
(*(_1 + 2))(ia) = 0;
(*(_1 + 3))(ip) = 0;
BOOST_TEST(ia[2] == 0);
BOOST_TEST(ia[3] == 0);
// pointer - pointer
BOOST_TEST((_1 - _2)(ia_last, ia) == 3);
BOOST_TEST((_1 - _2)(cia_last, cia) == 3);
BOOST_TEST((ia_last - _1)(ia) == 3);
BOOST_TEST((cia_last - _1)(cia) == 3);
BOOST_TEST((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;
}

View File

@@ -1,139 +0,0 @@
// phoenix_style_control_structures.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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 tatements
//
///////////////////////////////////////////////////////////////////////////////
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_TEST(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_TEST(lt==4);
BOOST_TEST(eq==1);
BOOST_TEST(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_TEST(counta == 55);
BOOST_TEST(countb == 10);
v = t;
counta = 0; countb = 0;
//////////////////////////////////
for_each(v.begin(), v.end(),
(
do_
[
++var(counta)
]
.while_(_1--),
++var(countb)
)
);
BOOST_TEST(counta == (2+11)*10/2);
BOOST_TEST(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_TEST(counta == (1+10)*10/2);
BOOST_TEST(countb == 10);
v = t;
return 0;
}

View File

@@ -1,381 +0,0 @@
// switch_test.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(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_TEST(check(w, -1));
BOOST_TEST(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_TEST(check(w, 0));
BOOST_TEST(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_TEST(check(w, 1));
BOOST_TEST(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_TEST(check(w, 2));
BOOST_TEST(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_TEST(check(w, 3));
BOOST_TEST(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_TEST(check(w, 4));
BOOST_TEST(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_TEST(check(w, 5));
BOOST_TEST(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_TEST(check(w, 6));
BOOST_TEST(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_TEST(check(w, 7));
BOOST_TEST(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;
}