| [/============================================================================== |
| 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] |