Getting started with arithmetic concepts

Not long ago, I implemented a Matrix class with template expressions. Sadly, I cannot release it to the public because it belongs to my employer. Such libraries dealing with arithmetic will benefit greatly from concepts. The compile errors from not implemented operators are horrendous.

In this chapter we’ll implement some arithmetic concepts, Addable and Subtractable. If anything, the type represented by a Matrix should be able to support addition and subtraction, but not always. It must be possible to store any type in a Matrix like grid, without doing any arithmetic on it. Then it doesn’t matter if the type stored supports addition and/or subtraction. The best place to put these concepts, is on the matrix operator + and operator -.

Before getting there, the concepts must be defined.

We also need to think through what we really want. A first take on a generic add() method may have some design flaws, assuming the type must be identical at both sides.

template<typename T>
T add(T a, T b)
{
return a + b;
}

Another assumption is that T + T -> T. That is not always the case. Some date-time libraries returns a timespan when subtracting two points in time.

We need two types. What about the return type? The return type is really the result of a + b, not the type of either a or b.

As luck would have it, in C++11 the keyword decltype was introduced. It is designed exactly for situations where the type might not be inherently clear.

Having those constraints in mind, we can look at creating concepts suited for the modern add method. Coincidently, using a trailing return type with decltype(t+u) acts like a poor mans concept, as it will complain about not being able to deduce the type. With GCC, the error message is surprisingly clear and to the point. The same can’t be said with Visual Studio at the time of writing. Maybe they’ll get better with time.

The Addable concept

The Addable concept should accept two template parameters, and it should perform the intended operation on those two objects in a requires-clause. Next up is a function concept where Addable have been implemented.

This addable function concept can be used to define a method taking only types which satisfy the constraints given by Addable. Extending the add-method above, we only really need to add the requires clause. There are two template parameters of different types, there is automatic return type deduction happening at compile time, and only types who support t + u are accepted into this method.

Using arithmetic concepts may be somewhat contrived. But hang on, there is a grand scheme. Those concepts can be joined together to create a concept, which requires all four mathematical operators to be defined, namely the Arithmetic concept.

Arithmetic concept

Having multiple concepts is fine, but sometimes you have to join multiple concepts. For mathematics, requiring the type to support all mathematical operators is a just requirement.

It’s called a conjunction when multiple concepts are joined together.

Here are the 4 mathematical operators defined with as function concepts.

Using the previous defined concepts for addition, subtraction, division and multiplication, each one of the above concepts are usable in itself, while they also may be used as building blocks in aggregate constraints.

The concept is built by joining the above concepts in a logical chain.