...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
#include <boost/phoenix/operator.hpp>
This facility provides a mechanism for lazily evaluating operators. Syntactically, a lazy operator looks and feels like an ordinary C/C++ infix, prefix or postfix operator. The operator application looks the same. However, unlike ordinary operators, the actual operator execution is deferred. Samples:
arg1 + arg2 1 + arg1 * arg2 1 / -arg1 arg1 < 150
We have seen the lazy operators in action (see Quick Start - Lazy Operators). Let's go back and examine them a little bit further:
std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
Through operator overloading, the expression arg1
% 2 == 1
actually
generates an actor. This actor object is passed on to STL's find_if
function. From the viewpoint of
STL, the expression is simply a function object expecting a single argument
of the containers value_type. For each element in c
,
the element is passed on as an argument arg1
to the actor (function object). The actor checks if this is an odd value
based on the expression arg1 % 2 ==
1
where arg1 is replaced by the container's
element.
Like lazy functions (see Function), lazy operators are not immediately executed when invoked. Instead, an actor (see Actor) object is created and returned to the caller. Example:
(arg1 + arg2) * arg3
does nothing more than return an actor. A second function call will evaluate the actual operators. Example:
std::cout << ((arg1 + arg2) * arg3)(4, 5, 6);
will print out "54".
Operator expressions are lazily evaluated following four simple rules:
->*
will be lazily evaluated when at least one of its
operands is an actor object (see Actor).
->*
is lazily
evaluated if the left hand argument is an actor object.
For example, to check the following expression is lazily evaluated:
-(arg1 + 3 + 6)
arg1 + 3
is
lazily evaluated since arg1
is an actor (see Arguments).
arg1 + 3
expression
is an actor object, following rule 4.
arg1 +
3 + 6
is again lazily evaluated. Rule 2.
arg1
+ 3 + 6
is
an actor object.
arg1 +
3 + 6
is an actor, -(arg1 + 3 + 6)
is lazily evaluated. Rule 2.
Lazy-operator application is highly contagious. In most cases, a single
argN
actor infects all its
immediate neighbors within a group (first level or parenthesized expression).
Note that at least one operand of any operator must be a valid actor for
lazy evaluation to take effect. To force lazy evaluation of an ordinary expression,
we can use ref(x)
, val(x)
or cref(x)
to transform an operand into a valid actor object (see Core).
For example:
1 << 3; // Immediately evaluated val(1) << 3; // Lazily evaluated
prefix: ~, !, -, +, ++, --, & (reference), * (dereference) postfix: ++, --
=, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= +, -, *, /, %, &, |, ^, <<, >> ==, !=, <, >, <=, >= &&, ||, ->*
if_else(c, a, b)
The ternary operator deserves special mention. Since C++ does not allow us
to overload the conditional expression: c
? a : b
, the
if_else pseudo function is provided for this purpose. The behavior is identical,
albeit in a lazy manner.
a->*member_object_pointer a->*member_function_pointer
The left hand side of the member pointer operator must be an actor returning a pointer type. The right hand side of the member pointer operator may be either a pointer to member object or pointer to member function.
If the right hand side is a member object pointer, the result is an actor which, when evaluated, returns a reference to that member. For example:
struct A { int member; }; A* a = new A; ... (arg1->*&A::member)(a); // returns member a->member
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:
struct A { int func(int); }; A* a = new A; int i = 0; (arg1->*&A::func)(arg2)(a, i); // returns a->func(i)
Operators |
File |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|