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