Operator

| Home | Libraries | People | FAQ | More

### 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 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:

1. A binary operator, except `->*` will be lazily evaluated when at least one of its operands is an actor object (see Actor).
2. Unary operators are lazily evaluated if their argument is an actor object.
3. Operator `->*` is lazily evaluated if the left hand argument is an actor object.
4. 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)

1. Following rule 1, `arg1 + 3` is lazily evaluated since `arg1` is an actor (see Arguments).
2. The result of this `arg1 + 3` expression is an actor object, following rule 4.
3. Continuing, `arg1 + 3 + 6` is again lazily evaluated. Rule 2.
4. By rule 4 again, the result of `arg1 + 3 + 6` is an actor object.
5. 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 Core). For example:

    1 << 3;      // Immediately evaluated
    val(1) << 3; // Lazily evaluated

##### Supported operators

##### Unary operators

    prefix:   ~, !, -, +, ++, --, & (reference), * (dereference)
    postfix:  ++, --

##### Binary operators

    =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
    +, -, *, /, %, &, |, ^, <<, >>
    ==, !=, <, >, <=, >=
    &&, ||, ->*

##### 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.

##### 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)

##### Include Files

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>`