1 [/==============================================================================
2 Copyright (C) 2001-2010 Joel de Guzman
3 Copyright (C) 2001-2005 Dan Marsden
4 Copyright (C) 2001-2010 Thomas Heller
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ===============================================================================/]
11 #include <boost/phoenix/operator.hpp>
13 This facility provides a mechanism for lazily evaluating operators.
14 Syntactically, a lazy operator looks and feels like an ordinary C/C++ infix,
15 prefix or postfix operator. The operator application looks the same. However,
16 unlike ordinary operators, the actual operator execution is deferred. Samples:
23 We have seen the lazy operators in action (see [link phoenix.starter_kit.lazy_operators
24 Quick Start - Lazy Operators]). Let's go back and examine them a little bit further:
26 std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
28 Through operator overloading, the expression `arg1 % 2 == 1` actually generates
29 an actor. This actor object is passed on to STL's `find_if` function. From
30 the viewpoint of STL, the expression is simply a function object expecting a
31 single argument of the containers value_type. For each element in `c`,
32 the element is passed on as an argument `arg1` to the actor (function
33 object). The actor checks if this is an odd value based on the expression
34 `arg1 % 2 == 1` where arg1 is replaced by the container's element.
36 Like lazy functions (see
37 [link phoenix.modules.function Function]), lazy operators are not immediately executed
38 when invoked. Instead, an actor (see [link phoenix.actor Actor])
39 object is created and returned to the caller. Example:
43 does nothing more than return an actor. A second function call will evaluate
44 the actual operators. Example:
46 std::cout << ((arg1 + arg2) * arg3)(4, 5, 6);
50 Operator expressions are lazily evaluated following four simple rules:
52 # A binary operator, except `->*` will be lazily evaluated when
53 /at least/ one of its operands is an actor object
54 (see [link phoenix.actor Actor]).
55 # Unary operators are lazily evaluated if their argument is an actor object.
56 # Operator `->*` is lazily evaluated if the left hand argument is an actor object.
57 # The result of a lazy operator is an actor object that can in turn allow the
58 applications of rules 1, 2 and 3.
60 For example, to check the following expression is lazily evaluated:
64 # Following rule 1, `arg1 + 3` is lazily evaluated since `arg1` is an actor
65 (see [link phoenix.modules.core.arguments Arguments]).
66 # The result of this `arg1 + 3` expression is an actor object, following rule 4.
67 # Continuing, `arg1 + 3 + 6` is again lazily evaluated.
69 # By rule 4 again, the result of `arg1 + 3 + 6` is an actor object.
70 # As `arg1 + 3 + 6` is an actor, `-(arg1 + 3 + 6)` is lazily evaluated. Rule 2.
72 Lazy-operator application is highly contagious. In most cases, a single `argN`
73 actor infects all its immediate neighbors within a group (first level or
74 parenthesized expression).
76 Note that at least one operand of any operator must be a valid actor
77 for lazy evaluation to take effect. To force lazy evaluation of an
78 ordinary expression, we can use `ref(x)`, `val(x)` or `cref(x)` to
79 transform an operand into a valid actor object (see [link phoenix.modules.core Core]).
82 1 << 3; // Immediately evaluated
83 val(1) << 3; // Lazily evaluated
85 [heading Supported operators]
87 [heading Unary operators]
89 prefix: ~, !, -, +, ++, --, & (reference), * (dereference)
92 [heading Binary operators]
94 =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
95 +, -, *, /, %, &, |, ^, <<, >>
99 [heading Ternary operator]
103 The ternary operator deserves special mention. Since C++ does not allow us to
104 overload the conditional expression: `c ? a : b`, the if_else pseudo function is
105 provided for this purpose. The behavior is identical, albeit in a lazy manner.
107 [heading Member pointer operator]
109 a->*member_object_pointer
110 a->*member_function_pointer
112 The left hand side of the member pointer operator must be an actor returning a pointer
113 type. The right hand side of the member pointer operator may be either a pointer to member
114 object or pointer to member function.
116 If the right hand side is a member object pointer, the result is an actor which, when evaluated,
117 returns a reference to that member. For example:
127 (arg1->*&A::member)(a); // returns member a->member
129 If the right hand side is a member function pointer, the result is an actor which, when invoked, calls the specified member function. For example:
139 (arg1->*&A::func)(arg2)(a, i); // returns a->func(i)
141 [heading Include Files]
145 [[`-`, `+`, `++`, `--`, `+=`,
146 `-=`, `*=`, `/=`, `%=`,
147 `*`, `/`, `%`] [`#include <boost/phoenix/operator/arithmetic.hpp>`]]
148 [[`&=`, `|=`, `^=`, `<<=`,
149 `>>=`, `&`, `|`, `^`, `<<`,
150 `>>`] [`#include <boost/phoenix/operator/bitwise.hpp>`]]
152 `<=`, `>`, `>=`] [`#include <boost/phoenix/operator/comparison.hpp>`]]
153 [[`<<`, `>>`] [`#include <boost/phoenix/operator/io.hpp>`]]
154 [[`!`, &&, `||`] [`#include <boost/phoenix/operator/logical.hpp>`]]
155 [[`&x`, `*p`, `=`, `[]`] [`#include <boost/phoenix/operator/self.hpp>`]]
156 [[`if_else(c, a, b)`] [`#include <boost/phoenix/operator/if_else.hpp>`]]
157 [[`->*`] [`#include <boost/phoenix/operator/member.hpp>`]]