1[/============================================================================== 2 Copyright (C) 2001-2010 Joel de Guzman 3 Copyright (C) 2001-2005 Dan Marsden 4 Copyright (C) 2001-2010 Thomas Heller 5 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===============================================================================/] 9 10[section Operator] 11 #include <boost/phoenix/operator.hpp> 12 13This facility provides a mechanism for lazily evaluating operators. 14Syntactically, a lazy operator looks and feels like an ordinary C/C++ infix, 15prefix or postfix operator. The operator application looks the same. However, 16unlike ordinary operators, the actual operator execution is deferred. Samples: 17 18 arg1 + arg2 19 1 + arg1 * arg2 20 1 / -arg1 21 arg1 < 150 22 23We have seen the lazy operators in action (see [link phoenix.starter_kit.lazy_operators 24Quick Start - Lazy Operators]). Let's go back and examine them a little bit further: 25 26 std::find_if(c.begin(), c.end(), arg1 % 2 == 1) 27 28Through operator overloading, the expression `arg1 % 2 == 1` actually generates 29an actor. This actor object is passed on to STL's `find_if` function. From 30the viewpoint of STL, the expression is simply a function object expecting a 31single argument of the containers value_type. For each element in `c`, 32the element is passed on as an argument `arg1` to the actor (function 33object). 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. 35 36Like lazy functions (see 37[link phoenix.modules.function Function]), lazy operators are not immediately executed 38when invoked. Instead, an actor (see [link phoenix.actor Actor]) 39object is created and returned to the caller. Example: 40 41 (arg1 + arg2) * arg3 42 43does nothing more than return an actor. A second function call will evaluate 44the actual operators. Example: 45 46 std::cout << ((arg1 + arg2) * arg3)(4, 5, 6); 47 48will print out "54". 49 50Operator expressions are lazily evaluated following four simple rules: 51 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. 59 60For example, to check the following expression is lazily evaluated: 61 62 -(arg1 + 3 + 6) 63 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. 68 Rule 2. 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. 71 72Lazy-operator application is highly contagious. In most cases, a single `argN` 73actor infects all its immediate neighbors within a group (first level or 74parenthesized expression). 75 76Note that at least one operand of any operator must be a valid actor 77for lazy evaluation to take effect. To force lazy evaluation of an 78ordinary expression, we can use `ref(x)`, `val(x)` or `cref(x)` to 79transform an operand into a valid actor object (see [link phoenix.modules.core Core]). 80For example: 81 82 1 << 3; // Immediately evaluated 83 val(1) << 3; // Lazily evaluated 84 85[heading Supported operators] 86 87[heading Unary operators] 88 89 prefix: ~, !, -, +, ++, --, & (reference), * (dereference) 90 postfix: ++, -- 91 92[heading Binary operators] 93 94 =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= 95 +, -, *, /, %, &, |, ^, <<, >> 96 ==, !=, <, >, <=, >= 97 &&, ||, ->* 98 99[heading Ternary operator] 100 101 if_else(c, a, b) 102 103The ternary operator deserves special mention. Since C++ does not allow us to 104overload the conditional expression: `c ? a : b`, the if_else pseudo function is 105provided for this purpose. The behavior is identical, albeit in a lazy manner. 106 107[heading Member pointer operator] 108 109 a->*member_object_pointer 110 a->*member_function_pointer 111 112The left hand side of the member pointer operator must be an actor returning a pointer 113type. The right hand side of the member pointer operator may be either a pointer to member 114object or pointer to member function. 115 116If the right hand side is a member object pointer, the result is an actor which, when evaluated, 117returns a reference to that member. For example: 118 119 struct A 120 { 121 int member; 122 }; 123 124 A* a = new A; 125 ... 126 127 (arg1->*&A::member)(a); // returns member a->member 128 129If the right hand side is a member function pointer, the result is an actor which, when invoked, calls the specified member function. For example: 130 131 struct A 132 { 133 int func(int); 134 }; 135 136 A* a = new A; 137 int i = 0; 138 139 (arg1->*&A::func)(arg2)(a, i); // returns a->func(i) 140 141[heading Include Files] 142 143[table 144 [[Operators] [File]] 145 [[`-`, `+`, `++`, `--`, `+=`, 146 `-=`, `*=`, `/=`, `%=`, 147 `*`, `/`, `%`] [`#include <boost/phoenix/operator/arithmetic.hpp>`]] 148 [[`&=`, `|=`, `^=`, `<<=`, 149 `>>=`, `&`, `|`, `^`, `<<`, 150 `>>`] [`#include <boost/phoenix/operator/bitwise.hpp>`]] 151 [[`==`, `!=`, `<`, 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>`]] 158] 159 160[endsect] 161