4.3. Expression templates in Sourcery VSIPL++

4.3.1. Generating expression templates

Most functions and operators provided by Sourcery VSIPL++ are written to support such lazy evaluation. Thus, instead of calculating the result value directly, they return objects of such expression types. Moreover, they are written in such a way that their input may be expression type objects, too, such that expressions can be nested without being evaluated.

template <typename T, typename LeftBlock, typename RightBlock>
Vector<T, Binary_expr_block<1, Plus, LeftBlock, T, RightBlock, T> >
operator+(Vector<LeftBlock> left, Vector<RightBlock> right);

This version of operator+ expects Vectors of arbitrary block types as input, and generates a Vector whose block type encodes the binary operation. (If the input arguments are themselves expressions, this will result in a composite expression tree.

Sourcery VSIPL++ provides a range of types to represent such non-terminal expression nodes, as well as the means to traverse them, to make it possible to generate expression (parse) trees for a wide range of expressions.

4.3.2. Evaluating expression templates

Expressions are ideally evaluated only once all the relevant information has been gathered. That point is typically reached once the whole assignment-expression has been seen. That is the case during assignment-operator evaluation.

Here is a conventional implementation of a vector-assignment, doing element-wise assignment:

template <typename T, typename LeftBlock, typename RightBlock>
void assign(Vector<T, LeftBlock> left, Vector<T, RightBlock> right)
{
  for (length_type i = Vector<T, LeftBlock>::size(); i; --i)
    left.put(i - 1, right.get(i - 1));
}

If RightBlock is an expression-block with an elementwise operation, its implementation of get will perform the (elementwise) evaluation. Thus, in this case, at least one temporary has already been eliminated, and multiple loops have been fused into one.

For non-elementwise operations, this is not quite as simple.