Normally, constexpr must be free of side-effects. However, I just discovered that it is possible to use side-effects in the constructors of thrown exceptions. That technique
It is legal.
For each constexpr
function there must be some argument values that result in a constant expression (§7.1.5/5):
For a
constexpr
function, if no function argument values exist such that the function invocation substitution would produce a constant expression (5.19), the program is ill-formed; no diagnostic required.
Note that this does not mean that every possible argument value must result in a constant expression. divide
clearly has some argument values that result in a constant expression: divide(1, 1)
is a simple example. So, the definition is clearly valid.
But can divide(1, 0)
be called? Yes, it can. There's almost no difference between invoking a constexpr
function or a "normal" function (§7.1.5/7):
A call to a
constexpr
function produces the same result as a call to an equivalent non-constexpr
function in all respects except that a call to aconstexpr
function can appear in a constant expression.
Note that calls to constexpr
functions can appear in constant expressions, but nothing forbids them from not resulting in constant expressions. This is intended so one can call constexpr
functions with both compile-time and runtime arguments (otherwise usefulness of constexpr
would be severaly limited).
For completeness, let's see what makes a constant expression (§5.19/2):
A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (§3.2), but subexpressions of logical AND (§5.14), logical OR (§5.15), and conditional (§5.16) operations that are not evaluated are not considered [...].
So, divide(1, 1)
is a constant expression, but divide(1, 0)
is not. If you used divide(1, 0)
in a template parameter, the program would be ill-formed. But otherwise it's fine.