32cea6cd01
[SVN r68612]
161 lines
5.9 KiB
Plaintext
161 lines
5.9 KiB
Plaintext
[/==============================================================================
|
|
Copyright (C) 2001-2010 Joel de Guzman
|
|
Copyright (C) 2001-2005 Dan Marsden
|
|
Copyright (C) 2001-2010 Thomas Heller
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
===============================================================================/]
|
|
|
|
[section Operator]
|
|
#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 [link phoenix.starter_kit.lazy_operators
|
|
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
|
|
[link phoenix.modules.function Function]), lazy operators are not immediately executed
|
|
when invoked. Instead, an actor (see [link phoenix.actor 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:
|
|
|
|
# A binary operator, except `->*` will be lazily evaluated when
|
|
/at least/ one of its operands is an actor object
|
|
(see [link phoenix.actor Actor]).
|
|
# Unary operators are lazily evaluated if their argument is an actor object.
|
|
# Operator `->*` is lazily evaluated if the left hand argument is an actor object.
|
|
# The result of a lazy operator is an actor object that can in turn allow the
|
|
applications of rules 1, 2 and 3.
|
|
|
|
For example, to check the following expression is lazily evaluated:
|
|
|
|
-(arg1 + 3 + 6)
|
|
|
|
# Following rule 1, `arg1 + 3` is lazily evaluated since `arg1` is an actor
|
|
(see [link phoenix.modules.core.arguments Arguments]).
|
|
# The result of this `arg1 + 3` expression is an actor object, following rule 4.
|
|
# Continuing, `arg1 + 3 + 6` is again lazily evaluated.
|
|
Rule 2.
|
|
# By rule 4 again, the result of `arg1 + 3 + 6` is an actor object.
|
|
# As `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 [link phoenix.modules.core Core]).
|
|
For example:
|
|
|
|
1 << 3; // Immediately evaluated
|
|
val(1) << 3; // Lazily evaluated
|
|
|
|
[heading Supported operators]
|
|
|
|
[heading Unary operators]
|
|
|
|
prefix: ~, !, -, +, ++, --, & (reference), * (dereference)
|
|
postfix: ++, --
|
|
|
|
[heading Binary operators]
|
|
|
|
=, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
|
|
+, -, *, /, %, &, |, ^, <<, >>
|
|
==, !=, <, >, <=, >=
|
|
&&, ||, ->*
|
|
|
|
[heading Ternary operator]
|
|
|
|
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.
|
|
|
|
[heading Member pointer operator]
|
|
|
|
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)
|
|
|
|
[heading Include Files]
|
|
|
|
[table
|
|
[[Operators] [File]]
|
|
[[`-`, `+`, `++`, `--`, `+=`,
|
|
`-=`, `*=`, `/=`, `%=`,
|
|
`*`, `/`, `%`] [`#include <boost/phoenix/operator/arithmetic.hpp>`]]
|
|
[[`&=`, `|=`, `^=`, `<<=`,
|
|
`>>=`, `&`, `|`, `^`, `<<`,
|
|
`>>`] [`#include <boost/phoenix/operator/bitwise.hpp>`]]
|
|
[[`==`, `!=`, `<`,
|
|
`<=`, `>`, `>=`] [`#include <boost/phoenix/operator/comparison.hpp>`]]
|
|
[[`<<`, `>>`] [`#include <boost/phoenix/operator/io.hpp>`]]
|
|
[[`!`, &&, `||`] [`#include <boost/phoenix/operator/logical.hpp>`]]
|
|
[[`&x`, `*p`, `=`, `[]`] [`#include <boost/phoenix/operator/self.hpp>`]]
|
|
[[`if_else(c, a, b)`] [`#include <boost/phoenix/operator/if_else.hpp>`]]
|
|
[[`->*`] [`#include <boost/phoenix/operator/member.hpp>`]]
|
|
]
|
|
|
|
[endsect]
|