| Home | Libraries | People | FAQ | More

#### Proto's Operator Overloads

Once we have some Proto terminals, expressions involving those terminals build expression trees for us. Proto defines overloads for each of C++'s overloadable operators in the `boost::proto` namespace. As long as one operand is a Proto expression, the result of the operation is a tree node representing that operation.

| Note
Proto's operator overloads live in the `boost::proto` namespace and are found via ADL (argument-dependent lookup). That is why expressions must be "tainted" with Proto-ness for Proto to be able to build trees out of expressions.

As a result of Proto's operator overloads, we can say:

    -_1;        // OK, build a unary-negate tree node
    _1 + 42;    // OK, build a binary-plus tree node

For the most part, this Just Works and you don't need to think about it, but a few operators are special and it can be helpful to know how Proto handles them.

###### Assignment, Subscript, and Function Call Operators

Proto also overloads `operator=`, `operator[]`, and `operator()`, but these operators are member functions of the expression template rather than free functions in Proto's namespace. The following are valid Proto expressions:

    _1 = 5;     // OK, builds a binary assign tree node
    _1[6];      // OK, builds a binary subscript tree node
    _1();       // OK, builds a unary function tree node
    _1(7);      // OK, builds a binary function tree node
    _1(8,9);    // OK, builds a ternary function tree node
    // ... etc.

For the first two lines, assignment and subscript, it should be fairly unsurprising that the resulting expression node should be binary. After all, there are two operands in each expression. It may be surprising at first that what appears to be a function call with no arguments, `_1()`, actually creates an expression node with one child. The child is `_1` itself. Likewise, the expression `_1(7)` has two children: `_1` and `7`.

Because these operators can only be defined as member functions, the following expressions are invalid:

    int i;
    i = _1;         // ERROR: cannot assign _1 to an int

    int *p;
    p[_1];          // ERROR: cannot use _1 as an index

    std::sin(_1);   // ERROR: cannot call std::sin() with _1

Also, C++ has special rules for overloads of `operator->` that make it useless for building expression templates, so Proto does not overload it.

###### The Address-Of Operator

Proto overloads the address-of operator for expression types, so that the following code creates a new unary address-of tree node:

    &_1;    // OK, creates a unary address-of tree node

It does not return the address of the `_1` object. However, there is special code in Proto such that a unary address-of node is implicitly convertible to a pointer to its child. In other words, the following code works and does what you might expect, but not in the obvious way:

    typedef
        proto::terminal< placeholder<0> >::type
    _1_type;

    _1_type const _1 = {{}};
    _1_type const * p = &_1; // OK, &_1 implicitly converted