Generalised constant expressions are a core language feature introduced to C++ by the recent C++11 standard. A call to a function or method qualified with the new `constexpr`

keyword can now be evaluated at compile-time. Of course there are restrictions: arguments to such a call must also be amenable to compile-time evaluation. The primary restriction is that the body of a `constexpr`

function must comprise of a single `return`

statement. While this initially sounds draconian, the use of recursion, and the ternary operator, can permit essentially any calculation. The language of C++11 generalised constant expressions is that of a functional language.

The code below presents a brief example. Note the call to `sqr_int`

in the second template argument to the C++11 `std::array`

object. Also of interest: the call to `sqr_int`

will prosaically perform floating-point calculations at compile-time. Incidentally, among other restrictions, lambda expressions may not, alas, form part of a C++11 generalised constant expression.

#include <array> constexpr unsigned sqr_int(double d) { return d*d; } std::array<bool,sqr_int(4.5)> garr;

Having been impressed by the ctrace and metatrace compile-time ray-tracers, I thought I’d give the fast fourier transform (FFT) a whirl. Seeking an FFT implemented in a functional language, I came across the elegant Single Assignment C (SAC) version shown here. After failing to compile the assembled pieces with the SAC compiler, I converted it to Fortran 9x and verified the results against another Fortran implementation from here.

The next thing I needed was a container data type to stand in for the rank-one, first-class arrays employed by the Fortran. Thoughts of using `std::array`

soon evaporated as I realised that no `constexpr`

element access methods exist; neither `operator[]`

nor `std::array::front()`

comply. Similar issues exist with `std::tuple`

. Furthermore, the FFT only requires a homogeneous container. An implementation using the heterogeneous `std::tuple`

would be inclined to add additional type-checking code. In response, I created the following *recursive array* container type:

template <typename T, size_t N> struct recarr { constexpr recarr(T x, recarr<T,N-1> a) : m_x(x), m_a(a) {} constexpr T head() { return m_x; } constexpr recarr<T,N-1> tail() { return m_a; } private: T m_x; recarr<T,N-1> m_a; }; template <typename T> struct recarr<T,0> {};

The common restriction on recursive data types: members having the same type as the enclosing class must be pointers, is not applicable here; the `m_a`

member is always a different type; i.e. `recarr`

is not the same type as `recarr`

. The zero-length specialisation of `recarr`

has no members.

The list type used routinely in functional languages such as Haskell is a clear inspiration in the design of `std::recarr`

. A *cons* function for `std::recarr`

, necessary for the construction of higher order functions such as map and zipWith, may be defined as shown below. Rather than the raw `recarr`

*constructor*, the stand-alone `recarr_cons`

*function* can infer its template arguments from the runtime arguments.

template <typename T, size_t N> constexpr recarr<T,N+1> recarr_cons(T x, recarr<T,N> xs) { return recarr<T,N+1>(x,xs); }

An FFT is an operation on complex numbers. The standard `std::complex`

type, however, delivers another spanner to the works; it too lacks the `constexpr`

methods needed for a compile-time FFT; including the constructors, and arithmetic operators. So, a new complex number class was developed, along with the necessary C++11 generalised constant expression support. Complex number formulae and definitions were drawn from here and here.

GCC and Clang both have excellent support for C++11. Wouldn’t it be nice to find out which is the faster compiler for the evaluation of a `constexpr`

FFT? Some more challenges materialise here: Clang rejects all of the `cmath`

library functions, as being non-`constexpr`

. Functions required by the FFT include `sin`

, `sinh`

, `cos`

, `cosh`

, `sqrt`

, `log`

, `exp`

, `atan`

, `atan2`

and `pow`

. Initially I though that Clang was being a little cranky here, but this is in fact the correct behaviour; n.b. a `constexpr`

function may not be overloaded with a non-`constexpr`

function; and vice-versa. Standard library functions which are to be `constexpr`

must consequently be specified as such by the relevant C++ standard; the functions in `cmath`

are not. After all, functions comprised of a single return statement may not be the most performant! The N3228 and N3231 documents from the C++ Standards Committee’s November 2010 mailings elaborate on this theme.

So, `constexpr`

versions of the mathematical functions from `cmath`

necessary for the FFT were developed; with reference to the formulae and guidelines of the Algebra Help e-Book.

I am in fact a big fan of the `std::tuple`

class. In the end I couldn’t resist a second, comparative implementation of a `constexpr`

FFT using C++11 tuples; and so the magic of variadic templates. Need I mention that `std::tuple`

is also missing many of the `constexpr`

constructors and support functions necessary for the job? The github code linked below includes a simple recursive version of the `std::tuple`

type, with `constexpr`

constructors; a version of `get`

; a version of `make_tuple`

; and, as the FFT uses concat, a version of `tuple_cat`

. For comparison with `recarr_cons`

above, here is the simple, concise `tuple_cons`

; in constrast to a more verbose definition for `tuple_cat`

provided in the full project.

template <typename T, typename ...Ts> constexpr tuple<T,Ts...> tuple_cons(T x, tuple<Ts...> xs) { return tuple_cat(make_tuple(x),xs); }

The code is stored in a github repository here.

It is a nice exercice but the fortran version is much more readable. I think it is a sad evolution; C used to be more readable than f77.

The (runtime) C and C++ versions would still look as readable as ever. New in C++11, functions qualified as constexpr, can be evaluated entirely at compile-time. This is neither available, nor would it be so useful, in Fortran. As far as readability is concerned, I think a better comparison can be made with template metaprogramming; check out the fine metatrace code here. Fresh new features such as constexpr, variadic templates, and rvalue references represent a glorious evolution in C++ 🙂

I can agree on this, constexpr is better than expression template.