[12] | 1 | <?xml version="1.0" encoding="ISO-Latin-1"?> |
---|
| 2 | <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" |
---|
| 3 | "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> |
---|
| 4 | <library name="Lambda" dirname="lambda" id="lambda" |
---|
| 5 | last-revision="$Date: 2004/11/28 03:29:16 $" |
---|
| 6 | xmlns:xi="http://www.w3.org/2001/XInclude"> |
---|
| 7 | <libraryinfo> |
---|
| 8 | <author> |
---|
| 9 | <firstname>Jaakko</firstname> |
---|
| 10 | <surname>Järvi</surname> |
---|
| 11 | <email>jarvi at cs tamu edu</email> |
---|
| 12 | </author> |
---|
| 13 | |
---|
| 14 | <copyright> |
---|
| 15 | <year>1999</year> |
---|
| 16 | <year>2000</year> |
---|
| 17 | <year>2001</year> |
---|
| 18 | <year>2002</year> |
---|
| 19 | <year>2003</year> |
---|
| 20 | <year>2004</year> |
---|
| 21 | <holder>Jaakko Järvi</holder> |
---|
| 22 | <holder>Gary Powell</holder> |
---|
| 23 | </copyright> |
---|
| 24 | |
---|
| 25 | <legalnotice> |
---|
| 26 | <para>Use, modification and distribution is subject to the Boost |
---|
| 27 | Software License, Version 1.0. (See accompanying file |
---|
| 28 | <filename>LICENSE_1_0.txt</filename> or copy at <ulink |
---|
| 29 | url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)</para> |
---|
| 30 | </legalnotice> |
---|
| 31 | |
---|
| 32 | <librarypurpose>Define small unnamed function objects at the actual call site, and more</librarypurpose> |
---|
| 33 | <librarycategory name="category:higher-order"/> |
---|
| 34 | </libraryinfo> |
---|
| 35 | |
---|
| 36 | <title>Boost.Lambda</title> |
---|
| 37 | |
---|
| 38 | <!-- --> |
---|
| 39 | |
---|
| 40 | <section id="introduction"> |
---|
| 41 | |
---|
| 42 | <title>In a nutshell</title> |
---|
| 43 | |
---|
| 44 | <para> |
---|
| 45 | |
---|
| 46 | The Boost Lambda Library (BLL in the sequel) is a C++ template |
---|
| 47 | library, which implements form of <emphasis>lambda abstractions</emphasis> for C++. |
---|
| 48 | The term originates from functional programming and lambda calculus, where a lambda abstraction defines an unnamed function. |
---|
| 49 | The primary motivation for the BLL is to provide flexible and |
---|
| 50 | convenient means to define unnamed function objects for STL algorithms. |
---|
| 51 | In explaining what the library is about, a line of code says more than a thousand words; the |
---|
| 52 | following line outputs the elements of some STL container |
---|
| 53 | <literal>a</literal> separated by spaces: |
---|
| 54 | |
---|
| 55 | <programlisting><![CDATA[for_each(a.begin(), a.end(), std::cout << _1 << ' ');]]></programlisting> |
---|
| 56 | |
---|
| 57 | The expression <literal><![CDATA[std::cout << _1 << ' ']]></literal> defines a unary function object. |
---|
| 58 | The variable <literal>_1</literal> is the parameter of this function, a <emphasis>placeholder</emphasis> for the actual argument. |
---|
| 59 | Within each iteration of <literal>for_each</literal>, the function is |
---|
| 60 | called with an element of <literal>a</literal> as the actual argument. |
---|
| 61 | This actual argument is substituted for the placeholder, and the <quote>body</quote> of the function is evaluated. |
---|
| 62 | </para> |
---|
| 63 | |
---|
| 64 | <para>The essence of BLL is letting you define small unnamed function objects, such as the one above, directly on the call site of an STL algorithm. |
---|
| 65 | </para> |
---|
| 66 | </section> |
---|
| 67 | |
---|
| 68 | <section id="lambda.getting_started"> |
---|
| 69 | <title>Getting Started</title> |
---|
| 70 | |
---|
| 71 | <section> |
---|
| 72 | <title>Installing the library</title> |
---|
| 73 | |
---|
| 74 | |
---|
| 75 | <para> |
---|
| 76 | The library consists of include files only, hence there is no |
---|
| 77 | installation procedure. The <literal>boost</literal> include directory |
---|
| 78 | must be on the include path. |
---|
| 79 | There are a number of include files that give different functionality: |
---|
| 80 | |
---|
| 81 | <!-- TODO: tarkista vielä riippuvuudet--> |
---|
| 82 | <itemizedlist> |
---|
| 83 | |
---|
| 84 | <listitem><para> |
---|
| 85 | <filename>lambda/lambda.hpp</filename> defines lambda expressions for different C++ |
---|
| 86 | operators, see <xref linkend="lambda.operator_expressions"/>. |
---|
| 87 | </para></listitem> |
---|
| 88 | |
---|
| 89 | <listitem><para> |
---|
| 90 | <filename>lambda/bind.hpp</filename> defines <literal>bind</literal> functions for up to 9 arguments, see <xref linkend="lambda.bind_expressions"/>.</para></listitem> |
---|
| 91 | |
---|
| 92 | |
---|
| 93 | <listitem><para> |
---|
| 94 | <filename>lambda/if.hpp</filename> defines lambda function equivalents for if statements and the conditional operator, see <xref linkend="lambda.lambda_expressions_for_control_structures"/> (includes <filename>lambda.hpp</filename>). |
---|
| 95 | </para></listitem> |
---|
| 96 | |
---|
| 97 | <listitem><para> |
---|
| 98 | <filename>lambda/loops.hpp</filename> defines lambda function equivalent for looping constructs, see <xref linkend="lambda.lambda_expressions_for_control_structures"/>. |
---|
| 99 | </para></listitem> |
---|
| 100 | |
---|
| 101 | <listitem><para> |
---|
| 102 | <filename>lambda/switch.hpp</filename> defines lambda function equivalent for the switch statement, see <xref linkend="lambda.lambda_expressions_for_control_structures"/>. |
---|
| 103 | </para></listitem> |
---|
| 104 | |
---|
| 105 | <listitem><para> |
---|
| 106 | <filename>lambda/construct.hpp</filename> provides tools for writing lambda expressions with constructor, destructor, new and delete invocations, see <xref linkend="lambda.construction_and_destruction"/> (includes <filename>lambda.hpp</filename>). |
---|
| 107 | </para></listitem> |
---|
| 108 | |
---|
| 109 | <listitem><para> |
---|
| 110 | <filename>lambda/casts.hpp</filename> provides lambda versions of different casts, as well as <literal>sizeof</literal> and <literal>typeid</literal>, see <xref linkend="lambda.cast_expressions"/>. |
---|
| 111 | </para></listitem> |
---|
| 112 | |
---|
| 113 | <listitem><para> |
---|
| 114 | <filename>lambda/exceptions.hpp</filename> gives tools for throwing and catching |
---|
| 115 | exceptions within lambda functions, <xref linkend="lambda.exceptions"/> (includes |
---|
| 116 | <filename>lambda.hpp</filename>). |
---|
| 117 | </para></listitem> |
---|
| 118 | |
---|
| 119 | <listitem><para> |
---|
| 120 | <filename>lambda/algorithm.hpp</filename> and <filename>lambda/numeric.hpp</filename> (cf. standard <filename>algortihm</filename> and <filename>numeric</filename> headers) allow nested STL algorithm invocations, see <xref linkend="lambda.nested_stl_algorithms"/>. |
---|
| 121 | </para></listitem> |
---|
| 122 | |
---|
| 123 | </itemizedlist> |
---|
| 124 | |
---|
| 125 | Any other header files in the package are for internal use. |
---|
| 126 | Additionally, the library depends on two other Boost Libraries, the |
---|
| 127 | <emphasis>Tuple</emphasis> <xref linkend="cit:boost::tuple"/> and the <emphasis>type_traits</emphasis> <xref linkend="cit:boost::type_traits"/> libraries, and on the <filename>boost/ref.hpp</filename> header. |
---|
| 128 | </para> |
---|
| 129 | |
---|
| 130 | <para> |
---|
| 131 | All definitions are placed in the namespace <literal>boost::lambda</literal> and its subnamespaces. |
---|
| 132 | </para> |
---|
| 133 | |
---|
| 134 | </section> |
---|
| 135 | |
---|
| 136 | <section> |
---|
| 137 | <title>Conventions used in this document</title> |
---|
| 138 | |
---|
| 139 | <para>In most code examples, we omit the namespace prefixes for names in the <literal moreinfo="none">std</literal> and <literal moreinfo="none">boost::lambda</literal> namespaces. |
---|
| 140 | Implicit using declarations |
---|
| 141 | <programlisting> |
---|
| 142 | using namespace std; |
---|
| 143 | using namespace boost::lambda; |
---|
| 144 | </programlisting> |
---|
| 145 | are assumed to be in effect. |
---|
| 146 | </para> |
---|
| 147 | |
---|
| 148 | </section> |
---|
| 149 | </section> |
---|
| 150 | |
---|
| 151 | <section> |
---|
| 152 | <title>Introduction</title> |
---|
| 153 | |
---|
| 154 | <section> |
---|
| 155 | <title>Motivation</title> |
---|
| 156 | <para>The Standard Template Library (STL) |
---|
| 157 | <xref role="citation" linkend="cit:stepanov:94"/>, now part of the C++ Standard Library <xref role="citation" linkend="cit:c++:98"/>, is a generic container and algorithm library. |
---|
| 158 | Typically STL algorithms operate on container elements via <emphasis>function objects</emphasis>. These function objects are passed as arguments to the algorithms. |
---|
| 159 | </para> |
---|
| 160 | |
---|
| 161 | <para> |
---|
| 162 | Any C++ construct that can be called with the function call syntax |
---|
| 163 | is a function object. |
---|
| 164 | The STL contains predefined function objects for some common cases (such as <literal>plus</literal>, <literal>less</literal> and <literal>not1</literal>). |
---|
| 165 | As an example, one possible implementation for the standard <literal>plus</literal> template is: |
---|
| 166 | |
---|
| 167 | <programlisting> |
---|
| 168 | <![CDATA[template <class T> : public binary_function<T, T, T> |
---|
| 169 | struct plus { |
---|
| 170 | T operator()(const T& i, const T& j) const { |
---|
| 171 | return i + j; |
---|
| 172 | } |
---|
| 173 | };]]> |
---|
| 174 | </programlisting> |
---|
| 175 | |
---|
| 176 | The base class <literal><![CDATA[binary_function<T, T, T>]]></literal> contains typedefs for the argument and return types of the function object, which are needed to make the function object <emphasis>adaptable</emphasis>. |
---|
| 177 | </para> |
---|
| 178 | |
---|
| 179 | <para> |
---|
| 180 | In addition to the basic function object classes, such as the one above, |
---|
| 181 | the STL contains <emphasis>binder</emphasis> templates for creating a unary function object from an adaptable binary function object by fixing one of the arguments to a constant value. |
---|
| 182 | For example, instead of having to explicitly write a function object class like: |
---|
| 183 | |
---|
| 184 | <programlisting> |
---|
| 185 | <![CDATA[class plus_1 { |
---|
| 186 | int _i; |
---|
| 187 | public: |
---|
| 188 | plus_1(const int& i) : _i(i) {} |
---|
| 189 | int operator()(const int& j) { return _i + j; } |
---|
| 190 | };]]> |
---|
| 191 | </programlisting> |
---|
| 192 | |
---|
| 193 | the equivalent functionality can be achieved with the <literal moreinfo="none">plus</literal> template and one of the binder templates (<literal moreinfo="none">bind1st</literal>). |
---|
| 194 | E.g., the following two expressions create function objects with identical functionalities; |
---|
| 195 | when invoked, both return the result of adding <literal moreinfo="none">1</literal> to the argument of the function object: |
---|
| 196 | |
---|
| 197 | <programlisting> |
---|
| 198 | <![CDATA[plus_1(1) |
---|
| 199 | bind1st(plus<int>(), 1)]]> |
---|
| 200 | </programlisting> |
---|
| 201 | |
---|
| 202 | The subexpression <literal><![CDATA[plus<int>()]]></literal> in the latter line is a binary function object which computes the sum of two integers, and <literal>bind1st</literal> invokes this function object partially binding the first argument to <literal>1</literal>. |
---|
| 203 | As an example of using the above function object, the following code adds <literal>1</literal> to each element of some container <literal>a</literal> and outputs the results into the standard output stream <literal>cout</literal>. |
---|
| 204 | |
---|
| 205 | <programlisting> |
---|
| 206 | <![CDATA[transform(a.begin(), a.end(), ostream_iterator<int>(cout), |
---|
| 207 | bind1st(plus<int>(), 1));]]> |
---|
| 208 | </programlisting> |
---|
| 209 | |
---|
| 210 | </para> |
---|
| 211 | |
---|
| 212 | <para> |
---|
| 213 | To make the binder templates more generally applicable, the STL contains <emphasis>adaptors</emphasis> for making |
---|
| 214 | pointers or references to functions, and pointers to member functions, |
---|
| 215 | adaptable. |
---|
| 216 | |
---|
| 217 | Finally, some STL implementations contain function composition operations as |
---|
| 218 | extensions to the standard <xref linkend="cit:sgi:02"/>. |
---|
| 219 | </para> |
---|
| 220 | |
---|
| 221 | <para> |
---|
| 222 | All these tools aim at one goal: to make it possible to specify |
---|
| 223 | <emphasis>unnamed functions</emphasis> in a call of an STL algorithm, |
---|
| 224 | in other words, to pass code fragments as an argument to a function. |
---|
| 225 | |
---|
| 226 | However, this goal is attained only partially. |
---|
| 227 | The simple example above shows that the definition of unnamed functions |
---|
| 228 | with the standard tools is cumbersome. |
---|
| 229 | |
---|
| 230 | Complex expressions involving functors, adaptors, binders and |
---|
| 231 | function composition operations tend to be difficult to comprehend. |
---|
| 232 | |
---|
| 233 | In addition to this, there are significant restrictions in applying |
---|
| 234 | the standard tools. E.g. the standard binders allow only one argument |
---|
| 235 | of a binary function to be bound; there are no binders for |
---|
| 236 | 3-ary, 4-ary etc. functions. |
---|
| 237 | </para> |
---|
| 238 | |
---|
| 239 | <para> |
---|
| 240 | The Boost Lambda Library provides solutions for the problems described above: |
---|
| 241 | |
---|
| 242 | <itemizedlist> |
---|
| 243 | <listitem> |
---|
| 244 | <para> |
---|
| 245 | Unnamed functions can be created easily with an intuitive syntax. |
---|
| 246 | |
---|
| 247 | The above example can be written as: |
---|
| 248 | |
---|
| 249 | <programlisting> |
---|
| 250 | <![CDATA[transform(a.begin(), a.end(), ostream_iterator<int>(cout), |
---|
| 251 | 1 + _1);]]> |
---|
| 252 | </programlisting> |
---|
| 253 | |
---|
| 254 | or even more intuitively: |
---|
| 255 | |
---|
| 256 | <programlisting> |
---|
| 257 | <![CDATA[for_each(a.begin(), a.end(), cout << (1 + _1));]]> |
---|
| 258 | </programlisting> |
---|
| 259 | </para> |
---|
| 260 | |
---|
| 261 | </listitem> |
---|
| 262 | |
---|
| 263 | <listitem> |
---|
| 264 | <para> |
---|
| 265 | Most of the restrictions in argument binding are removed, |
---|
| 266 | arbitrary arguments of practically any C++ function can be bound. |
---|
| 267 | </para> |
---|
| 268 | </listitem> |
---|
| 269 | |
---|
| 270 | <listitem> |
---|
| 271 | <para> |
---|
| 272 | Separate function composition operations are not needed, |
---|
| 273 | as function composition is supported implicitly. |
---|
| 274 | |
---|
| 275 | </para> |
---|
| 276 | </listitem> |
---|
| 277 | |
---|
| 278 | </itemizedlist> |
---|
| 279 | |
---|
| 280 | </para> |
---|
| 281 | |
---|
| 282 | </section> |
---|
| 283 | |
---|
| 284 | |
---|
| 285 | |
---|
| 286 | <section> |
---|
| 287 | <title>Introduction to lambda expressions</title> |
---|
| 288 | |
---|
| 289 | <para> |
---|
| 290 | Lambda expression are common in functional programming languages. |
---|
| 291 | Their syntax varies between languages (and between different forms of lambda calculus), but the basic form of a lambda expressions is: |
---|
| 292 | |
---|
| 293 | |
---|
| 294 | <programlisting> |
---|
| 295 | lambda x<subscript>1</subscript> ... x<subscript>n</subscript>.e |
---|
| 296 | </programlisting> |
---|
| 297 | <!-- $\lambda x_1 \cdots x_n . e$ --> |
---|
| 298 | |
---|
| 299 | A lambda expression defines an unnamed function and consists of: |
---|
| 300 | <itemizedlist> |
---|
| 301 | <listitem> |
---|
| 302 | <para> |
---|
| 303 | the parameters of this function: <literal>x<subscript>1</subscript> ... x<subscript>n</subscript></literal>. |
---|
| 304 | <!--$x_1 \cdots x_n$--> |
---|
| 305 | </para> |
---|
| 306 | </listitem> |
---|
| 307 | <listitem> |
---|
| 308 | <para>the expression e which computes the value of the function in terms of the parameters <literal>x<subscript>1</subscript> ... x<subscript>n</subscript></literal>. |
---|
| 309 | </para> |
---|
| 310 | </listitem> |
---|
| 311 | </itemizedlist> |
---|
| 312 | |
---|
| 313 | A simple example of a lambda expression is |
---|
| 314 | <programlisting> |
---|
| 315 | lambda x y.x+y |
---|
| 316 | </programlisting> |
---|
| 317 | Applying the lambda function means substituting the formal parameters with the actual arguments: |
---|
| 318 | <programlisting> |
---|
| 319 | (lambda x y.x+y) 2 3 = 2 + 3 = 5 |
---|
| 320 | </programlisting> |
---|
| 321 | |
---|
| 322 | |
---|
| 323 | </para> |
---|
| 324 | |
---|
| 325 | <para> |
---|
| 326 | In the C++ version of lambda expressions the <literal>lambda x<subscript>1</subscript> ... x<subscript>n</subscript></literal> part is missing and the formal parameters have predefined names. |
---|
| 327 | In the current version of the library, |
---|
| 328 | there are three such predefined formal parameters, |
---|
| 329 | called <emphasis>placeholders</emphasis>: |
---|
| 330 | <literal>_1</literal>, <literal>_2</literal> and <literal>_3</literal>. |
---|
| 331 | They refer to the first, second and third argument of the function defined |
---|
| 332 | by the lambda expression. |
---|
| 333 | |
---|
| 334 | For example, the C++ version of the definition |
---|
| 335 | <programlisting>lambda x y.x+y</programlisting> |
---|
| 336 | is |
---|
| 337 | <programlisting>_1 + _2</programlisting> |
---|
| 338 | </para> |
---|
| 339 | |
---|
| 340 | <para> |
---|
| 341 | Hence, there is no syntactic keyword for C++ lambda expressions. |
---|
| 342 | The use of a placeholder as an operand implies that the operator invocation is a lambda expression. |
---|
| 343 | However, this is true only for operator invocations. |
---|
| 344 | Lambda expressions containing function calls, control structures, casts etc. require special syntactic constructs. |
---|
| 345 | Most importantly, function calls need to be wrapped inside a <literal>bind</literal> function. |
---|
| 346 | |
---|
| 347 | As an example, consider the lambda expression: |
---|
| 348 | |
---|
| 349 | <programlisting>lambda x y.foo(x,y)</programlisting> |
---|
| 350 | |
---|
| 351 | Rather than <literal>foo(_1, _2)</literal>, the C++ counterpart for this expression is: |
---|
| 352 | |
---|
| 353 | <programlisting>bind(foo, _1, _2)</programlisting> |
---|
| 354 | |
---|
| 355 | We refer to this type of C++ lambda expressions as <emphasis>bind expressions</emphasis>. |
---|
| 356 | </para> |
---|
| 357 | |
---|
| 358 | <para>A lambda expression defines a C++ function object, hence function application syntax is like calling any other function object, for instance: <literal>(_1 + _2)(i, j)</literal>. |
---|
| 359 | |
---|
| 360 | |
---|
| 361 | </para> |
---|
| 362 | |
---|
| 363 | |
---|
| 364 | |
---|
| 365 | <section id="lambda.partial_function_application"> |
---|
| 366 | <title>Partial function application</title> |
---|
| 367 | |
---|
| 368 | <para> |
---|
| 369 | A bind expression is in effect a <emphasis>partial function application</emphasis>. |
---|
| 370 | In partial function application, some of the arguments of a function are bound to fixed values. |
---|
| 371 | The result is another function, with possibly fewer arguments. |
---|
| 372 | When called with the unbound arguments, this new function invokes the original function with the merged argument list of bound and unbound arguments. |
---|
| 373 | </para> |
---|
| 374 | |
---|
| 375 | <!-- <para>The underlying implementation of the BLL unifies the two types of lambda expressions (bind expressions and lambda expressions consisting of operator calls). |
---|
| 376 | If operators are regarded as functions, it is easy to see that lambda expressions using operators are partial function applications as well. |
---|
| 377 | E.g. the lambda expression <literal>_1 + 1</literal> can be seen as syntactic sugar for the pseudo code <literal>bind(operator+, _1, 1)</literal>. |
---|
| 378 | </para> |
---|
| 379 | --> |
---|
| 380 | |
---|
| 381 | </section> |
---|
| 382 | |
---|
| 383 | |
---|
| 384 | |
---|
| 385 | <section id="lambda.terminology"> |
---|
| 386 | <title>Terminology</title> |
---|
| 387 | |
---|
| 388 | <para> |
---|
| 389 | A lambda expression defines a function. A C++ lambda expression concretely constructs a function object, <emphasis>a functor</emphasis>, when evaluated. We use the name <emphasis>lambda functor</emphasis> to refer to such a function object. |
---|
| 390 | Hence, in the terminology adopted here, the result of evaluating a lambda expression is a lambda functor. |
---|
| 391 | </para> |
---|
| 392 | |
---|
| 393 | </section> |
---|
| 394 | |
---|
| 395 | </section> |
---|
| 396 | |
---|
| 397 | |
---|
| 398 | |
---|
| 399 | </section> |
---|
| 400 | |
---|
| 401 | <section id = "lambda.using_library"> |
---|
| 402 | <title>Using the library</title> |
---|
| 403 | |
---|
| 404 | <para> |
---|
| 405 | The purpose of this section is to introduce the basic functionality of the library. |
---|
| 406 | There are quite a lot of exceptions and special cases, but discussion of them is postponed until later sections. |
---|
| 407 | |
---|
| 408 | |
---|
| 409 | </para> |
---|
| 410 | |
---|
| 411 | <section id = "lambda.introductory_examples"> |
---|
| 412 | <title>Introductory Examples</title> |
---|
| 413 | |
---|
| 414 | <para> |
---|
| 415 | In this section we give basic examples of using BLL lambda expressions in STL algorithm invocations. |
---|
| 416 | We start with some simple expressions and work up. |
---|
| 417 | First, we initialize the elements of a container, say, a <literal>list</literal>, to the value <literal>1</literal>: |
---|
| 418 | |
---|
| 419 | |
---|
| 420 | <programlisting> |
---|
| 421 | <![CDATA[list<int> v(10); |
---|
| 422 | for_each(v.begin(), v.end(), _1 = 1);]]></programlisting> |
---|
| 423 | |
---|
| 424 | The expression <literal>_1 = 1</literal> creates a lambda functor which assigns the value <literal>1</literal> to every element in <literal>v</literal>.<footnote> |
---|
| 425 | <para> |
---|
| 426 | Strictly taken, the C++ standard defines <literal>for_each</literal> as a <emphasis>non-modifying sequence operation</emphasis>, and the function object passed to <literal moreinfo="none">for_each</literal> should not modify its argument. |
---|
| 427 | The requirements for the arguments of <literal>for_each</literal> are unnecessary strict, since as long as the iterators are <emphasis>mutable</emphasis>, <literal>for_each</literal> accepts a function object that can have side-effects on their argument. |
---|
| 428 | Nevertheless, it is straightforward to provide another function template with the functionality of<literal>std::for_each</literal> but more fine-grained requirements for its arguments. |
---|
| 429 | </para> |
---|
| 430 | </footnote> |
---|
| 431 | </para> |
---|
| 432 | |
---|
| 433 | <para> |
---|
| 434 | Next, we create a container of pointers and make them point to the elements in the first container <literal>v</literal>: |
---|
| 435 | |
---|
| 436 | <programlisting> |
---|
| 437 | <![CDATA[vector<int*> vp(10); |
---|
| 438 | transform(v.begin(), v.end(), vp.begin(), &_1);]]></programlisting> |
---|
| 439 | |
---|
| 440 | The expression <literal><![CDATA[&_1]]></literal> creates a function object for getting the address of each element in <literal>v</literal>. |
---|
| 441 | The addresses get assigned to the corresponding elements in <literal>vp</literal>. |
---|
| 442 | </para> |
---|
| 443 | |
---|
| 444 | <para> |
---|
| 445 | The next code fragment changes the values in <literal>v</literal>. |
---|
| 446 | For each element, the function <literal>foo</literal> is called. |
---|
| 447 | The original value of the element is passed as an argument to <literal>foo</literal>. |
---|
| 448 | The result of <literal>foo</literal> is assigned back to the element: |
---|
| 449 | |
---|
| 450 | |
---|
| 451 | <programlisting> |
---|
| 452 | <![CDATA[int foo(int); |
---|
| 453 | for_each(v.begin(), v.end(), _1 = bind(foo, _1));]]></programlisting> |
---|
| 454 | </para> |
---|
| 455 | |
---|
| 456 | |
---|
| 457 | <para> |
---|
| 458 | The next step is to sort the elements of <literal>vp</literal>: |
---|
| 459 | |
---|
| 460 | <programlisting>sort(vp.begin(), vp.end(), *_1 > *_2);</programlisting> |
---|
| 461 | |
---|
| 462 | In this call to <literal>sort</literal>, we are sorting the elements by their contents in descending order. |
---|
| 463 | </para> |
---|
| 464 | |
---|
| 465 | <para> |
---|
| 466 | Finally, the following <literal>for_each</literal> call outputs the sorted content of <literal>vp</literal> separated by line breaks: |
---|
| 467 | |
---|
| 468 | <programlisting> |
---|
| 469 | <![CDATA[for_each(vp.begin(), vp.end(), cout << *_1 << '\n');]]> |
---|
| 470 | </programlisting> |
---|
| 471 | |
---|
| 472 | Note that a normal (non-lambda) expression as subexpression of a lambda expression is evaluated immediately. |
---|
| 473 | This may cause surprises. |
---|
| 474 | For instance, if the previous example is rewritten as |
---|
| 475 | <programlisting> |
---|
| 476 | <![CDATA[for_each(vp.begin(), vp.end(), cout << '\n' << *_1);]]> |
---|
| 477 | </programlisting> |
---|
| 478 | the subexpression <literal><![CDATA[cout << '\n']]></literal> is evaluated immediately and the effect is to output a single line break, followed by the elements of <literal>vp</literal>. |
---|
| 479 | The BLL provides functions <literal>constant</literal> and <literal>var</literal> to turn constants and, respectively, variables into lambda expressions, and can be used to prevent the immediate evaluation of subexpressions: |
---|
| 480 | <programlisting> |
---|
| 481 | <![CDATA[for_each(vp.begin(), vp.end(), cout << constant('\n') << *_1);]]> |
---|
| 482 | </programlisting> |
---|
| 483 | These functions are described more thoroughly in <xref linkend="lambda.delaying_constants_and_variables"/> |
---|
| 484 | |
---|
| 485 | </para> |
---|
| 486 | |
---|
| 487 | |
---|
| 488 | |
---|
| 489 | |
---|
| 490 | |
---|
| 491 | </section> |
---|
| 492 | |
---|
| 493 | |
---|
| 494 | <section id="lambda.parameter_and_return_types"> |
---|
| 495 | <title>Parameter and return types of lambda functors</title> |
---|
| 496 | |
---|
| 497 | <para> |
---|
| 498 | During the invocation of a lambda functor, the actual arguments are substituted for the placeholders. |
---|
| 499 | The placeholders do not dictate the type of these actual arguments. |
---|
| 500 | 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. |
---|
| 501 | As an example, the expression |
---|
| 502 | <literal>_1 + _2</literal> creates a binary lambda functor. |
---|
| 503 | It can be called with two objects of any types <literal>A</literal> and <literal>B</literal> for which <literal>operator+(A,B)</literal> is defined (and for which BLL knows the return type of the operator, see below). |
---|
| 504 | </para> |
---|
| 505 | |
---|
| 506 | <para> |
---|
| 507 | C++ lacks a mechanism to query a type of an expression. |
---|
| 508 | However, this precise mechanism is crucial for the implementation of C++ lambda expressions. |
---|
| 509 | Consequently, BLL includes a somewhat complex type deduction system which uses a set of traits classes for deducing the resulting type of lambda functions. |
---|
| 510 | It handles expressions where the operands are of built-in types and many of the expressions with operands of standard library types. |
---|
| 511 | Many of the user defined types are covered as well, particularly if the user defined operators obey normal conventions in defining the return types. |
---|
| 512 | </para> |
---|
| 513 | |
---|
| 514 | <!-- TODO: move this forward, and just refer to it. --> |
---|
| 515 | <para> |
---|
| 516 | There are, however, cases when the return type cannot be deduced. For example, suppose you have defined: |
---|
| 517 | |
---|
| 518 | <programlisting>C operator+(A, B);</programlisting> |
---|
| 519 | |
---|
| 520 | The following lambda function invocation fails, since the return type cannot be deduced: |
---|
| 521 | |
---|
| 522 | <programlisting>A a; B b; (_1 + _2)(a, b);</programlisting> |
---|
| 523 | </para> |
---|
| 524 | |
---|
| 525 | <para> |
---|
| 526 | There are two alternative solutions to this. |
---|
| 527 | The first is to extend the BLL type deduction system to cover your own types (see <xref linkend="lambda.extending"/>). |
---|
| 528 | The second is to use a special lambda expression (<literal>ret</literal>) which defines the return type in place (see <xref linkend = "lambda.overriding_deduced_return_type"/>): |
---|
| 529 | |
---|
| 530 | <programlisting><![CDATA[A a; B b; ret<C>(_1 + _2)(a, b);]]></programlisting> |
---|
| 531 | </para> |
---|
| 532 | |
---|
| 533 | <para> |
---|
| 534 | For bind expressions, the return type can be defined as a template argument of the bind function as well: |
---|
| 535 | <programlisting><![CDATA[bind<int>(foo, _1, _2);]]></programlisting> |
---|
| 536 | |
---|
| 537 | <!-- |
---|
| 538 | A rare case, where the <literal><![CDATA[ret<type>(bind(...))]]></literal> syntax does not work, but |
---|
| 539 | <literal><![CDATA[bind<type>(...)]]></literal> does, is explained in <xref linkend="lambda.nullary_functors_and_ret"/>. |
---|
| 540 | --> |
---|
| 541 | </para> |
---|
| 542 | </section> |
---|
| 543 | |
---|
| 544 | <section id="lambda.actual_arguments_to_lambda_functors"> |
---|
| 545 | <title>About actual arguments to lambda functors</title> |
---|
| 546 | |
---|
| 547 | <!-- <para><emphasis>This section is no longer (or currently) relevant; |
---|
| 548 | acual arguments can be non-const rvalues. |
---|
| 549 | The section can, however, become relevant again, if in the future BLL will support |
---|
| 550 | lambda functors with higher arities than 3.</emphasis></para> --> |
---|
| 551 | |
---|
| 552 | <para>A general restriction for the actual arguments is that they cannot be non-const rvalues. |
---|
| 553 | For example: |
---|
| 554 | |
---|
| 555 | <programlisting> |
---|
| 556 | int i = 1; int j = 2; |
---|
| 557 | (_1 + _2)(i, j); // ok |
---|
| 558 | (_1 + _2)(1, 2); // error (!) |
---|
| 559 | </programlisting> |
---|
| 560 | |
---|
| 561 | This restriction is not as bad as it may look. |
---|
| 562 | Since the lambda functors are most often called inside STL-algorithms, |
---|
| 563 | the arguments originate from dereferencing iterators and the dereferencing operators seldom return rvalues. |
---|
| 564 | And for the cases where they do, there are workarounds discussed in |
---|
| 565 | <xref linkend="lambda.rvalues_as_actual_arguments"/>. |
---|
| 566 | |
---|
| 567 | |
---|
| 568 | </para> |
---|
| 569 | |
---|
| 570 | </section> |
---|
| 571 | |
---|
| 572 | |
---|
| 573 | <section id="lambda.storing_bound_arguments"> |
---|
| 574 | |
---|
| 575 | <title>Storing bound arguments in lambda functions</title> |
---|
| 576 | |
---|
| 577 | <para> |
---|
| 578 | |
---|
| 579 | By default, temporary const copies of the bound arguments are stored |
---|
| 580 | in the lambda functor. |
---|
| 581 | |
---|
| 582 | This means that the value of a bound argument is fixed at the time of the |
---|
| 583 | creation of the lambda function and remains constant during the lifetime |
---|
| 584 | of the lambda function object. |
---|
| 585 | For example: |
---|
| 586 | <programlisting> |
---|
| 587 | int i = 1; |
---|
| 588 | (_1 = 2, _1 + i)(i); |
---|
| 589 | </programlisting> |
---|
| 590 | The comma operator is overloaded to combine lambda expressions into a sequence; |
---|
| 591 | the resulting unary lambda functor first assigns 2 to its argument, |
---|
| 592 | then adds the value of <literal>i</literal> to it. |
---|
| 593 | The value of the expression in the last line is 3, not 4. |
---|
| 594 | In other words, the lambda expression that is created is |
---|
| 595 | <literal>lambda x.(x = 2, x + 1)</literal> rather than |
---|
| 596 | <literal>lambda x.(x = 2, x + i)</literal>. |
---|
| 597 | |
---|
| 598 | </para> |
---|
| 599 | |
---|
| 600 | <para> |
---|
| 601 | |
---|
| 602 | As said, this is the default behavior for which there are exceptions. |
---|
| 603 | The exact rules are as follows: |
---|
| 604 | |
---|
| 605 | <itemizedlist> |
---|
| 606 | |
---|
| 607 | <listitem> |
---|
| 608 | |
---|
| 609 | <para> |
---|
| 610 | |
---|
| 611 | The programmer can control the storing mechanism with <literal>ref</literal> |
---|
| 612 | and <literal>cref</literal> wrappers <xref linkend="cit:boost::ref"/>. |
---|
| 613 | |
---|
| 614 | Wrapping an argument with <literal>ref</literal>, or <literal>cref</literal>, |
---|
| 615 | instructs the library to store the argument as a reference, |
---|
| 616 | or as a reference to const respectively. |
---|
| 617 | |
---|
| 618 | For example, if we rewrite the previous example and wrap the variable |
---|
| 619 | <literal>i</literal> with <literal>ref</literal>, |
---|
| 620 | we are creating the lambda expression <literal>lambda x.(x = 2, x + i)</literal> |
---|
| 621 | and the value of the expression in the last line will be 4: |
---|
| 622 | |
---|
| 623 | <programlisting> |
---|
| 624 | i = 1; |
---|
| 625 | (_1 = 2, _1 + ref(i))(i); |
---|
| 626 | </programlisting> |
---|
| 627 | |
---|
| 628 | Note that <literal>ref</literal> and <literal>cref</literal> are different |
---|
| 629 | from <literal>var</literal> and <literal>constant</literal>. |
---|
| 630 | |
---|
| 631 | While the latter ones create lambda functors, the former do not. |
---|
| 632 | For example: |
---|
| 633 | |
---|
| 634 | <programlisting> |
---|
| 635 | int i; |
---|
| 636 | var(i) = 1; // ok |
---|
| 637 | ref(i) = 1; // not ok, ref(i) is not a lambda functor |
---|
| 638 | </programlisting> |
---|
| 639 | |
---|
| 640 | The functions <literal>ref</literal> and <literal>cref</literal> mostly |
---|
| 641 | exist for historical reasons, |
---|
| 642 | and <literal>ref</literal> can always |
---|
| 643 | be replaced with <literal>var</literal>, and <literal>cref</literal> with |
---|
| 644 | <literal>constant_ref</literal>. |
---|
| 645 | See <xref linkend="lambda.delaying_constants_and_variables"/> for details. |
---|
| 646 | The <literal>ref</literal> and <literal>cref</literal> functions are |
---|
| 647 | general purpose utility functions in Boost, and hence defined directly |
---|
| 648 | in the <literal moreinfo="none">boost</literal> namespace. |
---|
| 649 | |
---|
| 650 | </para> |
---|
| 651 | </listitem> |
---|
| 652 | |
---|
| 653 | <listitem> |
---|
| 654 | <para> |
---|
| 655 | Array types cannot be copied, they are thus stored as const reference by default. |
---|
| 656 | </para> |
---|
| 657 | </listitem> |
---|
| 658 | |
---|
| 659 | <listitem> |
---|
| 660 | |
---|
| 661 | <para> |
---|
| 662 | For some expressions it makes more sense to store the arguments as references. |
---|
| 663 | |
---|
| 664 | For example, the obvious intention of the lambda expression |
---|
| 665 | <literal>i += _1</literal> is that calls to the lambda functor affect the |
---|
| 666 | value of the variable <literal>i</literal>, |
---|
| 667 | rather than some temporary copy of it. |
---|
| 668 | |
---|
| 669 | As another example, the streaming operators take their leftmost argument |
---|
| 670 | as non-const references. |
---|
| 671 | |
---|
| 672 | The exact rules are: |
---|
| 673 | |
---|
| 674 | <itemizedlist> |
---|
| 675 | <listitem> |
---|
| 676 | <para>The left argument of compound assignment operators (<literal>+=</literal>, <literal>*=</literal>, etc.) are stored as references to non-const.</para> |
---|
| 677 | </listitem> |
---|
| 678 | |
---|
| 679 | <listitem> |
---|
| 680 | <para>If the left argument of <literal><![CDATA[<<]]></literal> or <literal><![CDATA[>>]]></literal> operator is derived from an instantiation of <literal>basic_ostream</literal> or respectively from <literal>basic_istream</literal>, the argument is stored as a reference to non-const. |
---|
| 681 | For all other types, the argument is stored as a copy. |
---|
| 682 | </para> |
---|
| 683 | </listitem> |
---|
| 684 | |
---|
| 685 | <listitem> |
---|
| 686 | <para> |
---|
| 687 | In pointer arithmetic expressions, non-const array types are stored as non-const references. |
---|
| 688 | This is to prevent pointer arithmetic making non-const arrays const. |
---|
| 689 | |
---|
| 690 | </para> |
---|
| 691 | </listitem> |
---|
| 692 | |
---|
| 693 | </itemizedlist> |
---|
| 694 | |
---|
| 695 | </para> |
---|
| 696 | </listitem> |
---|
| 697 | |
---|
| 698 | </itemizedlist> |
---|
| 699 | </para> |
---|
| 700 | |
---|
| 701 | </section> |
---|
| 702 | |
---|
| 703 | </section> |
---|
| 704 | |
---|
| 705 | <section id="lambda.le_in_details"> |
---|
| 706 | <title>Lambda expressions in details</title> |
---|
| 707 | |
---|
| 708 | <para> |
---|
| 709 | This section describes different categories of lambda expressions in details. |
---|
| 710 | We devote a separate section for each of the possible forms of a lambda expression. |
---|
| 711 | |
---|
| 712 | |
---|
| 713 | </para> |
---|
| 714 | |
---|
| 715 | <section id="lambda.placeholders"> |
---|
| 716 | <title>Placeholders</title> |
---|
| 717 | |
---|
| 718 | <para> |
---|
| 719 | The BLL defines three placeholder types: <literal>placeholder1_type</literal>, <literal>placeholder2_type</literal> and <literal>placeholder3_type</literal>. |
---|
| 720 | BLL has a predefined placeholder variable for each placeholder type: <literal>_1</literal>, <literal>_2</literal> and <literal>_3</literal>. |
---|
| 721 | However, the user is not forced to use these placeholders. |
---|
| 722 | It is easy to define placeholders with alternative names. |
---|
| 723 | This is done by defining new variables of placeholder types. |
---|
| 724 | For example: |
---|
| 725 | |
---|
| 726 | <programlisting>boost::lambda::placeholder1_type X; |
---|
| 727 | boost::lambda::placeholder2_type Y; |
---|
| 728 | boost::lambda::placeholder3_type Z; |
---|
| 729 | </programlisting> |
---|
| 730 | |
---|
| 731 | With these variables defined, <literal>X += Y * Z</literal> is equivalent to <literal>_1 += _2 * _3</literal>. |
---|
| 732 | </para> |
---|
| 733 | |
---|
| 734 | <para> |
---|
| 735 | The use of placeholders in the lambda expression determines whether the resulting function is nullary, unary, binary or 3-ary. |
---|
| 736 | The highest placeholder index is decisive. For example: |
---|
| 737 | |
---|
| 738 | <programlisting> |
---|
| 739 | _1 + 5 // unary |
---|
| 740 | _1 * _1 + _1 // unary |
---|
| 741 | _1 + _2 // binary |
---|
| 742 | bind(f, _1, _2, _3) // 3-ary |
---|
| 743 | _3 + 10 // 3-ary |
---|
| 744 | </programlisting> |
---|
| 745 | |
---|
| 746 | Note that the last line creates a 3-ary function, which adds <literal>10</literal> to its <emphasis>third</emphasis> argument. |
---|
| 747 | The first two arguments are discarded. |
---|
| 748 | Furthermore, lambda functors only have a minimum arity. |
---|
| 749 | One can always provide more arguments (up the number of supported placeholders) |
---|
| 750 | that is really needed. |
---|
| 751 | The remaining arguments are just discarded. |
---|
| 752 | For example: |
---|
| 753 | |
---|
| 754 | <programlisting> |
---|
| 755 | int i, j, k; |
---|
| 756 | _1(i, j, k) // returns i, discards j and k |
---|
| 757 | (_2 + _2)(i, j, k) // returns j+j, discards i and k |
---|
| 758 | </programlisting> |
---|
| 759 | |
---|
| 760 | See |
---|
| 761 | <xref linkend="lambda.why_weak_arity"/> for the design rationale behind this |
---|
| 762 | functionality. |
---|
| 763 | |
---|
| 764 | </para> |
---|
| 765 | |
---|
| 766 | <para> |
---|
| 767 | In addition to these three placeholder types, there is also a fourth placeholder type <literal>placeholderE_type</literal>. |
---|
| 768 | The use of this placeholder is defined in <xref linkend="lambda.exceptions"/> describing exception handling in lambda expressions. |
---|
| 769 | </para> |
---|
| 770 | |
---|
| 771 | <para>When an actual argument is supplied for a placeholder, the parameter passing mode is always by reference. |
---|
| 772 | This means that any side-effects to the placeholder are reflected to the actual argument. |
---|
| 773 | For example: |
---|
| 774 | |
---|
| 775 | |
---|
| 776 | <programlisting> |
---|
| 777 | <![CDATA[int i = 1; |
---|
| 778 | (_1 += 2)(i); // i is now 3 |
---|
| 779 | (++_1, cout << _1)(i) // i is now 4, outputs 4]]> |
---|
| 780 | </programlisting> |
---|
| 781 | </para> |
---|
| 782 | |
---|
| 783 | </section> |
---|
| 784 | |
---|
| 785 | <section id="lambda.operator_expressions"> |
---|
| 786 | <title>Operator expressions</title> |
---|
| 787 | |
---|
| 788 | <para> |
---|
| 789 | The basic rule is that any C++ operator invocation with at least one argument being a lambda expression is itself a lambda expression. |
---|
| 790 | Almost all overloadable operators are supported. |
---|
| 791 | For example, the following is a valid lambda expression: |
---|
| 792 | |
---|
| 793 | <programlisting><![CDATA[cout << _1, _2[_3] = _1 && false]]></programlisting> |
---|
| 794 | </para> |
---|
| 795 | |
---|
| 796 | <para> |
---|
| 797 | However, there are some restrictions that originate from the C++ operator overloading rules, and some special cases. |
---|
| 798 | </para> |
---|
| 799 | |
---|
| 800 | |
---|
| 801 | <section> |
---|
| 802 | <title>Operators that cannot be overloaded</title> |
---|
| 803 | |
---|
| 804 | <para> |
---|
| 805 | Some operators cannot be overloaded at all (<literal>::</literal>, <literal>.</literal>, <literal>.*</literal>). |
---|
| 806 | For some operators, the requirements on return types prevent them to be overloaded to create lambda functors. |
---|
| 807 | These operators are <literal>->.</literal>, <literal>-></literal>, <literal>new</literal>, <literal>new[]</literal>, <literal>delete</literal>, <literal>delete[]</literal> and <literal>?:</literal> (the conditional operator). |
---|
| 808 | </para> |
---|
| 809 | |
---|
| 810 | </section> |
---|
| 811 | |
---|
| 812 | <section id="lambda.assignment_and_subscript"> |
---|
| 813 | <title>Assignment and subscript operators</title> |
---|
| 814 | |
---|
| 815 | <para> |
---|
| 816 | These operators must be implemented as class members. |
---|
| 817 | Consequently, the left operand must be a lambda expression. For example: |
---|
| 818 | |
---|
| 819 | <programlisting> |
---|
| 820 | int i; |
---|
| 821 | _1 = i; // ok |
---|
| 822 | i = _1; // not ok. i is not a lambda expression |
---|
| 823 | </programlisting> |
---|
| 824 | |
---|
| 825 | There is a simple solution around this limitation, described in <xref linkend="lambda.delaying_constants_and_variables"/>. |
---|
| 826 | In short, |
---|
| 827 | the left hand argument can be explicitly turned into a lambda functor by wrapping it with a special <literal>var</literal> function: |
---|
| 828 | <programlisting> |
---|
| 829 | var(i) = _1; // ok |
---|
| 830 | </programlisting> |
---|
| 831 | |
---|
| 832 | </para> |
---|
| 833 | </section> |
---|
| 834 | |
---|
| 835 | <section id="lambda.logical_operators"> |
---|
| 836 | <title>Logical operators</title> |
---|
| 837 | |
---|
| 838 | <para> |
---|
| 839 | Logical operators obey the short-circuiting evaluation rules. For example, in the following code, <literal>i</literal> is never incremented: |
---|
| 840 | <programlisting> |
---|
| 841 | bool flag = true; int i = 0; |
---|
| 842 | (_1 || ++_2)(flag, i); |
---|
| 843 | </programlisting> |
---|
| 844 | </para> |
---|
| 845 | </section> |
---|
| 846 | |
---|
| 847 | <section id="lambda.comma_operator"> |
---|
| 848 | <title>Comma operator</title> |
---|
| 849 | |
---|
| 850 | <para> |
---|
| 851 | Comma operator is the <quote>statement separator</quote> in lambda expressions. |
---|
| 852 | Since comma is also the separator between arguments in a function call, extra parenthesis are sometimes needed: |
---|
| 853 | |
---|
| 854 | <programlisting> |
---|
| 855 | for_each(a.begin(), a.end(), (++_1, cout << _1)); |
---|
| 856 | </programlisting> |
---|
| 857 | |
---|
| 858 | Without the extra parenthesis around <literal>++_1, cout << _1</literal>, the code would be interpreted as an attempt to call <literal>for_each</literal> with four arguments. |
---|
| 859 | </para> |
---|
| 860 | <para> |
---|
| 861 | The lambda functor created by the comma operator adheres to the C++ rule of always evaluating the left operand before the right one. |
---|
| 862 | In the above example, each element of <literal>a</literal> is first incremented, then written to the stream. |
---|
| 863 | </para> |
---|
| 864 | </section> |
---|
| 865 | |
---|
| 866 | <section id="lambda.function_call_operator"> |
---|
| 867 | <title>Function call operator</title> |
---|
| 868 | |
---|
| 869 | <para> |
---|
| 870 | The function call operators have the effect of evaluating the lambda |
---|
| 871 | functor. |
---|
| 872 | Calls with too few arguments lead to a compile time error. |
---|
| 873 | </para> |
---|
| 874 | </section> |
---|
| 875 | |
---|
| 876 | <section id="lambda.member_pointer_operator"> |
---|
| 877 | <title>Member pointer operator</title> |
---|
| 878 | |
---|
| 879 | <para> |
---|
| 880 | The member pointer operator <literal>operator->*</literal> can be overloaded freely. |
---|
| 881 | Hence, for user defined types, member pointer operator is no special case. |
---|
| 882 | The built-in meaning, however, is a somewhat more complicated case. |
---|
| 883 | The built-in member pointer operator is applied if the left argument is a pointer to an object of some class <literal>A</literal>, and the right hand argument is a pointer to a member of <literal>A</literal>, or a pointer to a member of a class from which <literal>A</literal> derives. |
---|
| 884 | We must separate two cases: |
---|
| 885 | |
---|
| 886 | <itemizedlist> |
---|
| 887 | |
---|
| 888 | <listitem> |
---|
| 889 | <para>The right hand argument is a pointer to a data member. |
---|
| 890 | In this case the lambda functor simply performs the argument substitution and calls the built-in member pointer operator, which returns a reference to the member pointed to. |
---|
| 891 | For example: |
---|
| 892 | <programlisting> |
---|
| 893 | <![CDATA[struct A { int d; }; |
---|
| 894 | A* a = new A(); |
---|
| 895 | ... |
---|
| 896 | (a ->* &A::d); // returns a reference to a->d |
---|
| 897 | (_1 ->* &A::d)(a); // likewise]]> |
---|
| 898 | </programlisting> |
---|
| 899 | </para> |
---|
| 900 | </listitem> |
---|
| 901 | |
---|
| 902 | <listitem> |
---|
| 903 | <para> |
---|
| 904 | The right hand argument is a pointer to a member function. |
---|
| 905 | For a built-in call like this, the result is kind of a delayed member function call. |
---|
| 906 | Such an expression must be followed by a function argument list, with which the delayed member function call is performed. |
---|
| 907 | For example: |
---|
| 908 | <programlisting> |
---|
| 909 | <![CDATA[struct B { int foo(int); }; |
---|
| 910 | B* b = new B(); |
---|
| 911 | ... |
---|
| 912 | (b ->* &B::foo) // returns a delayed call to b->foo |
---|
| 913 | // a function argument list must follow |
---|
| 914 | (b ->* &B::foo)(1) // ok, calls b->foo(1) |
---|
| 915 | |
---|
| 916 | (_1 ->* &B::foo)(b); // returns a delayed call to b->foo, |
---|
| 917 | // no effect as such |
---|
| 918 | (_1 ->* &B::foo)(b)(1); // calls b->foo(1)]]> |
---|
| 919 | </programlisting> |
---|
| 920 | </para> |
---|
| 921 | </listitem> |
---|
| 922 | </itemizedlist> |
---|
| 923 | </para> |
---|
| 924 | </section> |
---|
| 925 | |
---|
| 926 | </section> |
---|
| 927 | |
---|
| 928 | <section id="lambda.bind_expressions"> |
---|
| 929 | <title>Bind expressions</title> |
---|
| 930 | |
---|
| 931 | <para> |
---|
| 932 | Bind expressions can have two forms: |
---|
| 933 | |
---|
| 934 | <!-- TODO: shouldn't really be emphasis, but a variable or something--> |
---|
| 935 | <programlisting> |
---|
| 936 | bind(<parameter>target-function</parameter>, <parameter>bind-argument-list</parameter>) |
---|
| 937 | bind(<parameter>target-member-function</parameter>, <parameter>object-argument</parameter>, <parameter>bind-argument-list</parameter>) |
---|
| 938 | </programlisting> |
---|
| 939 | |
---|
| 940 | A bind expression delays the call of a function. |
---|
| 941 | If this <emphasis>target function</emphasis> is <emphasis>n</emphasis>-ary, then the <literal><emphasis>bind-argument-list</emphasis></literal> must contain <emphasis>n</emphasis> arguments as well. |
---|
| 942 | In the current version of the BLL, <inlineequation>0 <= n <= 9</inlineequation> must hold. |
---|
| 943 | For member functions, the number of arguments must be at most <inlineequation>8</inlineequation>, as the object argument takes one argument position. |
---|
| 944 | |
---|
| 945 | Basically, the |
---|
| 946 | <emphasis><literal>bind-argument-list</literal></emphasis> must be a valid argument list for the target function, except that any argument can be replaced with a placeholder, or more generally, with a lambda expression. |
---|
| 947 | Note that also the target function can be a lambda expression. |
---|
| 948 | |
---|
| 949 | The result of a bind expression is either a nullary, unary, binary or 3-ary function object depending on the use of placeholders in the <emphasis><literal>bind-argument-list</literal></emphasis> (see <xref linkend="lambda.placeholders"/>). |
---|
| 950 | </para> |
---|
| 951 | |
---|
| 952 | <para> |
---|
| 953 | The return type of the lambda functor created by the bind expression can be given as an explicitly specified template parameter, as in the following example: |
---|
| 954 | <programlisting> |
---|
| 955 | bind<<emphasis>RET</emphasis>>(<emphasis>target-function</emphasis>, <emphasis>bind-argument-list</emphasis>) |
---|
| 956 | </programlisting> |
---|
| 957 | This is only necessary if the return type of the target function cannot be deduced. |
---|
| 958 | </para> |
---|
| 959 | |
---|
| 960 | <para> |
---|
| 961 | The following sections describe the different types of bind expressions. |
---|
| 962 | </para> |
---|
| 963 | |
---|
| 964 | <section id="lambda.function_pointers_as_targets"> |
---|
| 965 | <title>Function pointers or references as targets</title> |
---|
| 966 | |
---|
| 967 | <para>The target function can be a pointer or a reference to a function and it can be either bound or unbound. For example: |
---|
| 968 | <programlisting> |
---|
| 969 | <![CDATA[X foo(A, B, C); A a; B b; C c; |
---|
| 970 | bind(foo, _1, _2, c)(a, b); |
---|
| 971 | bind(&foo, _1, _2, c)(a, b); |
---|
| 972 | bind(_1, a, b, c)(foo);]]> |
---|
| 973 | </programlisting> |
---|
| 974 | |
---|
| 975 | The return type deduction always succeeds with this type of bind expressions. |
---|
| 976 | </para> |
---|
| 977 | |
---|
| 978 | <para> |
---|
| 979 | Note, that in C++ it is possible to take the address of an overloaded function only if the address is assigned to, or used as an initializer of, a variable, the type of which solves the amibiguity, or if an explicit cast expression is used. |
---|
| 980 | This means that overloaded functions cannot be used in bind expressions directly, e.g.: |
---|
| 981 | <programlisting> |
---|
| 982 | <![CDATA[void foo(int); |
---|
| 983 | void foo(float); |
---|
| 984 | int i; |
---|
| 985 | ... |
---|
| 986 | bind(&foo, _1)(i); // error |
---|
| 987 | ... |
---|
| 988 | void (*pf1)(int) = &foo; |
---|
| 989 | bind(pf1, _1)(i); // ok |
---|
| 990 | bind(static_cast<void(*)(int)>(&foo), _1)(i); // ok]]> |
---|
| 991 | </programlisting> |
---|
| 992 | </para> |
---|
| 993 | </section> |
---|
| 994 | |
---|
| 995 | <section id="member_functions_as_targets"> |
---|
| 996 | <title>Member functions as targets</title> |
---|
| 997 | |
---|
| 998 | <para> |
---|
| 999 | The syntax for using pointers to member function in bind expression is: |
---|
| 1000 | <programlisting> |
---|
| 1001 | bind(<parameter>target-member-function</parameter>, <parameter>object-argument</parameter>, <parameter>bind-argument-list</parameter>) |
---|
| 1002 | </programlisting> |
---|
| 1003 | |
---|
| 1004 | The object argument can be a reference or pointer to the object, the BLL supports both cases with a uniform interface: |
---|
| 1005 | |
---|
| 1006 | <programlisting> |
---|
| 1007 | <![CDATA[bool A::foo(int) const; |
---|
| 1008 | A a; |
---|
| 1009 | vector<int> ints; |
---|
| 1010 | ... |
---|
| 1011 | find_if(ints.begin(), ints.end(), bind(&A::foo, a, _1)); |
---|
| 1012 | find_if(ints.begin(), ints.end(), bind(&A::foo, &a, _1));]]> |
---|
| 1013 | </programlisting> |
---|
| 1014 | |
---|
| 1015 | Similarly, if the object argument is unbound, the resulting lambda functor can be called both via a pointer or a reference: |
---|
| 1016 | |
---|
| 1017 | <programlisting> |
---|
| 1018 | <![CDATA[bool A::foo(int); |
---|
| 1019 | list<A> refs; |
---|
| 1020 | list<A*> pointers; |
---|
| 1021 | ... |
---|
| 1022 | find_if(refs.begin(), refs.end(), bind(&A::foo, _1, 1)); |
---|
| 1023 | find_if(pointers.begin(), pointers.end(), bind(&A::foo, _1, 1));]]> |
---|
| 1024 | </programlisting> |
---|
| 1025 | |
---|
| 1026 | </para> |
---|
| 1027 | |
---|
| 1028 | <!--%The exact rules for the object argument (whether it is bound, or supplied in the lambda function invoction) are as follows: |
---|
| 1029 | %If the target function is a pointer to a member function of some class \snip{A}, then the object argument must be an expression of type \snip{B}, where either |
---|
| 1030 | %\begin{itemize} |
---|
| 1031 | %\item \snip{B} = \snip{A} or there is an implicit conversion from \snip{B} to \snip{A}. |
---|
| 1032 | %\item \snip{B} = \snip{A*}. |
---|
| 1033 | %\item \snip{B} = \snip{C*}, where \snip{C} is any class derived form \snip{A}. |
---|
| 1034 | %\end{itemize} |
---|
| 1035 | %For example: |
---|
| 1036 | %\begin{alltt} |
---|
| 1037 | %struct A \{ |
---|
| 1038 | % virtual void f(); |
---|
| 1039 | % void fc() const; |
---|
| 1040 | %\}; |
---|
| 1041 | % |
---|
| 1042 | %struct B : public A \{ |
---|
| 1043 | % virtual void f(); |
---|
| 1044 | %\}; |
---|
| 1045 | % |
---|
| 1046 | %struct C \{ |
---|
| 1047 | % operator A const() \{ return A(); \} |
---|
| 1048 | %\}; |
---|
| 1049 | % |
---|
| 1050 | % A a; B b; C c; |
---|
| 1051 | % ... |
---|
| 1052 | % bind(&A::f, a)(); |
---|
| 1053 | % bind(&A::f, b)(); // calls B::f |
---|
| 1054 | % bind(&A::fc, c)(); |
---|
| 1055 | % |
---|
| 1056 | % bind(&A::f, &a)(); |
---|
| 1057 | % bind(&A::f, &b)(); // calls B::f |
---|
| 1058 | % bind(&A::f, &c)(); // error: no conversion from C* \(\rightarrow\) A, |
---|
| 1059 | %\end{alltt} |
---|
| 1060 | --> |
---|
| 1061 | |
---|
| 1062 | <para> |
---|
| 1063 | Even though the interfaces are the same, there are important semantic differences between using a pointer or a reference as the object argument. |
---|
| 1064 | The differences stem from the way <literal>bind</literal>-functions take their parameters, and how the bound parameters are stored within the lambda functor. |
---|
| 1065 | The object argument has the same parameter passing and storing mechanism as any other bind argument slot (see <xref linkend="lambda.storing_bound_arguments"/>); it is passed as a const reference and stored as a const copy in the lambda functor. |
---|
| 1066 | This creates some asymmetry between the lambda functor and the original member function, and between seemingly similar lambda functors. For example: |
---|
| 1067 | <programlisting> |
---|
| 1068 | class A { |
---|
| 1069 | int i; mutable int j; |
---|
| 1070 | public: |
---|
| 1071 | |
---|
| 1072 | A(int ii, int jj) : i(ii), j(jj) {}; |
---|
| 1073 | void set_i(int x) { i = x; }; |
---|
| 1074 | void set_j(int x) const { j = x; }; |
---|
| 1075 | }; |
---|
| 1076 | </programlisting> |
---|
| 1077 | |
---|
| 1078 | When a pointer is used, the behavior is what the programmer might expect: |
---|
| 1079 | |
---|
| 1080 | <programlisting> |
---|
| 1081 | <![CDATA[A a(0,0); int k = 1; |
---|
| 1082 | bind(&A::set_i, &a, _1)(k); // a.i == 1 |
---|
| 1083 | bind(&A::set_j, &a, _1)(k); // a.j == 1]]> |
---|
| 1084 | </programlisting> |
---|
| 1085 | |
---|
| 1086 | Even though a const copy of the object argument is stored, the original object <literal>a</literal> is still modified. |
---|
| 1087 | This is since the object argument is a pointer, and the pointer is copied, not the object it points to. |
---|
| 1088 | When we use a reference, the behaviour is different: |
---|
| 1089 | |
---|
| 1090 | <programlisting> |
---|
| 1091 | <![CDATA[A a(0,0); int k = 1; |
---|
| 1092 | bind(&A::set_i, a, _1)(k); // error; a const copy of a is stored. |
---|
| 1093 | // Cannot call a non-const function set_i |
---|
| 1094 | bind(&A::set_j, a, _1)(k); // a.j == 0, as a copy of a is modified]]> |
---|
| 1095 | </programlisting> |
---|
| 1096 | </para> |
---|
| 1097 | |
---|
| 1098 | <para> |
---|
| 1099 | To prevent the copying from taking place, one can use the <literal>ref</literal> or <literal>cref</literal> wrappers (<literal>var</literal> and <literal>constant_ref</literal> would do as well): |
---|
| 1100 | <programlisting> |
---|
| 1101 | <![CDATA[bind(&A::set_i, ref(a), _1)(k); // a.j == 1 |
---|
| 1102 | bind(&A::set_j, cref(a), _1)(k); // a.j == 1]]> |
---|
| 1103 | </programlisting> |
---|
| 1104 | </para> |
---|
| 1105 | |
---|
| 1106 | <para>Note that the preceding discussion is relevant only for bound arguments. |
---|
| 1107 | If the object argument is unbound, the parameter passing mode is always by reference. |
---|
| 1108 | Hence, the argument <literal>a</literal> is not copied in the calls to the two lambda functors below: |
---|
| 1109 | <programlisting> |
---|
| 1110 | <![CDATA[A a(0,0); |
---|
| 1111 | bind(&A::set_i, _1, 1)(a); // a.i == 1 |
---|
| 1112 | bind(&A::set_j, _1, 1)(a); // a.j == 1]]> |
---|
| 1113 | </programlisting> |
---|
| 1114 | </para> |
---|
| 1115 | </section> |
---|
| 1116 | |
---|
| 1117 | <section id="lambda.members_variables_as_targets"> |
---|
| 1118 | <title>Member variables as targets</title> |
---|
| 1119 | |
---|
| 1120 | <para> |
---|
| 1121 | A pointer to a member variable is not really a function, but |
---|
| 1122 | the first argument to the <literal>bind</literal> function can nevertheless |
---|
| 1123 | be a pointer to a member variable. |
---|
| 1124 | Invoking such a bind expression returns a reference to the data member. |
---|
| 1125 | For example: |
---|
| 1126 | |
---|
| 1127 | <programlisting> |
---|
| 1128 | <![CDATA[struct A { int data; }; |
---|
| 1129 | A a; |
---|
| 1130 | bind(&A::data, _1)(a) = 1; // a.data == 1]]> |
---|
| 1131 | </programlisting> |
---|
| 1132 | |
---|
| 1133 | The cv-qualifiers of the object whose member is accessed are respected. |
---|
| 1134 | For example, the following tries to write into a const location: |
---|
| 1135 | <programlisting> |
---|
| 1136 | <![CDATA[const A ca = a; |
---|
| 1137 | bind(&A::data, _1)(ca) = 1; // error]]> |
---|
| 1138 | </programlisting> |
---|
| 1139 | |
---|
| 1140 | </para> |
---|
| 1141 | </section> |
---|
| 1142 | |
---|
| 1143 | <section id="lambda.function_objects_as_targets"> |
---|
| 1144 | <title>Function objects as targets</title> |
---|
| 1145 | |
---|
| 1146 | <para> |
---|
| 1147 | |
---|
| 1148 | Function objects, that is, class objects which have the function call |
---|
| 1149 | operator defined, can be used as target functions. |
---|
| 1150 | |
---|
| 1151 | In general, BLL cannot deduce the return type of an arbitrary function object. |
---|
| 1152 | |
---|
| 1153 | However, there are two methods for giving BLL this capability for a certain |
---|
| 1154 | function object class. |
---|
| 1155 | |
---|
| 1156 | </para> |
---|
| 1157 | |
---|
| 1158 | <simplesect> |
---|
| 1159 | |
---|
| 1160 | <title>The result_type typedef</title> |
---|
| 1161 | |
---|
| 1162 | <para> |
---|
| 1163 | |
---|
| 1164 | The BLL supports the standard library convention of declaring the return type |
---|
| 1165 | of a function object with a member typedef named <literal>result_type</literal> in the |
---|
| 1166 | function object class. |
---|
| 1167 | |
---|
| 1168 | Here is a simple example: |
---|
| 1169 | <programlisting> |
---|
| 1170 | <![CDATA[struct A { |
---|
| 1171 | typedef B result_type; |
---|
| 1172 | B operator()(X, Y, Z); |
---|
| 1173 | };]]> |
---|
| 1174 | </programlisting> |
---|
| 1175 | |
---|
| 1176 | If a function object does not define a <literal>result_type</literal> typedef, |
---|
| 1177 | the method described below (<literal>sig</literal> template) |
---|
| 1178 | is attempted to resolve the return type of the |
---|
| 1179 | function object. If a function object defines both <literal>result_type</literal> |
---|
| 1180 | and <literal>sig</literal>, <literal>result_type</literal> takes precedence. |
---|
| 1181 | |
---|
| 1182 | </para> |
---|
| 1183 | |
---|
| 1184 | </simplesect> |
---|
| 1185 | |
---|
| 1186 | <simplesect> |
---|
| 1187 | |
---|
| 1188 | <title>The sig template</title> |
---|
| 1189 | |
---|
| 1190 | <para> |
---|
| 1191 | Another mechanism that make BLL aware of the return type(s) of a function object is defining |
---|
| 1192 | member template struct |
---|
| 1193 | <literal><![CDATA[sig<Args>]]></literal> with a typedef |
---|
| 1194 | <literal>type</literal> that specifies the return type. |
---|
| 1195 | |
---|
| 1196 | Here is a simple example: |
---|
| 1197 | <programlisting> |
---|
| 1198 | <![CDATA[struct A { |
---|
| 1199 | template <class Args> struct sig { typedef B type; } |
---|
| 1200 | B operator()(X, Y, Z); |
---|
| 1201 | };]]> |
---|
| 1202 | </programlisting> |
---|
| 1203 | |
---|
| 1204 | The template argument <literal>Args</literal> is a |
---|
| 1205 | <literal>tuple</literal> (or more precisely a <literal>cons</literal> list) |
---|
| 1206 | type <xref linkend="cit:boost::tuple"/>, where the first element |
---|
| 1207 | is the function |
---|
| 1208 | object type itself, and the remaining elements are the types of |
---|
| 1209 | the arguments, with which the function object is being called. |
---|
| 1210 | |
---|
| 1211 | This may seem overly complex compared to defining the <literal>result_type</literal> typedef. |
---|
| 1212 | Howver, there are two significant restrictions with using just a simple |
---|
| 1213 | typedef to express the return type: |
---|
| 1214 | <orderedlist> |
---|
| 1215 | <listitem> |
---|
| 1216 | <para> |
---|
| 1217 | If the function object defines several function call operators, there is no way to specify different result types for them. |
---|
| 1218 | </para> |
---|
| 1219 | </listitem> |
---|
| 1220 | <listitem> |
---|
| 1221 | <para> |
---|
| 1222 | If the function call operator is a template, the result type may |
---|
| 1223 | depend on the template parameters. |
---|
| 1224 | Hence, the typedef ought to be a template too, which the C++ language |
---|
| 1225 | does not support. |
---|
| 1226 | </para> |
---|
| 1227 | </listitem> |
---|
| 1228 | </orderedlist> |
---|
| 1229 | |
---|
| 1230 | The following code shows an example, where the return type depends on the type |
---|
| 1231 | of one of the arguments, and how that dependency can be expressed with the |
---|
| 1232 | <literal>sig</literal> template: |
---|
| 1233 | |
---|
| 1234 | <programlisting> |
---|
| 1235 | <![CDATA[struct A { |
---|
| 1236 | |
---|
| 1237 | // the return type equals the third argument type: |
---|
| 1238 | template<class T1, class T2, class T3> |
---|
| 1239 | T3 operator()(const T1& t1, const T2& t2, const T3& t3) const; |
---|
| 1240 | |
---|
| 1241 | template <class Args> |
---|
| 1242 | class sig { |
---|
| 1243 | // get the third argument type (4th element) |
---|
| 1244 | typedef typename |
---|
| 1245 | boost::tuples::element<3, Args>::type T3; |
---|
| 1246 | public: |
---|
| 1247 | typedef typename |
---|
| 1248 | boost::remove_cv<T3>::type type; |
---|
| 1249 | }; |
---|
| 1250 | };]]> |
---|
| 1251 | </programlisting> |
---|
| 1252 | |
---|
| 1253 | |
---|
| 1254 | The elements of the <literal>Args</literal> tuple are always |
---|
| 1255 | non-reference types. |
---|
| 1256 | |
---|
| 1257 | Moreover, the element types can have a const or volatile qualifier |
---|
| 1258 | (jointly referred to as <emphasis>cv-qualifiers</emphasis>), or both. |
---|
| 1259 | This is since the cv-qualifiers in the arguments can affect the return type. |
---|
| 1260 | The reason for including the potentially cv-qualified function object |
---|
| 1261 | type itself into the <literal>Args</literal> tuple, is that the function |
---|
| 1262 | object class can contain both const and non-const (or volatile, even |
---|
| 1263 | const volatile) function call operators, and they can each have a different |
---|
| 1264 | return type. |
---|
| 1265 | </para> |
---|
| 1266 | |
---|
| 1267 | <para> |
---|
| 1268 | The <literal>sig</literal> template can be seen as a |
---|
| 1269 | <emphasis>meta-function</emphasis> that maps the argument type tuple to |
---|
| 1270 | the result type of the call made with arguments of the types in the tuple. |
---|
| 1271 | |
---|
| 1272 | As the example above demonstrates, the template can end up being somewhat |
---|
| 1273 | complex. |
---|
| 1274 | Typical tasks to be performed are the extraction of the relevant types |
---|
| 1275 | from the tuple, removing cv-qualifiers etc. |
---|
| 1276 | See the Boost type_traits <xref linkend="cit:boost::type_traits"/> and |
---|
| 1277 | Tuple <xref linkend="cit:boost::type_traits"/> libraries |
---|
| 1278 | for tools that can aid in these tasks. |
---|
| 1279 | The <literal>sig</literal> templates are a refined version of a similar |
---|
| 1280 | mechanism first introduced in the FC++ library |
---|
| 1281 | <xref linkend="cit:fc++"/>. |
---|
| 1282 | </para> |
---|
| 1283 | |
---|
| 1284 | </simplesect> |
---|
| 1285 | |
---|
| 1286 | </section> |
---|
| 1287 | |
---|
| 1288 | |
---|
| 1289 | |
---|
| 1290 | </section> |
---|
| 1291 | |
---|
| 1292 | <section id="lambda.overriding_deduced_return_type"> |
---|
| 1293 | <title>Overriding the deduced return type</title> |
---|
| 1294 | |
---|
| 1295 | <para> |
---|
| 1296 | The return type deduction system may not be able to deduce the return types of some user defined operators or bind expressions with class objects. |
---|
| 1297 | <!-- (see the example in <xref linkend="lambda.parameter_and_return_types"/>).--> |
---|
| 1298 | A special lambda expression type is provided for stating the return type explicitly and overriding the deduction system. |
---|
| 1299 | To state that the return type of the lambda functor defined by the lambda expression <literal>e</literal> is <literal>T</literal>, you can write: |
---|
| 1300 | |
---|
| 1301 | <programlisting><![CDATA[ret<T>(e);]]></programlisting> |
---|
| 1302 | |
---|
| 1303 | The effect is that the return type deduction is not performed for the lambda expression <literal>e</literal> at all, but instead, <literal>T</literal> is used as the return type. |
---|
| 1304 | Obviously <literal>T</literal> cannot be an arbitrary type, the true result of the lambda functor must be implicitly convertible to <literal>T</literal>. |
---|
| 1305 | For example: |
---|
| 1306 | |
---|
| 1307 | <programlisting> |
---|
| 1308 | <![CDATA[A a; B b; |
---|
| 1309 | C operator+(A, B); |
---|
| 1310 | int operator*(A, B); |
---|
| 1311 | ... |
---|
| 1312 | ret<D>(_1 + _2)(a, b); // error (C cannot be converted to D) |
---|
| 1313 | ret<C>(_1 + _2)(a, b); // ok |
---|
| 1314 | ret<float>(_1 * _2)(a, b); // ok (int can be converted to float) |
---|
| 1315 | ... |
---|
| 1316 | struct X { |
---|
| 1317 | Y operator(int)(); |
---|
| 1318 | }; |
---|
| 1319 | ... |
---|
| 1320 | X x; int i; |
---|
| 1321 | bind(x, _1)(i); // error, return type cannot be deduced |
---|
| 1322 | ret<Y>(bind(x, _1))(i); // ok]]> |
---|
| 1323 | </programlisting> |
---|
| 1324 | For bind expressions, there is a short-hand notation that can be used instead of <literal>ret</literal>. |
---|
| 1325 | The last line could alternatively be written as: |
---|
| 1326 | |
---|
| 1327 | <programlisting><![CDATA[bind<Z>(x, _1)(i);]]></programlisting> |
---|
| 1328 | This feature is modeled after the Boost Bind library <xref linkend="cit:boost::bind"/>. |
---|
| 1329 | |
---|
| 1330 | </para> |
---|
| 1331 | |
---|
| 1332 | <para>Note that within nested lambda expressions, |
---|
| 1333 | the <literal>ret</literal> must be used at each subexpression where |
---|
| 1334 | the deduction would otherwise fail. |
---|
| 1335 | For example: |
---|
| 1336 | <programlisting> |
---|
| 1337 | <![CDATA[A a; B b; |
---|
| 1338 | C operator+(A, B); D operator-(C); |
---|
| 1339 | ... |
---|
| 1340 | ret<D>( - (_1 + _2))(a, b); // error |
---|
| 1341 | ret<D>( - ret<C>(_1 + _2))(a, b); // ok]]> |
---|
| 1342 | </programlisting> |
---|
| 1343 | </para> |
---|
| 1344 | |
---|
| 1345 | <para>If you find yourself using <literal>ret</literal> repeatedly with the same types, it is worth while extending the return type deduction (see <xref linkend="lambda.extending"/>). |
---|
| 1346 | </para> |
---|
| 1347 | |
---|
| 1348 | <section id="lambda.nullary_functors_and_ret"> |
---|
| 1349 | <title>Nullary lambda functors and ret</title> |
---|
| 1350 | |
---|
| 1351 | <para> |
---|
| 1352 | As stated above, the effect of <literal>ret</literal> is to prevent the return type deduction to be performed. |
---|
| 1353 | However, there is an exception. |
---|
| 1354 | Due to the way the C++ template instantiation works, the compiler is always forced to instantiate the return type deduction templates for zero-argument lambda functors. |
---|
| 1355 | This introduces a slight problem with <literal>ret</literal>, best described with an example: |
---|
| 1356 | |
---|
| 1357 | <programlisting> |
---|
| 1358 | <![CDATA[struct F { int operator()(int i) const; }; |
---|
| 1359 | F f; |
---|
| 1360 | ... |
---|
| 1361 | bind(f, _1); // fails, cannot deduce the return type |
---|
| 1362 | ret<int>(bind(f, _1)); // ok |
---|
| 1363 | ... |
---|
| 1364 | bind(f, 1); // fails, cannot deduce the return type |
---|
| 1365 | ret<int>(bind(f, 1)); // fails as well!]]> |
---|
| 1366 | </programlisting> |
---|
| 1367 | The BLL cannot deduce the return types of the above bind calls, as <literal>F</literal> does not define the typedef <literal>result_type</literal>. |
---|
| 1368 | One would expect <literal>ret</literal> to fix this, but for the nullary lambda functor that results from a bind expression (last line above) this does not work. |
---|
| 1369 | The return type deduction templates are instantiated, even though it would not be necessary and the result is a compilation error. |
---|
| 1370 | </para> |
---|
| 1371 | |
---|
| 1372 | <para>The solution to this is not to use the <literal>ret</literal> function, but rather define the return type as an explicitly specified template parameter in the <literal>bind</literal> call: |
---|
| 1373 | <programlisting> |
---|
| 1374 | <![CDATA[bind<int>(f, 1); // ok]]> |
---|
| 1375 | </programlisting> |
---|
| 1376 | |
---|
| 1377 | The lambda functors created with |
---|
| 1378 | <literal>ret<<parameter>T</parameter>>(bind(<parameter>arg-list</parameter>))</literal> and |
---|
| 1379 | <literal>bind<<parameter>T</parameter>>(<parameter>arg-list</parameter>)</literal> have the exact same functionality — |
---|
| 1380 | apart from the fact that for some nullary lambda functors the former does not work while the latter does. |
---|
| 1381 | </para> |
---|
| 1382 | </section> |
---|
| 1383 | </section> |
---|
| 1384 | |
---|
| 1385 | |
---|
| 1386 | <section id="lambda.delaying_constants_and_variables"> |
---|
| 1387 | <title>Delaying constants and variables</title> |
---|
| 1388 | |
---|
| 1389 | <para> |
---|
| 1390 | The unary functions <literal>constant</literal>, |
---|
| 1391 | <literal>constant_ref</literal> and <literal>var</literal> turn their argument into a lambda functor, that implements an identity mapping. |
---|
| 1392 | The former two are for constants, the latter for variables. |
---|
| 1393 | The use of these <emphasis>delayed</emphasis> constants and variables is sometimes necessary due to the lack of explicit syntax for lambda expressions. |
---|
| 1394 | For example: |
---|
| 1395 | <programlisting> |
---|
| 1396 | <![CDATA[for_each(a.begin(), a.end(), cout << _1 << ' '); |
---|
| 1397 | for_each(a.begin(), a.end(), cout << ' ' << _1);]]> |
---|
| 1398 | </programlisting> |
---|
| 1399 | The first line outputs the elements of <literal>a</literal> separated by spaces, while the second line outputs a space followed by the elements of <literal>a</literal> without any separators. |
---|
| 1400 | The reason for this is that neither of the operands of |
---|
| 1401 | <literal><![CDATA[cout << ' ']]></literal> is a lambda expression, hence <literal><![CDATA[cout << ' ']]></literal> is evaluated immediately. |
---|
| 1402 | |
---|
| 1403 | To delay the evaluation of <literal><![CDATA[cout << ' ']]></literal>, one of the operands must be explicitly marked as a lambda expression. |
---|
| 1404 | This is accomplished with the <literal>constant</literal> function: |
---|
| 1405 | <programlisting> |
---|
| 1406 | <![CDATA[for_each(a.begin(), a.end(), cout << constant(' ') << _1);]]> |
---|
| 1407 | </programlisting> |
---|
| 1408 | |
---|
| 1409 | The call <literal>constant(' ')</literal> creates a nullary lambda functor which stores the character constant <literal>' '</literal> |
---|
| 1410 | and returns a reference to it when invoked. |
---|
| 1411 | The function <literal>constant_ref</literal> is similar, except that it |
---|
| 1412 | stores a constant reference to its argument. |
---|
| 1413 | |
---|
| 1414 | The <literal>constant</literal> and <literal>consant_ref</literal> are only |
---|
| 1415 | needed when the operator call has side effects, like in the above example. |
---|
| 1416 | </para> |
---|
| 1417 | |
---|
| 1418 | <para> |
---|
| 1419 | Sometimes we need to delay the evaluation of a variable. |
---|
| 1420 | Suppose we wanted to output the elements of a container in a numbered list: |
---|
| 1421 | |
---|
| 1422 | <programlisting> |
---|
| 1423 | <![CDATA[int index = 0; |
---|
| 1424 | for_each(a.begin(), a.end(), cout << ++index << ':' << _1 << '\n'); |
---|
| 1425 | for_each(a.begin(), a.end(), cout << ++var(index) << ':' << _1 << '\n');]]> |
---|
| 1426 | </programlisting> |
---|
| 1427 | |
---|
| 1428 | The first <literal>for_each</literal> invocation does not do what we want; <literal>index</literal> is incremented only once, and its value is written into the output stream only once. |
---|
| 1429 | By using <literal>var</literal> to make <literal>index</literal> a lambda expression, we get the desired effect. |
---|
| 1430 | <!-- Note that <literal>var</literal> accepts const objects as well, in which case |
---|
| 1431 | calling <literal>var</literal> equals calling <literal>constant_ref</literal>.--> |
---|
| 1432 | </para> |
---|
| 1433 | |
---|
| 1434 | <para> |
---|
| 1435 | In sum, <literal>var(x)</literal> creates a nullary lambda functor, |
---|
| 1436 | which stores a reference to the variable <literal>x</literal>. |
---|
| 1437 | When the lambda functor is invoked, a reference to <literal>x</literal> is returned. |
---|
| 1438 | </para> |
---|
| 1439 | |
---|
| 1440 | <simplesect> |
---|
| 1441 | <title>Naming delayed constants and variables</title> |
---|
| 1442 | |
---|
| 1443 | <para> |
---|
| 1444 | It is possible to predefine and name a delayed variable or constant outside a lambda expression. |
---|
| 1445 | The templates <literal>var_type</literal>, <literal>constant_type</literal> |
---|
| 1446 | and <literal>constant_ref_type</literal> serve for this purpose. |
---|
| 1447 | They are used as: |
---|
| 1448 | <programlisting> |
---|
| 1449 | <![CDATA[var_type<T>::type delayed_i(var(i)); |
---|
| 1450 | constant_type<T>::type delayed_c(constant(c));]]> |
---|
| 1451 | </programlisting> |
---|
| 1452 | The first line defines the variable <literal>delayed_i</literal> which is a delayed version of the variable <literal>i</literal> of type <literal>T</literal>. |
---|
| 1453 | Analogously, the second line defines the constant <literal>delayed_c</literal> as a delayed version of the constant <literal>c</literal>. |
---|
| 1454 | For example: |
---|
| 1455 | |
---|
| 1456 | <programlisting> |
---|
| 1457 | int i = 0; int j; |
---|
| 1458 | for_each(a.begin(), a.end(), (var(j) = _1, _1 = var(i), var(i) = var(j))); |
---|
| 1459 | </programlisting> |
---|
| 1460 | is equivalent to: |
---|
| 1461 | <programlisting> |
---|
| 1462 | <![CDATA[int i = 0; int j; |
---|
| 1463 | var_type<int>::type vi(var(i)), vj(var(j)); |
---|
| 1464 | for_each(a.begin(), a.end(), (vj = _1, _1 = vi, vi = vj));]]> |
---|
| 1465 | </programlisting> |
---|
| 1466 | </para> |
---|
| 1467 | <para> |
---|
| 1468 | Here is an example of naming a delayed constant: |
---|
| 1469 | <programlisting> |
---|
| 1470 | <![CDATA[constant_type<char>::type space(constant(' ')); |
---|
| 1471 | for_each(a.begin(),a.end(), cout << space << _1);]]> |
---|
| 1472 | </programlisting> |
---|
| 1473 | </para> |
---|
| 1474 | |
---|
| 1475 | </simplesect> |
---|
| 1476 | |
---|
| 1477 | <simplesect> |
---|
| 1478 | <title>About assignment and subscript operators</title> |
---|
| 1479 | |
---|
| 1480 | <para> |
---|
| 1481 | As described in <xref linkend="lambda.assignment_and_subscript"/>, assignment and subscripting operators are always defined as member functions. |
---|
| 1482 | This means, that for expressions of the form |
---|
| 1483 | <literal>x = y</literal> or <literal>x[y]</literal> to be interpreted as lambda expressions, the left-hand operand <literal>x</literal> must be a lambda expression. |
---|
| 1484 | Consequently, it is sometimes necessary to use <literal>var</literal> for this purpose. |
---|
| 1485 | We repeat the example from <xref linkend="lambda.assignment_and_subscript"/>: |
---|
| 1486 | |
---|
| 1487 | <programlisting> |
---|
| 1488 | int i; |
---|
| 1489 | i = _1; // error |
---|
| 1490 | var(i) = _1; // ok |
---|
| 1491 | </programlisting> |
---|
| 1492 | </para> |
---|
| 1493 | |
---|
| 1494 | <para> |
---|
| 1495 | |
---|
| 1496 | Note that the compound assignment operators <literal>+=</literal>, <literal>-=</literal> etc. can be defined as non-member functions, and thus they are interpreted as lambda expressions even if only the right-hand operand is a lambda expression. |
---|
| 1497 | Nevertheless, it is perfectly ok to delay the left operand explicitly. |
---|
| 1498 | For example, <literal>i += _1</literal> is equivalent to <literal>var(i) += _1</literal>. |
---|
| 1499 | </para> |
---|
| 1500 | </simplesect> |
---|
| 1501 | |
---|
| 1502 | </section> |
---|
| 1503 | |
---|
| 1504 | <section id="lambda.lambda_expressions_for_control_structures"> |
---|
| 1505 | <title>Lambda expressions for control structures</title> |
---|
| 1506 | |
---|
| 1507 | <para> |
---|
| 1508 | BLL defines several functions to create lambda functors that represent control structures. |
---|
| 1509 | They all take lambda functors as parameters and return <literal>void</literal>. |
---|
| 1510 | To start with an example, the following code outputs all even elements of some container <literal>a</literal>: |
---|
| 1511 | |
---|
| 1512 | <programlisting> |
---|
| 1513 | <![CDATA[for_each(a.begin(), a.end(), |
---|
| 1514 | if_then(_1 % 2 == 0, cout << _1));]]> |
---|
| 1515 | </programlisting> |
---|
| 1516 | </para> |
---|
| 1517 | |
---|
| 1518 | <para> |
---|
| 1519 | The BLL supports the following function templates for control structures: |
---|
| 1520 | |
---|
| 1521 | <programlisting> |
---|
| 1522 | if_then(condition, then_part) |
---|
| 1523 | if_then_else(condition, then_part, else_part) |
---|
| 1524 | if_then_else_return(condition, then_part, else_part) |
---|
| 1525 | while_loop(condition, body) |
---|
| 1526 | while_loop(condition) // no body case |
---|
| 1527 | do_while_loop(condition, body) |
---|
| 1528 | do_while_loop(condition) // no body case |
---|
| 1529 | for_loop(init, condition, increment, body) |
---|
| 1530 | for_loop(init, condition, increment) // no body case |
---|
| 1531 | switch_statement(...) |
---|
| 1532 | </programlisting> |
---|
| 1533 | |
---|
| 1534 | The return types of all control construct lambda functor is |
---|
| 1535 | <literal>void</literal>, except for <literal>if_then_else_return</literal>, |
---|
| 1536 | which wraps a call to the conditional operator |
---|
| 1537 | <programlisting> |
---|
| 1538 | condition ? then_part : else_part |
---|
| 1539 | </programlisting> |
---|
| 1540 | The return type rules for this operator are somewhat complex. |
---|
| 1541 | Basically, if the branches have the same type, this type is the return type. |
---|
| 1542 | If the type of the branches differ, one branch, say of type |
---|
| 1543 | <literal>A</literal>, must be convertible to the other branch, |
---|
| 1544 | say of type <literal>B</literal>. |
---|
| 1545 | In this situation, the result type is <literal>B</literal>. |
---|
| 1546 | Further, if the common type is an lvalue, the return type will be an lvalue |
---|
| 1547 | too. |
---|
| 1548 | </para> |
---|
| 1549 | |
---|
| 1550 | |
---|
| 1551 | <para> |
---|
| 1552 | Delayed variables tend to be commonplace in control structure lambda expressions. |
---|
| 1553 | For instance, here we use the <literal>var</literal> function to turn the arguments of <literal>for_loop</literal> into lambda expressions. |
---|
| 1554 | The effect of the code is to add 1 to each element of a two-dimensional array: |
---|
| 1555 | |
---|
| 1556 | <programlisting> |
---|
| 1557 | <![CDATA[int a[5][10]; int i; |
---|
| 1558 | for_each(a, a+5, |
---|
| 1559 | for_loop(var(i)=0, var(i)<10, ++var(i), |
---|
| 1560 | _1[var(i)] += 1));]]> |
---|
| 1561 | </programlisting> |
---|
| 1562 | |
---|
| 1563 | <!-- |
---|
| 1564 | As explained in <xref linkend="lambda.delaying_constants_and_variables"/>, we can avoid the repeated use of wrapping of <literal>var</literal> if we define it beforehand: |
---|
| 1565 | |
---|
| 1566 | <programlisting> |
---|
| 1567 | <![CDATA[int i; |
---|
| 1568 | var_type<int>::type vi(var(i)); |
---|
| 1569 | for_each(a, a+5, |
---|
| 1570 | for_loop(vi=0, vi<10, ++vi, _1[vi] += 6));]]> |
---|
| 1571 | </programlisting> |
---|
| 1572 | |
---|
| 1573 | --> |
---|
| 1574 | </para> |
---|
| 1575 | |
---|
| 1576 | <para> |
---|
| 1577 | The BLL supports an alternative syntax for control expressions, suggested |
---|
| 1578 | by Joel de Guzmann. |
---|
| 1579 | By overloading the <literal>operator[]</literal> we can |
---|
| 1580 | get a closer resemblance with the built-in control structures: |
---|
| 1581 | |
---|
| 1582 | <programlisting> |
---|
| 1583 | <![CDATA[if_(condition)[then_part] |
---|
| 1584 | if_(condition)[then_part].else_[else_part] |
---|
| 1585 | while_(condition)[body] |
---|
| 1586 | do_[body].while_(condition) |
---|
| 1587 | for_(init, condition, increment)[body]]]> |
---|
| 1588 | </programlisting> |
---|
| 1589 | |
---|
| 1590 | For example, using this syntax the <literal>if_then</literal> example above |
---|
| 1591 | can be written as: |
---|
| 1592 | <programlisting> |
---|
| 1593 | <![CDATA[for_each(a.begin(), a.end(), |
---|
| 1594 | if_(_1 % 2 == 0)[ cout << _1 ])]]> |
---|
| 1595 | </programlisting> |
---|
| 1596 | |
---|
| 1597 | As more experience is gained, we may end up deprecating one or the other |
---|
| 1598 | of these syntaces. |
---|
| 1599 | |
---|
| 1600 | </para> |
---|
| 1601 | |
---|
| 1602 | |
---|
| 1603 | |
---|
| 1604 | <section id="lambda.switch_statement"> |
---|
| 1605 | <title>Switch statement</title> |
---|
| 1606 | </section> |
---|
| 1607 | |
---|
| 1608 | <para> |
---|
| 1609 | The lambda expressions for <literal>switch</literal> control structures are more complex since the number of cases may vary. |
---|
| 1610 | The general form of a switch lambda expression is: |
---|
| 1611 | |
---|
| 1612 | <programlisting> |
---|
| 1613 | switch_statement(<parameter>condition</parameter>, |
---|
| 1614 | case_statement<<parameter>label</parameter>>(<parameter>lambda expression</parameter>), |
---|
| 1615 | case_statement<<parameter>label</parameter>>(<parameter>lambda expression</parameter>), |
---|
| 1616 | ... |
---|
| 1617 | default_statement(<parameter>lambda expression</parameter>) |
---|
| 1618 | ) |
---|
| 1619 | </programlisting> |
---|
| 1620 | |
---|
| 1621 | The <literal><parameter>condition</parameter></literal> argument must be a lambda expression that creates a lambda functor with an integral return type. |
---|
| 1622 | The different cases are created with the <literal>case_statement</literal> functions, and the optional default case with the <literal>default_statement</literal> function. |
---|
| 1623 | The case labels are given as explicitly specified template arguments to <literal>case_statement</literal> functions and |
---|
| 1624 | <literal>break</literal> statements are implicitly part of each case. |
---|
| 1625 | For example, <literal><![CDATA[case_statement<1>(a)]]></literal>, where <literal>a</literal> is some lambda functor, generates the code: |
---|
| 1626 | |
---|
| 1627 | <programlisting> |
---|
| 1628 | case 1: |
---|
| 1629 | <parameter>evaluate lambda functor</parameter> a; |
---|
| 1630 | break; |
---|
| 1631 | </programlisting> |
---|
| 1632 | The <literal>switch_statement</literal> function is specialized for up to 9 case statements. |
---|
| 1633 | |
---|
| 1634 | </para> |
---|
| 1635 | |
---|
| 1636 | <para> |
---|
| 1637 | As a concrete example, the following code iterates over some container <literal>v</literal> and ouptuts <quote>zero</quote> for each <literal>0</literal>, <quote>one</quote> for each <literal>1</literal>, and <quote>other: <parameter>n</parameter></quote> for any other value <parameter>n</parameter>. |
---|
| 1638 | Note that another lambda expression is sequenced after the <literal>switch_statement</literal> to output a line break after each element: |
---|
| 1639 | |
---|
| 1640 | <programlisting> |
---|
| 1641 | <![CDATA[std::for_each(v.begin(), v.end(), |
---|
| 1642 | ( |
---|
| 1643 | switch_statement( |
---|
| 1644 | _1, |
---|
| 1645 | case_statement<0>(std::cout << constant("zero")), |
---|
| 1646 | case_statement<1>(std::cout << constant("one")), |
---|
| 1647 | default_statement(cout << constant("other: ") << _1) |
---|
| 1648 | ), |
---|
| 1649 | cout << constant("\n") |
---|
| 1650 | ) |
---|
| 1651 | );]]> |
---|
| 1652 | </programlisting> |
---|
| 1653 | </para> |
---|
| 1654 | |
---|
| 1655 | </section> |
---|
| 1656 | |
---|
| 1657 | <section id="lambda.exceptions"> |
---|
| 1658 | <title>Exceptions</title> |
---|
| 1659 | |
---|
| 1660 | <para> |
---|
| 1661 | The BLL provides lambda functors that throw and catch exceptions. |
---|
| 1662 | Lambda functors for throwing exceptions are created with the unary function <literal>throw_exception</literal>. |
---|
| 1663 | The argument to this function is the exception to be thrown, or a lambda functor which creates the exception to be thrown. |
---|
| 1664 | A lambda functor for rethrowing exceptions is created with the nullary <literal>rethrow</literal> function. |
---|
| 1665 | </para> |
---|
| 1666 | |
---|
| 1667 | <para> |
---|
| 1668 | Lambda expressions for handling exceptions are somewhat more complex. |
---|
| 1669 | The general form of a lambda expression for try catch blocks is as follows: |
---|
| 1670 | |
---|
| 1671 | <programlisting> |
---|
| 1672 | try_catch( |
---|
| 1673 | <parameter>lambda expression</parameter>, |
---|
| 1674 | catch_exception<<parameter>type</parameter>>(<parameter>lambda expression</parameter>), |
---|
| 1675 | catch_exception<<parameter>type</parameter>>(<parameter>lambda expression</parameter>), |
---|
| 1676 | ... |
---|
| 1677 | catch_all(<parameter>lambda expression</parameter>) |
---|
| 1678 | ) |
---|
| 1679 | </programlisting> |
---|
| 1680 | |
---|
| 1681 | The first lambda expression is the try block. |
---|
| 1682 | Each <literal>catch_exception</literal> defines a catch block where the |
---|
| 1683 | explicitly specified template argument defines the type of the exception |
---|
| 1684 | to catch. |
---|
| 1685 | |
---|
| 1686 | The lambda expression within the <literal>catch_exception</literal> defines |
---|
| 1687 | the actions to take if the exception is caught. |
---|
| 1688 | |
---|
| 1689 | Note that the resulting exception handlers catch the exceptions as |
---|
| 1690 | references, i.e., <literal>catch_exception<T>(...)</literal> |
---|
| 1691 | results in the catch block: |
---|
| 1692 | |
---|
| 1693 | <programlisting> |
---|
| 1694 | catch(T& e) { ... } |
---|
| 1695 | </programlisting> |
---|
| 1696 | |
---|
| 1697 | The last catch block can alternatively be a call to |
---|
| 1698 | <literal>catch_exception<<parameter>type</parameter>></literal> |
---|
| 1699 | or to |
---|
| 1700 | <literal>catch_all</literal>, which is the lambda expression equivalent to |
---|
| 1701 | <literal>catch(...)</literal>. |
---|
| 1702 | |
---|
| 1703 | </para> |
---|
| 1704 | |
---|
| 1705 | <para> |
---|
| 1706 | |
---|
| 1707 | The <xref linkend="ex:exceptions"/> demonstrates the use of the BLL |
---|
| 1708 | exception handling tools. |
---|
| 1709 | The first handler catches exceptions of type <literal>foo_exception</literal>. |
---|
| 1710 | Note the use of <literal>_1</literal> placeholder in the body of the handler. |
---|
| 1711 | </para> |
---|
| 1712 | |
---|
| 1713 | <para> |
---|
| 1714 | The second handler shows how to throw exceptions, and demonstrates the |
---|
| 1715 | use of the <emphasis>exception placeholder</emphasis> <literal>_e</literal>. |
---|
| 1716 | |
---|
| 1717 | It is a special placeholder, which refers to the caught exception object |
---|
| 1718 | within the handler body. |
---|
| 1719 | |
---|
| 1720 | Here we are handling an exception of type <literal>std::exception</literal>, |
---|
| 1721 | which carries a string explaining the cause of the exception. |
---|
| 1722 | |
---|
| 1723 | This explanation can be queried with the zero-argument member |
---|
| 1724 | function <literal>what</literal>. |
---|
| 1725 | |
---|
| 1726 | The expression |
---|
| 1727 | <literal>bind(&std::exception::what, _e)</literal> creates the lambda |
---|
| 1728 | function for making that call. |
---|
| 1729 | |
---|
| 1730 | Note that <literal>_e</literal> cannot be used outside of an exception handler lambda expression. |
---|
| 1731 | <!--Violating this rule is caught by the compiler.--> |
---|
| 1732 | |
---|
| 1733 | The last line of the second handler constructs a new exception object and |
---|
| 1734 | throws that with <literal>throw exception</literal>. |
---|
| 1735 | |
---|
| 1736 | Constructing and destructing objects within lambda expressions is |
---|
| 1737 | explained in <xref linkend="lambda.construction_and_destruction"/> |
---|
| 1738 | </para> |
---|
| 1739 | |
---|
| 1740 | <para> |
---|
| 1741 | Finally, the third handler (<literal>catch_all</literal>) demonstrates |
---|
| 1742 | rethrowing exceptions. |
---|
| 1743 | </para> |
---|
| 1744 | |
---|
| 1745 | <example id="ex:exceptions"> |
---|
| 1746 | <title>Throwing and handling exceptions in lambda expressions.</title> |
---|
| 1747 | <programlisting> |
---|
| 1748 | <![CDATA[for_each( |
---|
| 1749 | a.begin(), a.end(), |
---|
| 1750 | try_catch( |
---|
| 1751 | bind(foo, _1), // foo may throw |
---|
| 1752 | catch_exception<foo_exception>( |
---|
| 1753 | cout << constant("Caught foo_exception: ") |
---|
| 1754 | << "foo was called with argument = " << _1 |
---|
| 1755 | ), |
---|
| 1756 | catch_exception<std::exception>( |
---|
| 1757 | cout << constant("Caught std::exception: ") |
---|
| 1758 | << bind(&std::exception::what, _e), |
---|
| 1759 | throw_exception(bind(constructor<bar_exception>(), _1))) |
---|
| 1760 | ), |
---|
| 1761 | catch_all( |
---|
| 1762 | (cout << constant("Unknown"), rethrow()) |
---|
| 1763 | ) |
---|
| 1764 | ) |
---|
| 1765 | );]]> |
---|
| 1766 | </programlisting> |
---|
| 1767 | </example> |
---|
| 1768 | |
---|
| 1769 | </section> |
---|
| 1770 | |
---|
| 1771 | <section id="lambda.construction_and_destruction"> |
---|
| 1772 | <title>Construction and destruction</title> |
---|
| 1773 | |
---|
| 1774 | |
---|
| 1775 | <para> |
---|
| 1776 | Operators <literal>new</literal> and <literal>delete</literal> can be |
---|
| 1777 | overloaded, but their return types are fixed. |
---|
| 1778 | |
---|
| 1779 | Particularly, the return types cannot be lambda functors, |
---|
| 1780 | which prevents them to be overloaded for lambda expressions. |
---|
| 1781 | |
---|
| 1782 | It is not possible to take the address of a constructor, |
---|
| 1783 | hence constructors cannot be used as target functions in bind expressions. |
---|
| 1784 | |
---|
| 1785 | The same is true for destructors. |
---|
| 1786 | |
---|
| 1787 | As a way around these constraints, BLL defines wrapper classes for |
---|
| 1788 | <literal>new</literal> and <literal>delete</literal> calls, |
---|
| 1789 | as well as for constructors and destructors. |
---|
| 1790 | |
---|
| 1791 | Instances of these classes are function objects, that can be used as |
---|
| 1792 | target functions of bind expressions. |
---|
| 1793 | |
---|
| 1794 | For example: |
---|
| 1795 | |
---|
| 1796 | <programlisting> |
---|
| 1797 | <![CDATA[int* a[10]; |
---|
| 1798 | for_each(a, a+10, _1 = bind(new_ptr<int>())); |
---|
| 1799 | for_each(a, a+10, bind(delete_ptr(), _1));]]> |
---|
| 1800 | </programlisting> |
---|
| 1801 | |
---|
| 1802 | The <literal>new_ptr<int>()</literal> expression creates |
---|
| 1803 | a function object that calls <literal>new int()</literal> when invoked, |
---|
| 1804 | and wrapping that inside <literal>bind</literal> makes it a lambda functor. |
---|
| 1805 | |
---|
| 1806 | In the same way, the expression <literal>delete_ptr()</literal> creates |
---|
| 1807 | a function object that invokes <literal>delete</literal> on its argument. |
---|
| 1808 | |
---|
| 1809 | Note that <literal>new_ptr<<parameter>T</parameter>>()</literal> |
---|
| 1810 | can take arguments as well. |
---|
| 1811 | |
---|
| 1812 | They are passed directly to the constructor invocation and thus allow |
---|
| 1813 | calls to constructors which take arguments. |
---|
| 1814 | |
---|
| 1815 | </para> |
---|
| 1816 | |
---|
| 1817 | <para> |
---|
| 1818 | |
---|
| 1819 | As an example of constructor calls in lambda expressions, |
---|
| 1820 | the following code reads integers from two containers <literal>x</literal> |
---|
| 1821 | and <literal>y</literal>, |
---|
| 1822 | constructs pairs out of them and inserts them into a third container: |
---|
| 1823 | |
---|
| 1824 | <programlisting> |
---|
| 1825 | <![CDATA[vector<pair<int, int> > v; |
---|
| 1826 | transform(x.begin(), x.end(), y.begin(), back_inserter(v), |
---|
| 1827 | bind(constructor<pair<int, int> >(), _1, _2));]]> |
---|
| 1828 | </programlisting> |
---|
| 1829 | |
---|
| 1830 | <xref linkend="table:constructor_destructor_fos"/> lists all the function |
---|
| 1831 | objects related to creating and destroying objects, |
---|
| 1832 | showing the expression to create and call the function object, |
---|
| 1833 | and the effect of evaluating that expression. |
---|
| 1834 | |
---|
| 1835 | </para> |
---|
| 1836 | |
---|
| 1837 | |
---|
| 1838 | |
---|
| 1839 | <table id="table:constructor_destructor_fos"> |
---|
| 1840 | <title>Construction and destruction related function objects.</title> |
---|
| 1841 | <tgroup cols="2"> |
---|
| 1842 | <thead> |
---|
| 1843 | <row> |
---|
| 1844 | <entry>Function object call</entry> |
---|
| 1845 | <entry>Wrapped expression</entry> |
---|
| 1846 | </row> |
---|
| 1847 | </thead> |
---|
| 1848 | <tbody> |
---|
| 1849 | <row> |
---|
| 1850 | <entry><literal>constructor<T>()(<parameter>arg_list</parameter>)</literal></entry> |
---|
| 1851 | <entry>T(<parameter>arg_list</parameter>)</entry> |
---|
| 1852 | </row> |
---|
| 1853 | <row> |
---|
| 1854 | <entry><literal>destructor()(a)</literal></entry> |
---|
| 1855 | <entry><literal>a.~A()</literal>, where <literal>a</literal> is of type <literal>A</literal></entry> |
---|
| 1856 | </row> |
---|
| 1857 | <row> |
---|
| 1858 | <entry><literal>destructor()(pa)</literal></entry> |
---|
| 1859 | <entry><literal>pa->~A()</literal>, where <literal>pa</literal> is of type <literal>A*</literal></entry> |
---|
| 1860 | </row> |
---|
| 1861 | <row> |
---|
| 1862 | <entry><literal>new_ptr<T>()(<parameter>arg_list</parameter>)</literal></entry> |
---|
| 1863 | <entry><literal>new T(<parameter>arg_list</parameter>)</literal></entry> |
---|
| 1864 | </row> |
---|
| 1865 | <row> |
---|
| 1866 | <entry><literal>new_array<T>()(sz)</literal></entry> |
---|
| 1867 | <entry><literal>new T[sz]</literal></entry> |
---|
| 1868 | </row> |
---|
| 1869 | <row> |
---|
| 1870 | <entry><literal>delete_ptr()(p)</literal></entry> |
---|
| 1871 | <entry><literal>delete p</literal></entry> |
---|
| 1872 | </row> |
---|
| 1873 | <row> |
---|
| 1874 | <entry><literal>delete_array()(p)</literal></entry> |
---|
| 1875 | <entry><literal>delete p[]</literal></entry> |
---|
| 1876 | </row> |
---|
| 1877 | |
---|
| 1878 | |
---|
| 1879 | </tbody> |
---|
| 1880 | </tgroup> |
---|
| 1881 | </table> |
---|
| 1882 | |
---|
| 1883 | </section> |
---|
| 1884 | |
---|
| 1885 | |
---|
| 1886 | <section> |
---|
| 1887 | <title>Special lambda expressions</title> |
---|
| 1888 | |
---|
| 1889 | <section> |
---|
| 1890 | <title>Preventing argument substitution</title> |
---|
| 1891 | |
---|
| 1892 | <para> |
---|
| 1893 | When a lambda functor is called, the default behavior is to substitute |
---|
| 1894 | the actual arguments for the placeholders within all subexpressions. |
---|
| 1895 | |
---|
| 1896 | This section describes the tools to prevent the substitution and |
---|
| 1897 | evaluation of a subexpression, and explains when these tools should be used. |
---|
| 1898 | </para> |
---|
| 1899 | |
---|
| 1900 | |
---|
| 1901 | <para> |
---|
| 1902 | The arguments to a bind expression can be arbitrary lambda expressions, |
---|
| 1903 | e.g., other bind expressions. |
---|
| 1904 | |
---|
| 1905 | For example: |
---|
| 1906 | |
---|
| 1907 | <programlisting> |
---|
| 1908 | int foo(int); int bar(int); |
---|
| 1909 | ... |
---|
| 1910 | int i; |
---|
| 1911 | bind(foo, bind(bar, _1)(i); |
---|
| 1912 | </programlisting> |
---|
| 1913 | |
---|
| 1914 | The last line makes the call <literal>foo(bar(i));</literal> |
---|
| 1915 | |
---|
| 1916 | Note that the first argument in a bind expression, the target function, |
---|
| 1917 | is no exception, and can thus be a bind expression too. |
---|
| 1918 | |
---|
| 1919 | The innermost lambda functor just has to return something that can be used |
---|
| 1920 | as a target function: another lambda functor, function pointer, |
---|
| 1921 | pointer to member function etc. |
---|
| 1922 | |
---|
| 1923 | For example, in the following code the innermost lambda functor makes |
---|
| 1924 | a selection between two functions, and returns a pointer to one of them: |
---|
| 1925 | |
---|
| 1926 | <programlisting> |
---|
| 1927 | int add(int a, int b) { return a+b; } |
---|
| 1928 | int mul(int a, int b) { return a*b; } |
---|
| 1929 | |
---|
| 1930 | int(*)(int, int) add_or_mul(bool x) { |
---|
| 1931 | return x ? add : mul; |
---|
| 1932 | } |
---|
| 1933 | |
---|
| 1934 | bool condition; int i; int j; |
---|
| 1935 | ... |
---|
| 1936 | bind(bind(&add_or_mul, _1), _2, _3)(condition, i, j); |
---|
| 1937 | </programlisting> |
---|
| 1938 | |
---|
| 1939 | </para> |
---|
| 1940 | |
---|
| 1941 | |
---|
| 1942 | |
---|
| 1943 | <section id="lambda.unlambda"> |
---|
| 1944 | <title>Unlambda</title> |
---|
| 1945 | |
---|
| 1946 | <para>A nested bind expression may occur inadvertently, |
---|
| 1947 | if the target function is a variable with a type that depends on a |
---|
| 1948 | template parameter. |
---|
| 1949 | |
---|
| 1950 | Typically the target function could be a formal parameter of a |
---|
| 1951 | function template. |
---|
| 1952 | |
---|
| 1953 | In such a case, the programmer may not know whether the target function is a lambda functor or not. |
---|
| 1954 | </para> |
---|
| 1955 | |
---|
| 1956 | <para>Consider the following function template: |
---|
| 1957 | |
---|
| 1958 | <programlisting> |
---|
| 1959 | <![CDATA[template<class F> |
---|
| 1960 | int nested(const F& f) { |
---|
| 1961 | int x; |
---|
| 1962 | ... |
---|
| 1963 | bind(f, _1)(x); |
---|
| 1964 | ... |
---|
| 1965 | }]]> |
---|
| 1966 | </programlisting> |
---|
| 1967 | |
---|
| 1968 | Somewhere inside the function the formal parameter |
---|
| 1969 | <literal>f</literal> is used as a target function in a bind expression. |
---|
| 1970 | |
---|
| 1971 | In order for this <literal>bind</literal> call to be valid, |
---|
| 1972 | <literal>f</literal> must be a unary function. |
---|
| 1973 | |
---|
| 1974 | Suppose the following two calls to <literal>nested</literal> are made: |
---|
| 1975 | |
---|
| 1976 | <programlisting> |
---|
| 1977 | <![CDATA[int foo(int); |
---|
| 1978 | int bar(int, int); |
---|
| 1979 | nested(&foo); |
---|
| 1980 | nested(bind(bar, 1, _1));]]> |
---|
| 1981 | </programlisting> |
---|
| 1982 | |
---|
| 1983 | Both are unary functions, or function objects, with appropriate argument |
---|
| 1984 | and return types, but the latter will not compile. |
---|
| 1985 | |
---|
| 1986 | In the latter call, the bind expression inside <literal>nested</literal> |
---|
| 1987 | will become: |
---|
| 1988 | |
---|
| 1989 | <programlisting> |
---|
| 1990 | bind(bind(bar, 1, _1), _1) |
---|
| 1991 | </programlisting> |
---|
| 1992 | |
---|
| 1993 | When this is invoked with <literal>x</literal>, |
---|
| 1994 | after substituitions we end up trying to call |
---|
| 1995 | |
---|
| 1996 | <programlisting> |
---|
| 1997 | bar(1, x)(x) |
---|
| 1998 | </programlisting> |
---|
| 1999 | |
---|
| 2000 | which is an error. |
---|
| 2001 | |
---|
| 2002 | The call to <literal>bar</literal> returns int, |
---|
| 2003 | not a unary function or function object. |
---|
| 2004 | </para> |
---|
| 2005 | |
---|
| 2006 | <para> |
---|
| 2007 | In the example above, the intent of the bind expression in the |
---|
| 2008 | <literal>nested</literal> function is to treat <literal>f</literal> |
---|
| 2009 | as an ordinary function object, instead of a lambda functor. |
---|
| 2010 | |
---|
| 2011 | The BLL provides the function template <literal>unlambda</literal> to |
---|
| 2012 | express this: a lambda functor wrapped inside <literal>unlambda</literal> |
---|
| 2013 | is not a lambda functor anymore, and does not take part into the |
---|
| 2014 | argument substitution process. |
---|
| 2015 | |
---|
| 2016 | Note that for all other argument types <literal>unlambda</literal> is |
---|
| 2017 | an identity operation, except for making non-const objects const. |
---|
| 2018 | </para> |
---|
| 2019 | |
---|
| 2020 | <para> |
---|
| 2021 | Using <literal>unlambda</literal>, the <literal>nested</literal> |
---|
| 2022 | function is written as: |
---|
| 2023 | |
---|
| 2024 | <programlisting> |
---|
| 2025 | <![CDATA[template<class F> |
---|
| 2026 | int nested(const F& f) { |
---|
| 2027 | int x; |
---|
| 2028 | ... |
---|
| 2029 | bind(unlambda(f), _1)(x); |
---|
| 2030 | ... |
---|
| 2031 | }]]> |
---|
| 2032 | </programlisting> |
---|
| 2033 | |
---|
| 2034 | </para> |
---|
| 2035 | |
---|
| 2036 | </section> |
---|
| 2037 | |
---|
| 2038 | <section> |
---|
| 2039 | <title>Protect</title> |
---|
| 2040 | |
---|
| 2041 | <para> |
---|
| 2042 | The <literal>protect</literal> function is related to unlambda. |
---|
| 2043 | |
---|
| 2044 | It is also used to prevent the argument substitution taking place, |
---|
| 2045 | but whereas <literal>unlambda</literal> turns a lambda functor into |
---|
| 2046 | an ordinary function object for good, <literal>protect</literal> does |
---|
| 2047 | this temporarily, for just one evaluation round. |
---|
| 2048 | |
---|
| 2049 | For example: |
---|
| 2050 | |
---|
| 2051 | <programlisting> |
---|
| 2052 | int x = 1, y = 10; |
---|
| 2053 | (_1 + protect(_1 + 2))(x)(y); |
---|
| 2054 | </programlisting> |
---|
| 2055 | |
---|
| 2056 | The first call substitutes <literal>x</literal> for the leftmost |
---|
| 2057 | <literal>_1</literal>, and results in another lambda functor |
---|
| 2058 | <literal>x + (_1 + 2)</literal>, which after the call with |
---|
| 2059 | <literal>y</literal> becomes <literal>x + (y + 2)</literal>, |
---|
| 2060 | and thus finally 13. |
---|
| 2061 | </para> |
---|
| 2062 | |
---|
| 2063 | <para> |
---|
| 2064 | Primary motivation for including <literal>protect</literal> into the library, |
---|
| 2065 | was to allow nested STL algorithm invocations |
---|
| 2066 | (<xref linkend="lambda.nested_stl_algorithms"/>). |
---|
| 2067 | </para> |
---|
| 2068 | |
---|
| 2069 | </section> |
---|
| 2070 | |
---|
| 2071 | </section> |
---|
| 2072 | |
---|
| 2073 | <section id="lambda.rvalues_as_actual_arguments"> |
---|
| 2074 | <title>Rvalues as actual arguments to lambda functors</title> |
---|
| 2075 | |
---|
| 2076 | <!-- <para><emphasis>This section and all of its subsections |
---|
| 2077 | are no longer (or currently) relevant; |
---|
| 2078 | acual arguments can be non-const rvalues and these workarounds are thus |
---|
| 2079 | not needed. |
---|
| 2080 | The section can, however, become relevant again, if in the future BLL will support |
---|
| 2081 | lambda functors with higher arities than 3.</emphasis></para> --> |
---|
| 2082 | |
---|
| 2083 | <para> |
---|
| 2084 | Actual arguments to the lambda functors cannot be non-const rvalues. |
---|
| 2085 | This is due to a deliberate design decision: either we have this restriction, |
---|
| 2086 | or there can be no side-effects to the actual arguments. |
---|
| 2087 | |
---|
| 2088 | There are ways around this limitation. |
---|
| 2089 | |
---|
| 2090 | We repeat the example from section |
---|
| 2091 | <xref linkend="lambda.actual_arguments_to_lambda_functors"/> and list the |
---|
| 2092 | different solutions: |
---|
| 2093 | |
---|
| 2094 | <programlisting> |
---|
| 2095 | int i = 1; int j = 2; |
---|
| 2096 | (_1 + _2)(i, j); // ok |
---|
| 2097 | (_1 + _2)(1, 2); // error (!) |
---|
| 2098 | </programlisting> |
---|
| 2099 | |
---|
| 2100 | <orderedlist> |
---|
| 2101 | <listitem> |
---|
| 2102 | <para> |
---|
| 2103 | If the rvalue is of a class type, the return type of the function that |
---|
| 2104 | creates the rvalue should be defined as const. |
---|
| 2105 | Due to an unfortunate language restriction this does not work for |
---|
| 2106 | built-in types, as built-in rvalues cannot be const qualified. |
---|
| 2107 | </para> |
---|
| 2108 | </listitem> |
---|
| 2109 | |
---|
| 2110 | <listitem> |
---|
| 2111 | <para> |
---|
| 2112 | If the lambda function call is accessible, the <literal>make_const</literal> |
---|
| 2113 | function can be used to <emphasis>constify</emphasis> the rvalue. E.g.: |
---|
| 2114 | |
---|
| 2115 | <programlisting> |
---|
| 2116 | (_1 + _2)(make_const(1), make_const(2)); // ok |
---|
| 2117 | </programlisting> |
---|
| 2118 | |
---|
| 2119 | Commonly the lambda function call site is inside a standard algorithm |
---|
| 2120 | function template, preventing this solution to be used. |
---|
| 2121 | |
---|
| 2122 | </para> |
---|
| 2123 | </listitem> |
---|
| 2124 | |
---|
| 2125 | <listitem> |
---|
| 2126 | <para> |
---|
| 2127 | If neither of the above is possible, the lambda expression can be wrapped |
---|
| 2128 | in a <literal>const_parameters</literal> function. |
---|
| 2129 | It creates another type of lambda functor, which takes its arguments as |
---|
| 2130 | const references. For example: |
---|
| 2131 | |
---|
| 2132 | <programlisting> |
---|
| 2133 | const_parameters(_1 + _2)(1, 2); // ok |
---|
| 2134 | </programlisting> |
---|
| 2135 | |
---|
| 2136 | Note that <literal>const_parameters</literal> makes all arguments const. |
---|
| 2137 | Hence, in the case were one of the arguments is a non-const rvalue, |
---|
| 2138 | and another argument needs to be passed as a non-const reference, |
---|
| 2139 | this approach cannot be used. |
---|
| 2140 | </para> |
---|
| 2141 | |
---|
| 2142 | </listitem> |
---|
| 2143 | |
---|
| 2144 | <listitem> |
---|
| 2145 | <para>If none of the above is possible, there is still one solution, |
---|
| 2146 | which unfortunately can break const correctness. |
---|
| 2147 | |
---|
| 2148 | The solution is yet another lambda functor wrapper, which we have named |
---|
| 2149 | <literal>break_const</literal> to alert the user of the potential dangers |
---|
| 2150 | of this function. |
---|
| 2151 | |
---|
| 2152 | The <literal>break_const</literal> function creates a lambda functor that |
---|
| 2153 | takes its arguments as const, and casts away constness prior to the call |
---|
| 2154 | to the original wrapped lambda functor. |
---|
| 2155 | |
---|
| 2156 | For example: |
---|
| 2157 | <programlisting> |
---|
| 2158 | int i; |
---|
| 2159 | ... |
---|
| 2160 | (_1 += _2)(i, 2); // error, 2 is a non-const rvalue |
---|
| 2161 | const_parameters(_1 += _2)(i, 2); // error, i becomes const |
---|
| 2162 | break_const(_1 += _2)(i, 2); // ok, but dangerous |
---|
| 2163 | </programlisting> |
---|
| 2164 | |
---|
| 2165 | Note, that the results of <literal> break_const</literal> or |
---|
| 2166 | <literal>const_parameters</literal> are not lambda functors, |
---|
| 2167 | so they cannot be used as subexpressions of lambda expressions. For instance: |
---|
| 2168 | |
---|
| 2169 | <programlisting> |
---|
| 2170 | break_const(_1 + _2) + _3; // fails. |
---|
| 2171 | const_parameters(_1 + _2) + _3; // fails. |
---|
| 2172 | </programlisting> |
---|
| 2173 | |
---|
| 2174 | However, this kind of code should never be necessary, |
---|
| 2175 | since calls to sub lambda functors are made inside the BLL, |
---|
| 2176 | and are not affected by the non-const rvalue problem. |
---|
| 2177 | </para> |
---|
| 2178 | </listitem> |
---|
| 2179 | |
---|
| 2180 | </orderedlist> |
---|
| 2181 | |
---|
| 2182 | </para> |
---|
| 2183 | </section> |
---|
| 2184 | |
---|
| 2185 | </section> |
---|
| 2186 | |
---|
| 2187 | |
---|
| 2188 | <section> |
---|
| 2189 | <title>Casts, sizeof and typeid</title> |
---|
| 2190 | |
---|
| 2191 | <section id="lambda.cast_expressions"> |
---|
| 2192 | <title> |
---|
| 2193 | Cast expressions |
---|
| 2194 | </title> |
---|
| 2195 | <para> |
---|
| 2196 | The BLL defines its counterparts for the four cast expressions |
---|
| 2197 | <literal>static_cast</literal>, <literal>dynamic_cast</literal>, |
---|
| 2198 | <literal>const_cast</literal> and <literal>reinterpret_cast</literal>. |
---|
| 2199 | |
---|
| 2200 | The BLL versions of the cast expressions have the prefix |
---|
| 2201 | <literal>ll_</literal>. |
---|
| 2202 | |
---|
| 2203 | The type to cast to is given as an explicitly specified template argument, |
---|
| 2204 | and the sole argument is the expression from which to perform the cast. |
---|
| 2205 | |
---|
| 2206 | If the argument is a lambda functor, the lambda functor is evaluated first. |
---|
| 2207 | |
---|
| 2208 | For example, the following code uses <literal>ll_dynamic_cast</literal> |
---|
| 2209 | to count the number of <literal>derived</literal> instances in the container |
---|
| 2210 | <literal>a</literal>: |
---|
| 2211 | |
---|
| 2212 | <programlisting> |
---|
| 2213 | <![CDATA[class base {}; |
---|
| 2214 | class derived : public base {}; |
---|
| 2215 | |
---|
| 2216 | vector<base*> a; |
---|
| 2217 | ... |
---|
| 2218 | int count = 0; |
---|
| 2219 | for_each(a.begin(), a.end(), |
---|
| 2220 | if_then(ll_dynamic_cast<derived*>(_1), ++var(count)));]]> |
---|
| 2221 | </programlisting> |
---|
| 2222 | </para> |
---|
| 2223 | </section> |
---|
| 2224 | |
---|
| 2225 | <section> |
---|
| 2226 | <title>Sizeof and typeid</title> |
---|
| 2227 | <para> |
---|
| 2228 | The BLL counterparts for these expressions are named |
---|
| 2229 | <literal>ll_sizeof</literal> and <literal>ll_typeid</literal>. |
---|
| 2230 | |
---|
| 2231 | Both take one argument, which can be a lambda expression. |
---|
| 2232 | The lambda functor created wraps the <literal>sizeof</literal> or |
---|
| 2233 | <literal>typeid</literal> call, and when the lambda functor is called |
---|
| 2234 | the wrapped operation is performed. |
---|
| 2235 | |
---|
| 2236 | For example: |
---|
| 2237 | |
---|
| 2238 | <programlisting> |
---|
| 2239 | <![CDATA[vector<base*> a; |
---|
| 2240 | ... |
---|
| 2241 | for_each(a.begin(), a.end(), |
---|
| 2242 | cout << bind(&type_info::name, ll_typeid(*_1)));]]> |
---|
| 2243 | </programlisting> |
---|
| 2244 | |
---|
| 2245 | Here <literal>ll_typeid</literal> creates a lambda functor for |
---|
| 2246 | calling <literal>typeid</literal> for each element. |
---|
| 2247 | |
---|
| 2248 | The result of a <literal>typeid</literal> call is an instance of |
---|
| 2249 | the <literal>type_info</literal> class, and the bind expression creates |
---|
| 2250 | a lambda functor for calling the <literal>name</literal> member |
---|
| 2251 | function of that class. |
---|
| 2252 | |
---|
| 2253 | </para> |
---|
| 2254 | </section> |
---|
| 2255 | |
---|
| 2256 | |
---|
| 2257 | |
---|
| 2258 | </section> |
---|
| 2259 | |
---|
| 2260 | <section id="lambda.nested_stl_algorithms"> |
---|
| 2261 | <title>Nesting STL algorithm invocations</title> |
---|
| 2262 | |
---|
| 2263 | <para> |
---|
| 2264 | The BLL defines common STL algorithms as function object classes, |
---|
| 2265 | instances of which can be used as target functions in bind expressions. |
---|
| 2266 | For example, the following code iterates over the elements of a |
---|
| 2267 | two-dimensional array, and computes their sum. |
---|
| 2268 | |
---|
| 2269 | <programlisting> |
---|
| 2270 | int a[100][200]; |
---|
| 2271 | int sum = 0; |
---|
| 2272 | |
---|
| 2273 | std::for_each(a, a + 100, |
---|
| 2274 | bind(ll::for_each(), _1, _1 + 200, protect(sum += _1))); |
---|
| 2275 | </programlisting> |
---|
| 2276 | |
---|
| 2277 | The BLL versions of the STL algorithms are classes, which define the function call operator (or several overloaded ones) to call the corresponding function templates in the <literal>std</literal> namespace. |
---|
| 2278 | All these structs are placed in the subnamespace <literal>boost::lambda:ll</literal>. |
---|
| 2279 | <!--The supported algorithms are listed in <xref linkend="table:nested_algorithms"/>.--> |
---|
| 2280 | </para> |
---|
| 2281 | |
---|
| 2282 | <para> |
---|
| 2283 | Note that there is no easy way to express an overloaded member function |
---|
| 2284 | call in a lambda expression. |
---|
| 2285 | |
---|
| 2286 | This limits the usefulness of nested STL algorithms, as for instance |
---|
| 2287 | the <literal>begin</literal> function has more than one overloaded |
---|
| 2288 | definitions in container templates. |
---|
| 2289 | |
---|
| 2290 | In general, something analogous to the pseudo-code below cannot be written: |
---|
| 2291 | |
---|
| 2292 | <programlisting> |
---|
| 2293 | std::for_each(a.begin(), a.end(), |
---|
| 2294 | bind(ll::for_each(), _1.begin(), _1.end(), protect(sum += _1))); |
---|
| 2295 | </programlisting> |
---|
| 2296 | |
---|
| 2297 | Some aid for common special cases can be provided though. |
---|
| 2298 | |
---|
| 2299 | The BLL defines two helper function object classes, |
---|
| 2300 | <literal>call_begin</literal> and <literal>call_end</literal>, |
---|
| 2301 | which wrap a call to the <literal>begin</literal> and, respectively, |
---|
| 2302 | <literal>end</literal> functions of a container, and return the |
---|
| 2303 | <literal>const_iterator</literal> type of the container. |
---|
| 2304 | |
---|
| 2305 | With these helper templates, the above code becomes: |
---|
| 2306 | <programlisting> |
---|
| 2307 | std::for_each(a.begin(), a.end(), |
---|
| 2308 | bind(ll::for_each(), |
---|
| 2309 | bind(call_begin(), _1), bind(call_end(), _1), |
---|
| 2310 | protect(sum += _1))); |
---|
| 2311 | </programlisting> |
---|
| 2312 | |
---|
| 2313 | </para> |
---|
| 2314 | |
---|
| 2315 | <!-- |
---|
| 2316 | <table id="table:nested_algorithms"> |
---|
| 2317 | <title>The nested STL algorithms.</title> |
---|
| 2318 | <tgroup cols="1"> |
---|
| 2319 | <thead> |
---|
| 2320 | <trow><entry>Otsikko</entry></trow> |
---|
| 2321 | </thead> |
---|
| 2322 | <tbody> |
---|
| 2323 | <row><entry><literal>for_each</literal></entry></row> |
---|
| 2324 | <row><entry><literal>find</literal></entry></row> |
---|
| 2325 | <row><entry><literal>find_if</literal></entry></row> |
---|
| 2326 | <row><entry><literal>find_end</literal></entry></row> |
---|
| 2327 | <row><entry><literal>find_first_of</literal></entry></row> |
---|
| 2328 | <row><entry><literal>transform</literal></entry></row> |
---|
| 2329 | </tbody> |
---|
| 2330 | </tgroup> |
---|
| 2331 | |
---|
| 2332 | </table> |
---|
| 2333 | |
---|
| 2334 | --> |
---|
| 2335 | |
---|
| 2336 | </section> |
---|
| 2337 | |
---|
| 2338 | |
---|
| 2339 | </section> |
---|
| 2340 | |
---|
| 2341 | |
---|
| 2342 | <!-- |
---|
| 2343 | <section> |
---|
| 2344 | <title>Common gothcas</title> |
---|
| 2345 | |
---|
| 2346 | calling member functions a.begin() |
---|
| 2347 | |
---|
| 2348 | calling templated functions ... |
---|
| 2349 | |
---|
| 2350 | </section> |
---|
| 2351 | |
---|
| 2352 | --> |
---|
| 2353 | |
---|
| 2354 | <section id="lambda.extending"> |
---|
| 2355 | <title>Extending return type deduction system</title> |
---|
| 2356 | |
---|
| 2357 | <para> |
---|
| 2358 | <!--The <xref linkend = "lambda.overriding_deduced_return_type"/> showed how to make BLL aware of the return type of a function object in bind expressions.--> |
---|
| 2359 | |
---|
| 2360 | In this section, we explain how to extend the return type deduction system |
---|
| 2361 | to cover user defined operators. |
---|
| 2362 | |
---|
| 2363 | In many cases this is not necessary, |
---|
| 2364 | as the BLL defines default return types for operators. |
---|
| 2365 | |
---|
| 2366 | For example, the default return type for all comparison operators is |
---|
| 2367 | <literal>bool</literal>, and as long as the user defined comparison operators |
---|
| 2368 | have a bool return type, there is no need to write new specializations |
---|
| 2369 | for the return type deduction classes. |
---|
| 2370 | |
---|
| 2371 | Sometimes this cannot be avoided, though. |
---|
| 2372 | |
---|
| 2373 | </para> |
---|
| 2374 | |
---|
| 2375 | <para> |
---|
| 2376 | The overloadable user defined operators are either unary or binary. |
---|
| 2377 | |
---|
| 2378 | For each arity, there are two traits templates that define the |
---|
| 2379 | return types of the different operators. |
---|
| 2380 | |
---|
| 2381 | Hence, the return type system can be extended by providing more |
---|
| 2382 | specializations for these templates. |
---|
| 2383 | |
---|
| 2384 | The templates for unary functors are |
---|
| 2385 | |
---|
| 2386 | <literal> |
---|
| 2387 | <![CDATA[plain_return_type_1<Action, A>]]> |
---|
| 2388 | </literal> |
---|
| 2389 | |
---|
| 2390 | and |
---|
| 2391 | |
---|
| 2392 | <literal> |
---|
| 2393 | <![CDATA[return_type_1<Action, A>]]> |
---|
| 2394 | </literal>, and |
---|
| 2395 | |
---|
| 2396 | <literal> |
---|
| 2397 | <![CDATA[plain_return_type_2<Action, A, B>]]> |
---|
| 2398 | </literal> |
---|
| 2399 | |
---|
| 2400 | and |
---|
| 2401 | |
---|
| 2402 | <literal> |
---|
| 2403 | <![CDATA[return_type_2<Action, A, B>]]> |
---|
| 2404 | </literal> |
---|
| 2405 | |
---|
| 2406 | respectively for binary functors. |
---|
| 2407 | |
---|
| 2408 | </para> |
---|
| 2409 | |
---|
| 2410 | <para> |
---|
| 2411 | The first parameter (<literal>Action</literal>) to all these templates |
---|
| 2412 | is the <emphasis>action</emphasis> class, which specifies the operator. |
---|
| 2413 | |
---|
| 2414 | Operators with similar return type rules are grouped together into |
---|
| 2415 | <emphasis>action groups</emphasis>, |
---|
| 2416 | and only the action class and action group together define the operator |
---|
| 2417 | unambiguously. |
---|
| 2418 | |
---|
| 2419 | As an example, the action type |
---|
| 2420 | <literal><![CDATA[arithmetic_action<plus_action>]]></literal> stands for |
---|
| 2421 | <literal>operator+</literal>. |
---|
| 2422 | |
---|
| 2423 | The complete listing of different action types is shown in |
---|
| 2424 | <xref linkend="table:actions"/>. |
---|
| 2425 | </para> |
---|
| 2426 | |
---|
| 2427 | <para> |
---|
| 2428 | The latter parameters, <literal>A</literal> in the unary case, |
---|
| 2429 | or <literal>A</literal> and <literal>B</literal> in the binary case, |
---|
| 2430 | stand for the argument types of the operator call. |
---|
| 2431 | |
---|
| 2432 | The two sets of templates, |
---|
| 2433 | <literal>plain_return_type_<parameter>n</parameter></literal> and |
---|
| 2434 | <literal>return_type_<parameter>n</parameter></literal> |
---|
| 2435 | (<parameter>n</parameter> is 1 or 2) differ in the way how parameter types |
---|
| 2436 | are presented to them. |
---|
| 2437 | |
---|
| 2438 | For the former templates, the parameter types are always provided as |
---|
| 2439 | non-reference types, and do not have const or volatile qualifiers. |
---|
| 2440 | |
---|
| 2441 | This makes specializing easy, as commonly one specialization for each |
---|
| 2442 | user defined operator, or operator group, is enough. |
---|
| 2443 | |
---|
| 2444 | On the other hand, if a particular operator is overloaded for different |
---|
| 2445 | cv-qualifications of the same argument types, |
---|
| 2446 | and the return types of these overloaded versions differ, a more fine-grained control is needed. |
---|
| 2447 | |
---|
| 2448 | Hence, for the latter templates, the parameter types preserve the |
---|
| 2449 | cv-qualifiers, and are non-reference types as well. |
---|
| 2450 | |
---|
| 2451 | The downside is, that for an overloaded set of operators of the |
---|
| 2452 | kind described above, one may end up needing up to |
---|
| 2453 | 16 <literal>return_type_2</literal> specializations. |
---|
| 2454 | </para> |
---|
| 2455 | |
---|
| 2456 | <para> |
---|
| 2457 | Suppose the user has overloaded the following operators for some user defined |
---|
| 2458 | types <literal>X</literal>, <literal>Y</literal> and <literal>Z</literal>: |
---|
| 2459 | |
---|
| 2460 | <programlisting> |
---|
| 2461 | <![CDATA[Z operator+(const X&, const Y&); |
---|
| 2462 | Z operator-(const X&, const Y&);]]> |
---|
| 2463 | </programlisting> |
---|
| 2464 | |
---|
| 2465 | Now, one can add a specialization stating, that if the left hand argument |
---|
| 2466 | is of type <literal>X</literal>, and the right hand one of type |
---|
| 2467 | <literal>Y</literal>, the return type of all such binary arithmetic |
---|
| 2468 | operators is <literal>Z</literal>: |
---|
| 2469 | |
---|
| 2470 | <programlisting> |
---|
| 2471 | <![CDATA[namespace boost { |
---|
| 2472 | namespace lambda { |
---|
| 2473 | |
---|
| 2474 | template<class Act> |
---|
| 2475 | struct plain_return_type_2<arithmetic_action<Act>, X, Y> { |
---|
| 2476 | typedef Z type; |
---|
| 2477 | }; |
---|
| 2478 | |
---|
| 2479 | } |
---|
| 2480 | }]]> |
---|
| 2481 | </programlisting> |
---|
| 2482 | |
---|
| 2483 | Having this specialization defined, BLL is capable of correctly |
---|
| 2484 | deducing the return type of the above two operators. |
---|
| 2485 | |
---|
| 2486 | Note, that the specializations must be in the same namespace, |
---|
| 2487 | <literal>::boost::lambda</literal>, with the primary template. |
---|
| 2488 | |
---|
| 2489 | For brevity, we do not show the namespace definitions in the examples below. |
---|
| 2490 | </para> |
---|
| 2491 | |
---|
| 2492 | <para> |
---|
| 2493 | It is possible to specialize on the level of an individual operator as well, |
---|
| 2494 | in addition to providing a specialization for a group of operators. |
---|
| 2495 | Say, we add a new arithmetic operator for argument types <literal>X</literal> |
---|
| 2496 | and <literal>Y</literal>: |
---|
| 2497 | |
---|
| 2498 | <programlisting> |
---|
| 2499 | <![CDATA[X operator*(const X&, const Y&);]]> |
---|
| 2500 | </programlisting> |
---|
| 2501 | |
---|
| 2502 | Our first rule for all arithmetic operators specifies that the return |
---|
| 2503 | type of this operator is <literal>Z</literal>, |
---|
| 2504 | which obviously is not the case. |
---|
| 2505 | Hence, we provide a new rule for the multiplication operator: |
---|
| 2506 | |
---|
| 2507 | <programlisting> |
---|
| 2508 | <![CDATA[template<> |
---|
| 2509 | struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> { |
---|
| 2510 | typedef X type; |
---|
| 2511 | };]]> |
---|
| 2512 | </programlisting> |
---|
| 2513 | </para> |
---|
| 2514 | |
---|
| 2515 | <para> |
---|
| 2516 | The specializations can define arbitrary mappings from the argument types |
---|
| 2517 | to the return type. |
---|
| 2518 | |
---|
| 2519 | Suppose we have some mathematical vector type, templated on the element type: |
---|
| 2520 | |
---|
| 2521 | <programlisting> |
---|
| 2522 | <![CDATA[template <class T> class my_vector;]]> |
---|
| 2523 | </programlisting> |
---|
| 2524 | |
---|
| 2525 | Suppose the addition operator is defined between any two |
---|
| 2526 | <literal>my_vector</literal> instantiations, |
---|
| 2527 | as long as the addition operator is defined between their element types. |
---|
| 2528 | |
---|
| 2529 | Furthermore, the element type of the resulting <literal>my_vector</literal> |
---|
| 2530 | is the same as the result type of the addition between the element types. |
---|
| 2531 | |
---|
| 2532 | E.g., adding <literal><![CDATA[my_vector<int>]]></literal> and |
---|
| 2533 | <literal><![CDATA[my_vector<double>]]></literal> results in |
---|
| 2534 | <literal><![CDATA[my_vector<double>]]></literal>. |
---|
| 2535 | |
---|
| 2536 | The BLL has traits classes to perform the implicit built-in and standard |
---|
| 2537 | type conversions between integral, floating point, and complex classes. |
---|
| 2538 | |
---|
| 2539 | Using BLL tools, the addition operator described above can be defined as: |
---|
| 2540 | |
---|
| 2541 | <programlisting> |
---|
| 2542 | <![CDATA[template<class A, class B> |
---|
| 2543 | my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type> |
---|
| 2544 | operator+(const my_vector<A>& a, const my_vector<B>& b) |
---|
| 2545 | { |
---|
| 2546 | typedef typename |
---|
| 2547 | return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; |
---|
| 2548 | return my_vector<res_type>(); |
---|
| 2549 | }]]> |
---|
| 2550 | </programlisting> |
---|
| 2551 | </para> |
---|
| 2552 | |
---|
| 2553 | <para> |
---|
| 2554 | To allow BLL to deduce the type of <literal>my_vector</literal> |
---|
| 2555 | additions correctly, we can define: |
---|
| 2556 | |
---|
| 2557 | <programlisting> |
---|
| 2558 | <![CDATA[template<class A, class B> |
---|
| 2559 | class plain_return_type_2<arithmetic_action<plus_action>, |
---|
| 2560 | my_vector<A>, my_vector<B> > { |
---|
| 2561 | typedef typename |
---|
| 2562 | return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; |
---|
| 2563 | public: |
---|
| 2564 | typedef my_vector<res_type> type; |
---|
| 2565 | };]]> |
---|
| 2566 | </programlisting> |
---|
| 2567 | Note, that we are reusing the existing specializations for the |
---|
| 2568 | BLL <literal>return_type_2</literal> template, |
---|
| 2569 | which require that the argument types are references. |
---|
| 2570 | </para> |
---|
| 2571 | |
---|
| 2572 | <!-- TODO: is an example of specifying the other level needed at all --> |
---|
| 2573 | <!-- TODO: comma operator is a special case for that --> |
---|
| 2574 | |
---|
| 2575 | <table id = "table:actions"> |
---|
| 2576 | <title>Action types</title> |
---|
| 2577 | <tgroup cols="2"> |
---|
| 2578 | <tbody> |
---|
| 2579 | |
---|
| 2580 | <row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[arithmetic_action<plus_action>]]></literal></entry></row> |
---|
| 2581 | <row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[arithmetic_action<minus_action>]]></literal></entry></row> |
---|
| 2582 | <row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[arithmetic_action<multiply_action>]]></literal></entry></row> |
---|
| 2583 | <row><entry><literal><![CDATA[/]]></literal></entry><entry><literal><![CDATA[arithmetic_action<divide_action>]]></literal></entry></row> |
---|
| 2584 | <row><entry><literal><![CDATA[%]]></literal></entry><entry><literal><![CDATA[arithmetic_action<remainder_action>]]></literal></entry></row> |
---|
| 2585 | |
---|
| 2586 | |
---|
| 2587 | |
---|
| 2588 | <row><entry><literal><![CDATA[+]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<plus_action>]]></literal></entry></row> |
---|
| 2589 | <row><entry><literal><![CDATA[-]]></literal></entry><entry><literal><![CDATA[unary_arithmetic_action<minus_action>]]></literal></entry></row> |
---|
| 2590 | |
---|
| 2591 | |
---|
| 2592 | |
---|
| 2593 | <row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[bitwise_action<and_action>]]></literal></entry></row> |
---|
| 2594 | <row><entry><literal><![CDATA[|]]></literal></entry><entry><literal><![CDATA[bitwise_action<or_action>]]></literal></entry></row> |
---|
| 2595 | <row><entry><literal><![CDATA[~]]></literal></entry><entry><literal><![CDATA[bitwise_action<not_action>]]></literal></entry></row> |
---|
| 2596 | <row><entry><literal><![CDATA[^]]></literal></entry><entry><literal><![CDATA[bitwise_action<xor_action>]]></literal></entry></row> |
---|
| 2597 | <row><entry><literal><![CDATA[<<]]></literal></entry><entry><literal><![CDATA[bitwise_action<leftshift_action_no_stream>]]></literal></entry></row> |
---|
| 2598 | <row><entry><literal><![CDATA[>>]]></literal></entry><entry><literal><![CDATA[bitwise_action<rightshift_action_no_stream>]]></literal></entry></row> |
---|
| 2599 | |
---|
| 2600 | |
---|
| 2601 | |
---|
| 2602 | <row><entry><literal><![CDATA[&&]]></literal></entry><entry><literal><![CDATA[logical_action<and_action>]]></literal></entry></row> |
---|
| 2603 | <row><entry><literal><![CDATA[||]]></literal></entry><entry><literal><![CDATA[logical_action<or_action>]]></literal></entry></row> |
---|
| 2604 | <row><entry><literal><![CDATA[!]]></literal></entry><entry><literal><![CDATA[logical_action<not_action>]]></literal></entry></row> |
---|
| 2605 | |
---|
| 2606 | |
---|
| 2607 | |
---|
| 2608 | <row><entry><literal><![CDATA[<]]></literal></entry><entry><literal><![CDATA[relational_action<less_action>]]></literal></entry></row> |
---|
| 2609 | <row><entry><literal><![CDATA[>]]></literal></entry><entry><literal><![CDATA[relational_action<greater_action>]]></literal></entry></row> |
---|
| 2610 | <row><entry><literal><![CDATA[<=]]></literal></entry><entry><literal><![CDATA[relational_action<lessorequal_action>]]></literal></entry></row> |
---|
| 2611 | <row><entry><literal><![CDATA[>=]]></literal></entry><entry><literal><![CDATA[relational_action<greaterorequal_action>]]></literal></entry></row> |
---|
| 2612 | <row><entry><literal><![CDATA[==]]></literal></entry><entry><literal><![CDATA[relational_action<equal_action>]]></literal></entry></row> |
---|
| 2613 | <row><entry><literal><![CDATA[!=]]></literal></entry><entry><literal><![CDATA[relational_action<notequal_action>]]></literal></entry></row> |
---|
| 2614 | |
---|
| 2615 | |
---|
| 2616 | |
---|
| 2617 | <row><entry><literal><![CDATA[+=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<plus_action>]]></literal></entry></row> |
---|
| 2618 | <row><entry><literal><![CDATA[-=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<minus_action>]]></literal></entry></row> |
---|
| 2619 | <row><entry><literal><![CDATA[*=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<multiply_action>]]></literal></entry></row> |
---|
| 2620 | <row><entry><literal><![CDATA[/=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<divide_action>]]></literal></entry></row> |
---|
| 2621 | <row><entry><literal><![CDATA[%=]]></literal></entry><entry><literal><![CDATA[arithmetic_assignment_action<remainder_action>]]></literal></entry></row> |
---|
| 2622 | |
---|
| 2623 | |
---|
| 2624 | |
---|
| 2625 | <row><entry><literal><![CDATA[&=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<and_action>]]></literal></entry></row> |
---|
| 2626 | <row><entry><literal><![CDATA[=|]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<or_action>]]></literal></entry></row> |
---|
| 2627 | <row><entry><literal><![CDATA[^=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<xor_action>]]></literal></entry></row> |
---|
| 2628 | <row><entry><literal><![CDATA[<<=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<leftshift_action>]]></literal></entry></row> |
---|
| 2629 | <row><entry><literal><![CDATA[>>=]]></literal></entry><entry><literal><![CDATA[bitwise_assignment_action<rightshift_action>]]></literal></entry></row> |
---|
| 2630 | |
---|
| 2631 | |
---|
| 2632 | |
---|
| 2633 | <row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<increment_action>]]></literal></entry></row> |
---|
| 2634 | <row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[pre_increment_decrement_action<decrement_action>]]></literal></entry></row> |
---|
| 2635 | <row><entry><literal><![CDATA[++]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<increment_action>]]></literal></entry></row> |
---|
| 2636 | <row><entry><literal><![CDATA[--]]></literal></entry><entry><literal><![CDATA[post_increment_decrement_action<decrement_action>]]></literal></entry></row> |
---|
| 2637 | |
---|
| 2638 | |
---|
| 2639 | |
---|
| 2640 | <row><entry><literal><![CDATA[&]]></literal></entry><entry><literal><![CDATA[other_action<address_of_action>]]></literal></entry></row> |
---|
| 2641 | <row><entry><literal><![CDATA[*]]></literal></entry><entry><literal><![CDATA[other_action<contents_of_action>]]></literal></entry></row> |
---|
| 2642 | <row><entry><literal><![CDATA[,]]></literal></entry><entry><literal><![CDATA[other_action<comma_action>]]></literal></entry></row> |
---|
| 2643 | |
---|
| 2644 | </tbody> |
---|
| 2645 | </tgroup> |
---|
| 2646 | </table> |
---|
| 2647 | |
---|
| 2648 | </section> |
---|
| 2649 | |
---|
| 2650 | |
---|
| 2651 | <section> |
---|
| 2652 | <title>Practical considerations</title> |
---|
| 2653 | |
---|
| 2654 | |
---|
| 2655 | <section> |
---|
| 2656 | <title>Performance</title> |
---|
| 2657 | |
---|
| 2658 | <para>In theory, all overhead of using STL algorithms and lambda functors |
---|
| 2659 | compared to hand written loops can be optimized away, just as the overhead |
---|
| 2660 | from standard STL function objects and binders can. |
---|
| 2661 | |
---|
| 2662 | Depending on the compiler, this can also be true in practice. |
---|
| 2663 | We ran two tests with the GCC 3.0.4 compiler on 1.5 GHz Intel Pentium 4. |
---|
| 2664 | The optimization flag -03 was used. |
---|
| 2665 | </para> |
---|
| 2666 | |
---|
| 2667 | <para> |
---|
| 2668 | In the first test we compared lambda functors against explicitly written |
---|
| 2669 | function objects. |
---|
| 2670 | We used both of these styles to define unary functions which multiply the |
---|
| 2671 | argument repeatedly by itself. |
---|
| 2672 | We started with the identity function, going up to |
---|
| 2673 | x<superscript>5</superscript>. |
---|
| 2674 | The expressions were called inside a <literal>std::transform</literal> loop, |
---|
| 2675 | reading the argument from one <literal><![CDATA[std::vector<int>]]></literal> |
---|
| 2676 | and placing the result into another. |
---|
| 2677 | The length of the vectors was 100 elements. |
---|
| 2678 | The running times are listed in |
---|
| 2679 | <xref linkend="table:increasing_arithmetic_test"/>. |
---|
| 2680 | |
---|
| 2681 | We can observe that there is no significant difference between the |
---|
| 2682 | two approaches. |
---|
| 2683 | </para> |
---|
| 2684 | |
---|
| 2685 | <para> |
---|
| 2686 | In the second test we again used <literal>std::transform</literal> to |
---|
| 2687 | perform an operation to each element in a 100-element long vector. |
---|
| 2688 | This time the element type of the vectors was <literal>double</literal> |
---|
| 2689 | and we started with very simple arithmetic expressions and moved to |
---|
| 2690 | more complex ones. |
---|
| 2691 | The running times are listed in <xref linkend="table:ll_vs_stl_test"/>. |
---|
| 2692 | |
---|
| 2693 | Here, we also included classic STL style unnamed functions into tests. |
---|
| 2694 | We do not show these expressions, as they get rather complex. |
---|
| 2695 | For example, the |
---|
| 2696 | last expression in <xref linkend="table:ll_vs_stl_test"/> written with |
---|
| 2697 | classic STL tools contains 7 calls to <literal>compose2</literal>, |
---|
| 2698 | 8 calls to <literal>bind1st</literal> |
---|
| 2699 | and altogether 14 constructor invocations for creating |
---|
| 2700 | <literal>multiplies</literal>, <literal>minus</literal> |
---|
| 2701 | and <literal>plus</literal> objects. |
---|
| 2702 | |
---|
| 2703 | In this test the BLL expressions are a little slower (roughly 10% on average, |
---|
| 2704 | less than 14% in all cases) |
---|
| 2705 | than the corresponding hand-written function objects. |
---|
| 2706 | The performance hit is a bit greater with classic STL expressions, |
---|
| 2707 | up to 27% for the simplest expressios. |
---|
| 2708 | </para> |
---|
| 2709 | |
---|
| 2710 | <para> |
---|
| 2711 | The tests suggest that the BLL does not introduce a loss of performance |
---|
| 2712 | compared to STL function objects. |
---|
| 2713 | With a reasonable optimizing compiler, one should expect the performance characteristics be comparable to using classic STL. |
---|
| 2714 | Moreover, with simple expressions the performance can be expected to be close |
---|
| 2715 | to that of explicitly written function objects. |
---|
| 2716 | |
---|
| 2717 | <!-- We repeated both tests with the KAI C++ 4.0f compiler (using +K2 -O3 flags), |
---|
| 2718 | generally considered a good optimizing compiler. |
---|
| 2719 | We do not list the results here, since the running times for the two alternatives in the first test were essentially the same, just as the running times |
---|
| 2720 | for the three different alternatives in the second test. |
---|
| 2721 | These tests suggest there to be no performance penalty at all |
---|
| 2722 | with a good optimizing compiler. |
---|
| 2723 | --> |
---|
| 2724 | |
---|
| 2725 | Note however, that evaluating a lambda functor consist of a sequence of calls to small functions that are declared inline. |
---|
| 2726 | If the compiler fails to actually expand these functions inline, |
---|
| 2727 | the performance can suffer. |
---|
| 2728 | The running time can more than double if this happens. |
---|
| 2729 | Although the above tests do not include such an expression, we have experienced |
---|
| 2730 | this for some seemingly simple expressions. |
---|
| 2731 | |
---|
| 2732 | |
---|
| 2733 | <table id = "table:increasing_arithmetic_test"> |
---|
| 2734 | <title>Test 1</title> |
---|
| 2735 | <caption>CPU time of expressions with integer multiplication written as a lambda expression and as a traditional hand-coded function object class. |
---|
| 2736 | The running times are expressed in arbitrary units.</caption> |
---|
| 2737 | <tgroup cols="3"> |
---|
| 2738 | <thead> |
---|
| 2739 | <row> |
---|
| 2740 | <entry>expression</entry><entry>lambda expression</entry><entry>hand-coded function object</entry></row> |
---|
| 2741 | </thead> |
---|
| 2742 | |
---|
| 2743 | <tbody> |
---|
| 2744 | |
---|
| 2745 | <row> |
---|
| 2746 | <entry>x</entry><entry>240</entry><entry>230</entry> |
---|
| 2747 | </row> |
---|
| 2748 | |
---|
| 2749 | <row> |
---|
| 2750 | <entry>x*x</entry><entry>340</entry><entry>350</entry> |
---|
| 2751 | </row> |
---|
| 2752 | |
---|
| 2753 | <row> |
---|
| 2754 | <entry>x*x*x</entry><entry>770</entry><entry>760</entry> |
---|
| 2755 | </row> |
---|
| 2756 | |
---|
| 2757 | <row> |
---|
| 2758 | <entry>x*x*x*x</entry><entry>1180</entry><entry>1210</entry> |
---|
| 2759 | </row> |
---|
| 2760 | |
---|
| 2761 | <row> |
---|
| 2762 | <entry>x*x*x*x*x</entry><entry>1950</entry><entry>1910</entry> |
---|
| 2763 | </row> |
---|
| 2764 | |
---|
| 2765 | </tbody> |
---|
| 2766 | </tgroup> |
---|
| 2767 | </table> |
---|
| 2768 | </para> |
---|
| 2769 | |
---|
| 2770 | <!-- |
---|
| 2771 | 16:19:49 bench [601] ./arith.out 100 1000000 |
---|
| 2772 | |
---|
| 2773 | Number of elements = 100 |
---|
| 2774 | L1 : 240 |
---|
| 2775 | L2 : 340 |
---|
| 2776 | L3 : 770 |
---|
| 2777 | L4 : 1180 |
---|
| 2778 | L5 : 1950 |
---|
| 2779 | |
---|
| 2780 | P2 : 1700 |
---|
| 2781 | P3 : 2130 |
---|
| 2782 | P4 : 2530 |
---|
| 2783 | P5 : 3000 |
---|
| 2784 | |
---|
| 2785 | F1 : 230 |
---|
| 2786 | F2 : 350 |
---|
| 2787 | F3 : 760 |
---|
| 2788 | F4 : 1210 |
---|
| 2789 | F5 : 1910 |
---|
| 2790 | |
---|
| 2791 | |
---|
| 2792 | Number of elements = 100 |
---|
| 2793 | Number of outer_iters = 1000000 |
---|
| 2794 | L1 : 330 |
---|
| 2795 | L2 : 350 |
---|
| 2796 | L3 : 470 |
---|
| 2797 | L4 : 620 |
---|
| 2798 | L5 : 1660 |
---|
| 2799 | LP : 1230 |
---|
| 2800 | C1 : 370 |
---|
| 2801 | C2 : 370 |
---|
| 2802 | C3 : 500 |
---|
| 2803 | C4 : 670 |
---|
| 2804 | C5 : 1660 |
---|
| 2805 | CP : 1770 |
---|
| 2806 | F1 : 290 |
---|
| 2807 | F2 : 310 |
---|
| 2808 | F3 : 420 |
---|
| 2809 | F4 : 600 |
---|
| 2810 | F5 : 1460 |
---|
| 2811 | FP : 1040 |
---|
| 2812 | |
---|
| 2813 | --> |
---|
| 2814 | |
---|
| 2815 | |
---|
| 2816 | <para> |
---|
| 2817 | <table id = "table:ll_vs_stl_test"> |
---|
| 2818 | <title>Test 2</title> |
---|
| 2819 | <caption>CPU time of arithmetic expressions written as lambda |
---|
| 2820 | expressions, as classic STL unnamed functions (using <literal>compose2</literal>, <literal>bind1st</literal> etc.) and as traditional hand-coded function object classes. |
---|
| 2821 | Using BLL terminology, |
---|
| 2822 | <literal>a</literal> and <literal>b</literal> are bound arguments in the expressions, and <literal>x</literal> is open. |
---|
| 2823 | All variables were of types <literal>double</literal>. |
---|
| 2824 | The running times are expressed in arbitrary units.</caption> |
---|
| 2825 | <tgroup cols="4"> |
---|
| 2826 | <thead> |
---|
| 2827 | <row> |
---|
| 2828 | <entry>expression</entry><entry>lambda expression</entry><entry>classic STL expression</entry><entry>hand-coded function object</entry></row> |
---|
| 2829 | </thead> |
---|
| 2830 | |
---|
| 2831 | <tbody> |
---|
| 2832 | |
---|
| 2833 | <row> |
---|
| 2834 | <entry>ax</entry><entry>330</entry><entry>370</entry><entry>290</entry> |
---|
| 2835 | </row> |
---|
| 2836 | |
---|
| 2837 | <row> |
---|
| 2838 | <entry>-ax</entry><entry>350</entry><entry>370</entry><entry>310</entry> |
---|
| 2839 | </row> |
---|
| 2840 | |
---|
| 2841 | <row> |
---|
| 2842 | <entry>ax-(a+x)</entry><entry>470</entry><entry>500</entry><entry>420</entry> |
---|
| 2843 | </row> |
---|
| 2844 | |
---|
| 2845 | <row> |
---|
| 2846 | <entry>(ax-(a+x))(a+x)</entry><entry>620</entry><entry>670</entry><entry>600</entry> |
---|
| 2847 | </row> |
---|
| 2848 | |
---|
| 2849 | <row> |
---|
| 2850 | <entry>((ax) - (a+x))(bx - (b+x))(ax - (b+x))(bx - (a+x))</entry><entry>1660</entry><entry>1660</entry><entry>1460</entry> |
---|
| 2851 | </row> |
---|
| 2852 | |
---|
| 2853 | </tbody> |
---|
| 2854 | </tgroup> |
---|
| 2855 | |
---|
| 2856 | </table> |
---|
| 2857 | </para> |
---|
| 2858 | |
---|
| 2859 | |
---|
| 2860 | <para>Some additional performance testing with an earlier version of the |
---|
| 2861 | library is described |
---|
| 2862 | <xref linkend="cit:jarvi:00"/>. |
---|
| 2863 | </para> |
---|
| 2864 | |
---|
| 2865 | </section> |
---|
| 2866 | <section> |
---|
| 2867 | <title>About compiling</title> |
---|
| 2868 | |
---|
| 2869 | <para>The BLL uses templates rather heavily, performing numerous recursive instantiations of the same templates. |
---|
| 2870 | This has (at least) three implications: |
---|
| 2871 | <itemizedlist> |
---|
| 2872 | |
---|
| 2873 | <listitem> |
---|
| 2874 | <para> |
---|
| 2875 | While it is possible to write incredibly complex lambda expressions, it probably isn't a good idea. |
---|
| 2876 | Compiling such expressions may end up requiring a lot of memory |
---|
| 2877 | at compile time, and being slow to compile. |
---|
| 2878 | </para> |
---|
| 2879 | </listitem> |
---|
| 2880 | |
---|
| 2881 | |
---|
| 2882 | <listitem> |
---|
| 2883 | <para> |
---|
| 2884 | The types of lambda functors that result from even the simplest lambda expressions are cryptic. |
---|
| 2885 | Usually the programmer doesn't need to deal with the lambda functor types at all, but in the case of an error in a lambda expression, the compiler usually outputs the types of the lambda functors involved. |
---|
| 2886 | This can make the error messages very long and difficult to interpret, particularly if the compiler outputs the whole chain of template instantiations. |
---|
| 2887 | </para> |
---|
| 2888 | </listitem> |
---|
| 2889 | |
---|
| 2890 | <listitem> |
---|
| 2891 | <para> |
---|
| 2892 | The C++ Standard suggests a template nesting level of 17 to help detect infinite recursion. |
---|
| 2893 | Complex lambda templates can easily exceed this limit. |
---|
| 2894 | Most compilers allow a greater number of nested templates, but commonly require the limit explicitly increased with a command line argument. |
---|
| 2895 | </para> |
---|
| 2896 | </listitem> |
---|
| 2897 | </itemizedlist></para> |
---|
| 2898 | |
---|
| 2899 | </section> |
---|
| 2900 | |
---|
| 2901 | <section> |
---|
| 2902 | <title>Portability</title> |
---|
| 2903 | <para> |
---|
| 2904 | The BLL works with the following compilers, that is, the compilers are capable of compiling the test cases that are included with the BLL: |
---|
| 2905 | |
---|
| 2906 | <itemizedlist> |
---|
| 2907 | <listitem>GCC 3.0.4 |
---|
| 2908 | </listitem> |
---|
| 2909 | <listitem>KCC 4.0f with EDG 2.43.1 |
---|
| 2910 | </listitem> |
---|
| 2911 | <listitem>GCC 2.96 (fails with one test case, the <filename>exception_test.cpp</filename> results in an internal compiler error. |
---|
| 2912 | ) |
---|
| 2913 | |
---|
| 2914 | </listitem> |
---|
| 2915 | </itemizedlist> |
---|
| 2916 | </para> |
---|
| 2917 | |
---|
| 2918 | <section> |
---|
| 2919 | <title>Test coverage</title> |
---|
| 2920 | |
---|
| 2921 | <para>The following list describes the test files included and the features that each file covers: |
---|
| 2922 | |
---|
| 2923 | <itemizedlist> |
---|
| 2924 | <listitem> |
---|
| 2925 | <para> |
---|
| 2926 | <filename>bind_tests_simple.cpp</filename> : Bind expressions of different arities and types of target functions: function pointers, function objects and member functions. |
---|
| 2927 | Function composition with bind expressions.</para> |
---|
| 2928 | </listitem> |
---|
| 2929 | |
---|
| 2930 | <listitem> |
---|
| 2931 | <para><filename>bind_tests_simple_function_references.cpp</filename> : |
---|
| 2932 | Repeats all tests from <filename moreinfo="none">bind_tests_simple.cpp</filename> where the target function is a function pointer, but uses function references instead. |
---|
| 2933 | </para></listitem> |
---|
| 2934 | |
---|
| 2935 | |
---|
| 2936 | <listitem> |
---|
| 2937 | <para><filename>bind_tests_advanced.cpp</filename> : Contains tests for nested bind expressions, <literal>unlambda</literal>, <literal>protect</literal>, <literal>const_parameters</literal> and <literal>break_const</literal>. |
---|
| 2938 | Tests passing lambda functors as actual arguments to other lambda functors, currying, and using the <literal>sig</literal> template to specify the return type of a function object. |
---|
| 2939 | </para> |
---|
| 2940 | </listitem> |
---|
| 2941 | |
---|
| 2942 | <listitem> |
---|
| 2943 | <para> |
---|
| 2944 | <filename>operator_tests_simple.cpp</filename> : |
---|
| 2945 | Tests using all operators that are overloaded for lambda expressions, that is, unary and binary arithmetic, |
---|
| 2946 | bitwise, |
---|
| 2947 | comparison, |
---|
| 2948 | logical, |
---|
| 2949 | increment and decrement, |
---|
| 2950 | compound, |
---|
| 2951 | assignment, |
---|
| 2952 | subscrict, |
---|
| 2953 | address of, |
---|
| 2954 | dereference, and comma operators. |
---|
| 2955 | The streaming nature of shift operators is tested, as well as pointer arithmetic with plus and minus operators. |
---|
| 2956 | </para> |
---|
| 2957 | </listitem> |
---|
| 2958 | |
---|
| 2959 | <listitem> |
---|
| 2960 | <para><filename>member_pointer_test.cpp</filename> : The pointer to member operator is complex enough to warrant a separate test file. |
---|
| 2961 | </para> |
---|
| 2962 | </listitem> |
---|
| 2963 | |
---|
| 2964 | <listitem> |
---|
| 2965 | <para> |
---|
| 2966 | <filename>control_structures.cpp</filename> : |
---|
| 2967 | Tests for the looping and if constructs. |
---|
| 2968 | </para></listitem> |
---|
| 2969 | |
---|
| 2970 | <listitem> |
---|
| 2971 | <para> |
---|
| 2972 | <filename>switch_construct.cpp</filename> : |
---|
| 2973 | Includes tests for all supported arities of the switch statement, both with and without the default case. |
---|
| 2974 | </para> |
---|
| 2975 | </listitem> |
---|
| 2976 | |
---|
| 2977 | <listitem> |
---|
| 2978 | <para> |
---|
| 2979 | <filename>exception_test.cpp</filename> : |
---|
| 2980 | Includes tests for throwing exceptions and for try/catch constructs with varying number of catch blocks. |
---|
| 2981 | </para> |
---|
| 2982 | </listitem> |
---|
| 2983 | |
---|
| 2984 | <listitem> |
---|
| 2985 | <para> |
---|
| 2986 | <filename>constructor_tests.cpp</filename> : |
---|
| 2987 | Contains tests for <literal>constructor</literal>, <literal>destructor</literal>, <literal>new_ptr</literal>, <literal>delete_ptr</literal>, <literal>new_array</literal> and <literal>delete_array</literal>. |
---|
| 2988 | </para> |
---|
| 2989 | </listitem> |
---|
| 2990 | |
---|
| 2991 | <listitem> |
---|
| 2992 | <para> |
---|
| 2993 | <filename>cast_test.cpp</filename> : Tests for the four cast expressions, as well as <filename>typeid</filename> and <literal>sizeof</literal>. |
---|
| 2994 | </para> |
---|
| 2995 | </listitem> |
---|
| 2996 | |
---|
| 2997 | <listitem> |
---|
| 2998 | <para> |
---|
| 2999 | <filename>extending_return_type_traits.cpp</filename> : Tests extending the return type deduction system for user defined types. |
---|
| 3000 | Contains several user defined operators and the corresponding specializations for the return type deduction templates. |
---|
| 3001 | </para> |
---|
| 3002 | </listitem> |
---|
| 3003 | |
---|
| 3004 | <listitem> |
---|
| 3005 | <para> |
---|
| 3006 | <filename>is_instance_of_test.cpp</filename> : Includes tests for an internally used traits template, which can detect whether a given type is an instance of a certain template or not. |
---|
| 3007 | </para></listitem> |
---|
| 3008 | |
---|
| 3009 | <listitem> |
---|
| 3010 | <para> |
---|
| 3011 | <filename>bll_and_function.cpp</filename> : |
---|
| 3012 | Contains tests for using <literal>boost::function</literal> together with lambda functors. |
---|
| 3013 | </para></listitem> |
---|
| 3014 | |
---|
| 3015 | </itemizedlist> |
---|
| 3016 | |
---|
| 3017 | </para> |
---|
| 3018 | |
---|
| 3019 | </section> |
---|
| 3020 | |
---|
| 3021 | </section> |
---|
| 3022 | |
---|
| 3023 | |
---|
| 3024 | </section> |
---|
| 3025 | |
---|
| 3026 | |
---|
| 3027 | <section> |
---|
| 3028 | <title>Relation to other Boost libraries</title> |
---|
| 3029 | |
---|
| 3030 | <section> |
---|
| 3031 | <title>Boost Function</title> |
---|
| 3032 | |
---|
| 3033 | <para>Sometimes it is convenient to store lambda functors in variables. |
---|
| 3034 | 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. |
---|
| 3035 | <emphasis>The Boost Function library</emphasis> <xref linkend="cit:boost::function"/> defines wrappers for arbitrary function objects, for example |
---|
| 3036 | lambda functors; and these wrappers have types that are easy to type out. |
---|
| 3037 | |
---|
| 3038 | For example: |
---|
| 3039 | |
---|
| 3040 | <programlisting> |
---|
| 3041 | <![CDATA[boost::function<int(int, int)> f = _1 + _2; |
---|
| 3042 | boost::function<int&(int&)> g = (_1 += 10); |
---|
| 3043 | int i = 1, j = 2; |
---|
| 3044 | f(i, j); // returns 3 |
---|
| 3045 | g(i); // sets i to = 11;]]> |
---|
| 3046 | </programlisting> |
---|
| 3047 | |
---|
| 3048 | The return and parameter types of the wrapped function object must be written explicilty as the template argument to the wrapper template <literal>boost::function</literal>; even when lambda functors, which otherwise have generic parameters, are wrapped. |
---|
| 3049 | Wrapping a function object with <literal>boost::function</literal> introduces a performance cost comparable to virtual function dispatch, though virtual functions are not actually used. |
---|
| 3050 | |
---|
| 3051 | Note that storing lambda functors inside <literal>boost::function</literal> |
---|
| 3052 | introduces a danger. |
---|
| 3053 | Certain types of lambda functors may store references to the bound |
---|
| 3054 | arguments, instead as taking copies of the arguments of the lambda expression. |
---|
| 3055 | When temporary lambda functor objects are used |
---|
| 3056 | in STL algorithm invocations this is always safe, as the lambda functor gets |
---|
| 3057 | destructed immediately after the STL algortihm invocation is completed. |
---|
| 3058 | |
---|
| 3059 | However, a lambda functor wrapped inside <literal>boost::function</literal> |
---|
| 3060 | may continue to exist longer, creating the possibility of dangling references. |
---|
| 3061 | For example: |
---|
| 3062 | |
---|
| 3063 | <programlisting> |
---|
| 3064 | <![CDATA[int* sum = new int(); |
---|
| 3065 | *sum = 0; |
---|
| 3066 | boost::function<int&(int)> counter = *sum += _1; |
---|
| 3067 | counter(5); // ok, *sum = 5; |
---|
| 3068 | delete sum; |
---|
| 3069 | counter(3); // error, *sum does not exist anymore]]> |
---|
| 3070 | </programlisting> |
---|
| 3071 | |
---|
| 3072 | </para> |
---|
| 3073 | |
---|
| 3074 | </section> |
---|
| 3075 | |
---|
| 3076 | <section> |
---|
| 3077 | <title>Boost Bind</title> |
---|
| 3078 | <para> |
---|
| 3079 | <emphasis>The Boost Bind</emphasis> <xref linkend="cit:boost::bind"/> library has partially overlapping functionality with the BLL. |
---|
| 3080 | Basically, the Boost Bind library (BB in the sequel) implements the bind expression part of BLL. |
---|
| 3081 | There are, however, some semantical differerences. |
---|
| 3082 | </para> |
---|
| 3083 | <para> |
---|
| 3084 | The BLL and BB evolved separately, and have different implementations. |
---|
| 3085 | This means that the bind expressions from the BB cannot be used within |
---|
| 3086 | bind expressions, or within other type of lambda expressions, of the BLL. |
---|
| 3087 | The same holds for using BLL bind expressions in the BB. |
---|
| 3088 | The libraries can coexist, however, as |
---|
| 3089 | the names of the BB library are in <literal>boost</literal> namespace, |
---|
| 3090 | whereas the BLL names are in <literal>boost::lambda</literal> namespace. |
---|
| 3091 | </para> |
---|
| 3092 | |
---|
| 3093 | <para> |
---|
| 3094 | The BLL requires a compiler that is reasonably conformant to the |
---|
| 3095 | C++ standard, whereas the BB library is more portable, and works with |
---|
| 3096 | a larger set of compilers. |
---|
| 3097 | </para> |
---|
| 3098 | |
---|
| 3099 | <para> |
---|
| 3100 | The following two sections describe what are the semantic differences |
---|
| 3101 | between the bind expressions in BB and BLL. |
---|
| 3102 | </para> |
---|
| 3103 | |
---|
| 3104 | |
---|
| 3105 | |
---|
| 3106 | |
---|
| 3107 | <section> |
---|
| 3108 | <title>First argument of bind expression</title> |
---|
| 3109 | |
---|
| 3110 | In BB the first argument of the bind expression, the target function, |
---|
| 3111 | is treated differently from the other arguments, |
---|
| 3112 | as no argument substitution takes place within that argument. |
---|
| 3113 | In BLL the first argument is not a special case in this respect. |
---|
| 3114 | |
---|
| 3115 | For example: |
---|
| 3116 | |
---|
| 3117 | <programlisting> |
---|
| 3118 | <![CDATA[template<class F> |
---|
| 3119 | int foo(const F& f) { |
---|
| 3120 | int x; |
---|
| 3121 | .. |
---|
| 3122 | bind(f, _1)(x); |
---|
| 3123 | ... |
---|
| 3124 | }]]> |
---|
| 3125 | </programlisting> |
---|
| 3126 | |
---|
| 3127 | <programlisting> |
---|
| 3128 | <![CDATA[int bar(int, int); |
---|
| 3129 | nested(bind(bar, 1, _1));]]> |
---|
| 3130 | </programlisting> |
---|
| 3131 | |
---|
| 3132 | The bind expression inside <literal>foo</literal> becomes: |
---|
| 3133 | <programlisting> |
---|
| 3134 | bind(bind(bar, 1, _1), _1)(x) |
---|
| 3135 | </programlisting> |
---|
| 3136 | |
---|
| 3137 | The BLL interpretes this as: |
---|
| 3138 | <programlisting> |
---|
| 3139 | bar(1, x)(x) |
---|
| 3140 | </programlisting> |
---|
| 3141 | whereas the BB library as |
---|
| 3142 | <programlisting> |
---|
| 3143 | bar(1, x) |
---|
| 3144 | </programlisting> |
---|
| 3145 | |
---|
| 3146 | To get this functionality in BLL, the bind expression inside the <literal moreinfo="none">foo</literal> function can be written as: |
---|
| 3147 | <programlisting> |
---|
| 3148 | bind(unlambda(f), _1)(x); |
---|
| 3149 | </programlisting> |
---|
| 3150 | as explained in <xref linkend = "lambda.unlambda"/>. |
---|
| 3151 | |
---|
| 3152 | </section> |
---|
| 3153 | |
---|
| 3154 | |
---|
| 3155 | |
---|
| 3156 | |
---|
| 3157 | <para> |
---|
| 3158 | The BB library supports up to nine placeholders, while the BLL |
---|
| 3159 | defines only three placeholders. |
---|
| 3160 | The rationale for not providing more, is that the highest arity of the |
---|
| 3161 | function objects accepted by any STL algorithm is two. |
---|
| 3162 | The placeholder count is easy to increase in the BB library. |
---|
| 3163 | In BLL it is possible, but more laborous. |
---|
| 3164 | The BLL currently passes the actual arguments to the lambda functors |
---|
| 3165 | internally just as they are and does not wrap them inside a tuple object. |
---|
| 3166 | The reason for this is that some widely used compilers are not capable |
---|
| 3167 | of optimizing the intermediate tuple objects away. |
---|
| 3168 | The creation of the intermediate tuples would cause a significant |
---|
| 3169 | performance hit, particularly for the simplest (and thus the most common) |
---|
| 3170 | lambda functors. |
---|
| 3171 | We are working on a hybrid approach, which will allow more placeholders |
---|
| 3172 | but not compromise the performance of simple lambda functors. |
---|
| 3173 | </para> |
---|
| 3174 | |
---|
| 3175 | </section> |
---|
| 3176 | |
---|
| 3177 | </section> |
---|
| 3178 | |
---|
| 3179 | |
---|
| 3180 | <section> |
---|
| 3181 | <title>Contributors</title> |
---|
| 3182 | |
---|
| 3183 | The main body of the library was written by Jaakko Järvi and Gary Powell. |
---|
| 3184 | We've got outside help, suggestions and ideas from Jeremy Siek, Peter Higley, Peter Dimov, Valentin Bonnard, William Kempf. |
---|
| 3185 | We would particularly like to mention Joel de Guzmann and his work with |
---|
| 3186 | Phoenix which has influenced BLL significantly, making it considerably simpler |
---|
| 3187 | to extend the library with new features. |
---|
| 3188 | |
---|
| 3189 | </section> |
---|
| 3190 | |
---|
| 3191 | |
---|
| 3192 | |
---|
| 3193 | <appendix> |
---|
| 3194 | <title>Rationale for some of the design decisions</title> |
---|
| 3195 | |
---|
| 3196 | <section id="lambda.why_weak_arity"> |
---|
| 3197 | <title> |
---|
| 3198 | Lambda functor arity |
---|
| 3199 | </title> |
---|
| 3200 | |
---|
| 3201 | <para> |
---|
| 3202 | The highest placeholder index in a lambda expression determines the arity of the resulting function object. |
---|
| 3203 | However, this is just the minimal arity, as the function object can take arbitrarily many arguments; those not needed are discarded. |
---|
| 3204 | Consider the two bind expressions and their invocations below: |
---|
| 3205 | |
---|
| 3206 | <programlisting> |
---|
| 3207 | bind(g, _3, _3, _3)(x, y, z); |
---|
| 3208 | bind(g, _1, _1, _1)(x, y, z); |
---|
| 3209 | </programlisting> |
---|
| 3210 | |
---|
| 3211 | This first line discards arguments <literal>x</literal> and |
---|
| 3212 | <literal>y</literal>, and makes the call: |
---|
| 3213 | <programlisting> |
---|
| 3214 | g(z, z, z) |
---|
| 3215 | </programlisting> |
---|
| 3216 | whereas the second line discards arguments <literal>y</literal> and |
---|
| 3217 | <literal>z</literal>, and calls: |
---|
| 3218 | <programlisting> |
---|
| 3219 | g(x, x, x) |
---|
| 3220 | </programlisting> |
---|
| 3221 | In earlier versions of the library, the latter line resulted in a compile |
---|
| 3222 | time error. |
---|
| 3223 | |
---|
| 3224 | This is basically a tradeoff between safety and flexibility, and the issue |
---|
| 3225 | was extensively discussed during the Boost review period of the library. |
---|
| 3226 | The main points for the <emphasis>strict arity</emphasis> checking |
---|
| 3227 | was that it might |
---|
| 3228 | catch a programming error at an earlier time and that a lambda expression that |
---|
| 3229 | explicitly discards its arguments is easy to write: |
---|
| 3230 | <programlisting> |
---|
| 3231 | (_3, bind(g, _1, _1, _1))(x, y, z); |
---|
| 3232 | </programlisting> |
---|
| 3233 | This lambda expression takes three arguments. |
---|
| 3234 | The left-hand argument of the comma operator does nothing, and as comma |
---|
| 3235 | returns the result of evaluating the right-hand argument we end up with |
---|
| 3236 | the call |
---|
| 3237 | <literal>g(x, x, x)</literal> |
---|
| 3238 | even with the strict arity. |
---|
| 3239 | </para> |
---|
| 3240 | |
---|
| 3241 | <para> |
---|
| 3242 | The main points against the strict arity checking were that the need to |
---|
| 3243 | discard arguments is commonplace, and should therefore be straightforward, |
---|
| 3244 | and that strict arity checking does not really buy that much more safety, |
---|
| 3245 | particularly as it is not symmetric. |
---|
| 3246 | For example, if the programmer wanted to write the expression |
---|
| 3247 | <literal>_1 + _2</literal> but mistakenly wrote <literal>_1 + 2</literal>, |
---|
| 3248 | with strict arity checking, the complier would spot the error. |
---|
| 3249 | However, if the erroneous expression was <literal>1 + _2</literal> instead, |
---|
| 3250 | the error would go unnoticed. |
---|
| 3251 | Furthermore, weak arity checking simplifies the implementation a bit. |
---|
| 3252 | Following the recommendation of the Boost review, strict arity checking |
---|
| 3253 | was dropped. |
---|
| 3254 | </para> |
---|
| 3255 | |
---|
| 3256 | </section> |
---|
| 3257 | |
---|
| 3258 | </appendix> |
---|
| 3259 | |
---|
| 3260 | |
---|
| 3261 | |
---|
| 3262 | <bibliography> |
---|
| 3263 | |
---|
| 3264 | <biblioentry id="cit:stepanov:94"> |
---|
| 3265 | <abbrev>STL94</abbrev> |
---|
| 3266 | <authorgroup> |
---|
| 3267 | <author> |
---|
| 3268 | <surname>Stepanov</surname> |
---|
| 3269 | <firstname>A. A.</firstname> |
---|
| 3270 | </author> |
---|
| 3271 | <author> |
---|
| 3272 | <surname>Lee</surname> |
---|
| 3273 | <firstname>M.</firstname> |
---|
| 3274 | </author> |
---|
| 3275 | </authorgroup> |
---|
| 3276 | <title>The Standard Template Library</title> |
---|
| 3277 | <orgname>Hewlett-Packard Laboratories</orgname> |
---|
| 3278 | <pubdate>1994</pubdate> |
---|
| 3279 | <bibliomisc> |
---|
| 3280 | <ulink url="http://www.hpl.hp.com/techreports">www.hpl.hp.com/techreports</ulink> |
---|
| 3281 | </bibliomisc> |
---|
| 3282 | </biblioentry> |
---|
| 3283 | |
---|
| 3284 | <biblioentry id="cit:sgi:02"> |
---|
| 3285 | <abbrev>SGI02</abbrev> |
---|
| 3286 | <title>The SGI Standard Template Library</title> |
---|
| 3287 | <pubdate>2002</pubdate> |
---|
| 3288 | <bibliomisc><ulink url="http://www.sgi.com/tech/stl/">www.sgi.com/tech/stl/</ulink></bibliomisc> |
---|
| 3289 | |
---|
| 3290 | </biblioentry> |
---|
| 3291 | |
---|
| 3292 | <biblioentry id="cit:c++:98"> |
---|
| 3293 | <abbrev>C++98</abbrev> |
---|
| 3294 | <title>International Standard, Programming Languages – C++</title> |
---|
| 3295 | <subtitle>ISO/IEC:14882</subtitle> |
---|
| 3296 | <pubdate>1998</pubdate> |
---|
| 3297 | </biblioentry> |
---|
| 3298 | |
---|
| 3299 | |
---|
| 3300 | <biblioentry id="cit:jarvi:99"> |
---|
| 3301 | <abbrev>Jär99</abbrev> |
---|
| 3302 | |
---|
| 3303 | <articleinfo> |
---|
| 3304 | <author> |
---|
| 3305 | <surname>Järvi</surname> |
---|
| 3306 | <firstname>Jaakko</firstname> |
---|
| 3307 | </author> |
---|
| 3308 | <title>C++ Function Object Binders Made Easy</title> |
---|
| 3309 | </articleinfo> |
---|
| 3310 | |
---|
| 3311 | <title>Lecture Notes in Computer Science</title> |
---|
| 3312 | <volumenum>1977</volumenum> |
---|
| 3313 | <publishername>Springer</publishername> |
---|
| 3314 | |
---|
| 3315 | <pubdate>2000</pubdate> |
---|
| 3316 | </biblioentry> |
---|
| 3317 | |
---|
| 3318 | |
---|
| 3319 | |
---|
| 3320 | <biblioentry id="cit:jarvi:00"> |
---|
| 3321 | <abbrev>Jär00</abbrev> |
---|
| 3322 | <author> |
---|
| 3323 | <surname>Järvi</surname> |
---|
| 3324 | <firstname>Jaakko</firstname> |
---|
| 3325 | </author> |
---|
| 3326 | <author> |
---|
| 3327 | <firstname>Gary</firstname> |
---|
| 3328 | <surname>Powell</surname> |
---|
| 3329 | </author> |
---|
| 3330 | <title>The Lambda Library : Lambda Abstraction in C++</title> |
---|
| 3331 | <orgname>Turku Centre for Computer Science</orgname> |
---|
| 3332 | <bibliomisc>Technical Report </bibliomisc> |
---|
| 3333 | <issuenum>378</issuenum> |
---|
| 3334 | <pubdate>2000</pubdate> |
---|
| 3335 | <bibliomisc><ulink url="http://www.tucs.fi/Publications/techreports/TR378.php">www.tucs.fi/publications</ulink></bibliomisc> |
---|
| 3336 | |
---|
| 3337 | |
---|
| 3338 | </biblioentry> |
---|
| 3339 | |
---|
| 3340 | |
---|
| 3341 | <biblioentry id="cit:jarvi:01"> |
---|
| 3342 | <abbrev>Jär01</abbrev> |
---|
| 3343 | <author> |
---|
| 3344 | <surname>Järvi</surname> |
---|
| 3345 | <firstname>Jaakko</firstname> |
---|
| 3346 | </author> |
---|
| 3347 | <author> |
---|
| 3348 | <firstname>Gary</firstname> |
---|
| 3349 | <surname>Powell</surname> |
---|
| 3350 | </author> |
---|
| 3351 | <title>The Lambda Library : Lambda Abstraction in C++</title> |
---|
| 3352 | <confgroup> |
---|
| 3353 | <conftitle>Second Workshop on C++ Template Programming</conftitle> |
---|
| 3354 | <address>Tampa Bay, OOPSLA'01</address> |
---|
| 3355 | </confgroup> |
---|
| 3356 | <pubdate>2001</pubdate> |
---|
| 3357 | <bibliomisc><ulink url="http://www.oonumerics.org/tmpw01/">www.oonumerics.org/tmpw01/</ulink></bibliomisc> |
---|
| 3358 | </biblioentry> |
---|
| 3359 | |
---|
| 3360 | <biblioentry id="cit:jarvi:03"> |
---|
| 3361 | <abbrev>Jär03</abbrev> |
---|
| 3362 | |
---|
| 3363 | <articleinfo> |
---|
| 3364 | |
---|
| 3365 | <author> |
---|
| 3366 | <surname>Järvi</surname> |
---|
| 3367 | <firstname>Jaakko</firstname> |
---|
| 3368 | </author> |
---|
| 3369 | |
---|
| 3370 | <author> |
---|
| 3371 | <firstname>Gary</firstname> |
---|
| 3372 | <surname>Powell</surname> |
---|
| 3373 | </author> |
---|
| 3374 | |
---|
| 3375 | <author> |
---|
| 3376 | <firstname>Andrew</firstname> |
---|
| 3377 | <surname>Lumsdaine</surname> |
---|
| 3378 | </author> |
---|
| 3379 | <title>The Lambda Library : unnamed functions in C++</title> |
---|
| 3380 | |
---|
| 3381 | </articleinfo> |
---|
| 3382 | |
---|
| 3383 | <title>Software - Practice and Expreience</title> |
---|
| 3384 | <volumenum>33:259-291</volumenum> |
---|
| 3385 | |
---|
| 3386 | |
---|
| 3387 | <pubdate>2003</pubdate> |
---|
| 3388 | </biblioentry> |
---|
| 3389 | |
---|
| 3390 | |
---|
| 3391 | <biblioentry id="cit:boost::tuple"> |
---|
| 3392 | <abbrev>tuple</abbrev> |
---|
| 3393 | <title>The Boost Tuple Library</title> |
---|
| 3394 | <bibliomisc><ulink url="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html">www.boost.org/libs/tuple/doc/tuple_users_guide.html</ulink> |
---|
| 3395 | </bibliomisc> |
---|
| 3396 | <pubdate>2002</pubdate> |
---|
| 3397 | </biblioentry> |
---|
| 3398 | |
---|
| 3399 | <biblioentry id="cit:boost::type_traits"> |
---|
| 3400 | <abbrev>type_traits</abbrev> |
---|
| 3401 | <title>The Boost type_traits</title> |
---|
| 3402 | <bibliomisc><ulink url="http://www.boost.org/libs/type_traits/index.htm">www.boost.org/libs/type_traits/</ulink> |
---|
| 3403 | </bibliomisc> |
---|
| 3404 | <pubdate>2002</pubdate> |
---|
| 3405 | </biblioentry> |
---|
| 3406 | |
---|
| 3407 | <biblioentry id="cit:boost::ref"> |
---|
| 3408 | <abbrev>ref</abbrev> |
---|
| 3409 | <title>Boost ref</title> |
---|
| 3410 | <bibliomisc><ulink url="http://www.boost.org/libs/bind/ref.html">www.boost.org/libs/bind/ref.html</ulink> |
---|
| 3411 | </bibliomisc> |
---|
| 3412 | <pubdate>2002</pubdate> |
---|
| 3413 | </biblioentry> |
---|
| 3414 | |
---|
| 3415 | <biblioentry id="cit:boost::bind"> |
---|
| 3416 | <abbrev>bind</abbrev> |
---|
| 3417 | <title>Boost Bind Library</title> |
---|
| 3418 | <bibliomisc><ulink url="http://www.boost.org/libs/bind/bind.html">www.boost.org/libs/bind/bind.html</ulink> |
---|
| 3419 | </bibliomisc> |
---|
| 3420 | <pubdate>2002</pubdate> |
---|
| 3421 | </biblioentry> |
---|
| 3422 | |
---|
| 3423 | <biblioentry id="cit:boost::function"> |
---|
| 3424 | <abbrev>function</abbrev> |
---|
| 3425 | <title>Boost Function Library</title> |
---|
| 3426 | <bibliomisc><ulink url="http://www.boost.org/libs/function/">www.boost.org/libs/function/</ulink> |
---|
| 3427 | </bibliomisc> |
---|
| 3428 | <pubdate>2002</pubdate> |
---|
| 3429 | </biblioentry> |
---|
| 3430 | |
---|
| 3431 | <biblioentry id="cit:fc++"> |
---|
| 3432 | <abbrev>fc++</abbrev> |
---|
| 3433 | <title>The FC++ library: Functional Programming in C++</title> |
---|
| 3434 | <author> |
---|
| 3435 | <surname>Smaragdakis</surname> |
---|
| 3436 | <firstname>Yannis</firstname> |
---|
| 3437 | </author> |
---|
| 3438 | <author> |
---|
| 3439 | <firstname>Brian</firstname> |
---|
| 3440 | <surname>McNamara</surname> |
---|
| 3441 | </author> |
---|
| 3442 | <bibliomisc><ulink url="http://www.cc.gatech.edu/~yannis/fc++/">www.cc.gatech.edu/~yannis/fc++/</ulink> |
---|
| 3443 | </bibliomisc> |
---|
| 3444 | <pubdate>2002</pubdate> |
---|
| 3445 | </biblioentry> |
---|
| 3446 | |
---|
| 3447 | |
---|
| 3448 | </bibliography> |
---|
| 3449 | |
---|
| 3450 | |
---|
| 3451 | </library> |
---|