C++ template programming for compile-time computation

Addenda to constexpr evaluation

It turns out the compiler can, in the interests of "optimization", actually choose to evaluate constexpr's at run time (live and learn)!

In those case, it appears to be setting aside the storage for the "constant", calculating it at run time, but treating it as read only after the value is initially set.

In that case it appears the only way to be certain whether it is performing the computation at compile time is to break out the compile-to-assembly option - which I won't require folks to do.

Since C++14, things have changed further, allowing the use of non-constexpr variables within constexpr functions. It appears that going back to compiling with -std=c++11 gives stricter controls over this, but limits the body of a constexpr function to being strictly a return statement (though nested :? operators can still be embedded within that).

Below we study the use of C++ templates to carry out computations at compile time. We can perform significant computation and code manipulation in this manner:

For compile time computation, we can also implement sets of functions capable of operating on constant structs, e.g. representing Fractions:

struct Fraction { int num, den; };

const Fraction f = { 3, 4 };   //  f represents 3/4
The functions can perform basic math operations on fractions and returning fractions as a result, e.g. addition, subtraction, etc.

Since the functions need to work at compile time, the safest approach is to declare the return type for each as a constant expression, e.g. the function square below returns a fraction multiplied by itself:

constexpr Fraction square(const Fraction f) {
   const Fraction result = { f.num*f.num, f.den*f.den };
   return result;
}
To be valid constant expressions, the functions are limited to basic operations on constant values, calls to constexpr functions, and the use of the ternary operator, e.g.

// if f holds a fraction whose numerator is greater than its denominator,
//    return the square of its inverse,
// otherwise return the square of the original
constexpr Fraction squareSmallOverBig(const Fraction f)
{
   // have an inverted version of the fraction ready
   const Fraction inverse = { f.den, f.num };

   // if the numerator is bigger than the denominator return the inverted version,
   // otherwise return the original
   return (f.num > f.den)? square(inverse) : square(f);
}

Sample function implementations for runtime computation are provided in runtime_fractions.h, but they need to be reworked considerably to make constexpr equivalents.