The introduction of constexpr in C++11 [2.1.4] greatly simplified some compile-time complex computations, even though they were some limitations. The most frustrating of which was certainly the constraint that constexpr functions should contain a single statement (a return statement). In practice this means no variable, no branch or control flow other than the ternary ?: operator and using recursion for any loop-based algorithm. See for example this implementation of popcount() we wrote in section [2.1.4]:
#include<cstdio> constexpr int popcount(unsigned n) { return (n == 0) ? 0 : ((n & 1) + popcount(n >> 1)); } int main(int argc, char**) { int array[popcount(45)]; printf("%d\n", popcount(argc)); return 0; }
In C++14, these restrictions are lifted and we can implement this function in a less convoluted way3:
#include<cstdio> constexpr int popcount(unsigned n) { int result = 0; for (; n != 0; n >>= 1) if ((n & 1) != 0) ++result; return result; } int main(int argc, char**) { int array[popcount(45)]; printf("%d\n", popcount(argc)); return 0; }
A subtle change in the transition from C++11 to C++14 is that constexpr used on a member function does not implies const anymore. For example, this code would not compile in C++11 but does in C++14:
struct s { int value; constexpr int increment(int v) { // Can’t do that in C++11 as the function signature is actually // // constexpr int increment(int) const. // // Okay in C++14, where the function signature is as declared. return value += v; } };
This can come as a surprise when switching to a newer standard since calling a constexpr-only member function on a const instance will suddenly trigger errors like “passing ‘const x’ as ‘this’ argument discards qualifiers”.
3Not that recursion is inherently convoluted. Some algorithms work very well when implemented in a recursive way, both regarding the readability and the performance, but even though any programmer worth is money must be know the practice I would argue that most code, i.e. the code we are familiar with, is non-recursive.