CONSTEXPR

Declare functions noexcept if they won’t emit exceptions

Values known during compilation are privileged. They may be placed in read-only memory, for example, and, especially for developers of embedded systems, this can be a feature of considerable importance. Of broader applicability is that integral val‐ ues that are constant and known during compilation can be used in contexts where C++ requires an integral constant expression. Such contexts include specification of array sizes, integral template arguments (including lengths of std::array objects), enumerator values, alignment specifiers, and more. If you want to use a variable for these kinds of things, you certainly want to declare it constexpr, because then com‐ pilers will ensure that it has a compile-time value:

int sz; // non-constexpr variable … 
constexpr auto arraySize1 = sz; // error! sz's value not known at compilation 
std::array data1; // error! same problem 
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr

Note that const doesn’t offer the same guarantee as constexpr, because const
objects need not be initialized with values known during compilation:

int sz; // as before
…
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value not known at compilation

Simply put, all constexpr objects are const, but not all const objects are constexpr.
If you want compilers to guarantee that a variable has a value that can beused in contexts requiring compile-time constants, the tool to reach for is constexpr, not const.

constexpr functions can be used in contexts that demand compile-time con‐
stants. If the values of the arguments you pass to a constexpr function in such a context are known during compilation, the result will be computed during compilation. If any of the arguments’ values is not known during compilation,your code will be rejected.

When a constexpr function is called with one or more values that are not
known during compilation, it acts like a normal function, computing its result at runtime. This means you don’t need two functions to perform the same operation, one for compile-time constants and one for all other values. The constexpr function does it all.

constexpr // pow's a constexpr func
int pow(int base, int exp) noexcept // that never throws
{
 … // impl is below
}
constexpr auto numConds = 5; // # of conditions
std::array<int, pow(3, numConds)> results; // results has 3^numConds elements
auto base = readFromDB("base"); // get these values
auto exp = readFromDB("exponent"); // at runtime
auto baseToExp = pow(base, exp); // call pow function at runtime
constexpr int pow(int base, int exp) noexcept
{
 return (exp == 0 ? 1 : base * pow(base, exp - 1));
}

constexpr functions are limited to taking and returning literal types, which essentially means types that can have values determined during compilation. In C++11, all built-in types except void qualify, but user-defined types may be literal, too, because constructors and other member functions may be constexpr:

class Point {
public:
 constexpr Point(double xVal = 0, double yVal = 0) noexcept
 : x(xVal), y(yVal)
 {}
 constexpr double xValue() const noexcept { return x; }
 constexpr double yValue() const noexcept { return y; }
 void setX(double newX) noexcept { x = newX; }
 void setY(double newY) noexcept { y = newY; }
private:
 double x, y;
};
constexpr Point p1(9.4, 27.7); // fine, "runs" constexpr ctor during compilation
constexpr
Point midpoint(const Point& p1, const Point& p2) noexcept
{
 return { (p1.xValue() + p2.xValue()) / 2, // call constexpr
 (p1.yValue() + p2.yValue()) / 2 }; // member funcs
}
constexpr auto mid = midpoint(p1, p2); // init constexpr object w/result of constexpr function

In C++11, two restrictions prevent Point’s member functions setX and setY from being declared constexpr. First, they modify the object they operate on, and in C++11, constexpr member functions are implicitly const. Second, they have void return types, and void isn’t a literal type in C++11. Both these restrictions are lifted in C++14, so in C++14, even Point’s setters can be constexpr:

class Point {
public:
 …
 constexpr void setX(double newX) noexcept // C++14
 { x = newX; }
 constexpr void setY(double newY) noexcept // C++14
 { y = newY; }
 …
};
constexpr Point reflection(const Point& p) noexcept
{
 Point result; // create non-const Point
 result.setX(-p.xValue()); // set its x and y values
 result.setY(-p.yValue());
 return result; // return copy of it
}
constexpr Point p1(9.4, 27.7); // as above
constexpr Point p2(28.8, 5.3);
constexpr auto mid = midpoint(p1, p2);
constexpr auto reflectedMid = // reflectedMid's value is
 reflection(mid); // (-19.1 -16.5) and known  during compilation