Am I right, that:
- Any function defined with
constexpr
is a pure function, and - Any pure function can be and must be defined with
constexpr
if it's not very expensive for compiler.
And if so, why arent <cmath>
's functions defined with constexpr
?
To add to what others have said, consider the following constexpr
function template:
template <typename T>
constexpr T add(T x, T y) { return x + y; }
This constexpr
function template is usable in a constant expression in some cases (e.g., where T
is int
) but not in others (e.g., where T
is a class type with an operator+
overload that is not declared constexpr
).
constexpr
does not mean that the function is always usable in a constant expression, it means that the function may be usable in a constant expression.
(There are similar examples involving nontemplate functions.)
In addition to the previous answers: constexpr on a function restricts its implementation greatly: its body must be visible to the compiler (inline), and must consist only of a single return statement. I'd be surprised if you could implement sqrt() or sin() correctly and still meet that last condition.
constexpr
functions are not pure
because the constexpr
is a hint to the compiler that the function may be computed during the compilation if its arguments are constants and the operation mentionned in the body of the function, for these arguments, are themselves constexpr
.
The latter, using template code, allows us to demonstrate an impure constexpr
function:
template <typename T>
constexpr T add(T lhs, T rhs) { return lhs + rhs; }
instantiated with this type
DebugInteger operator+(DebugInteger lhs, DebugInteger rhs) {
printf("operator+ %i %i", lhs._value, rhs._value);
return DebugInteger(lhs._value + rhs._value);
}
Here, the operator+
is not constexpr, and may thus read/write global state.
We could say that a constexpr
function is pure
when evaluated at compilation time... but then it's simply replaced by a constant as far as the runtime is concerned.
Every constexpr
function is pure, but not every pure function can or should be constexpr
.
[Examples involving constexpr
function templates are misleading, since function templates are not functions, they're patterns by which the compiler can generate functions. The outcome of function templates, their specialisations, are functions and they will be constexpr
iff possible.]
A pure function is one that only depends on its arguments, or other constant state. That's pretty much what a constexpr
function is. In addition, constexpr
functions must be defined (not only declared) prior to their first use (recursion seems to be allowed, though), and must consist of only the return statement. That's enough to make the allowed subset Turing-complete, but the result is not necessarily the most efficient form at runtime.
Which brings us to the mathematical functions. You can probably implement constexpr
sqrt()
or sin()
, but they would have to use a recursive implementation that the compiler can evaluate at compile-time, whereas at runtime, these would be better implemented in one assembler operation. Since constexpr
uses of sqrt()
and sin()
are few and far apart, its better to maximise runtime performance instead, which requires a form that isn't constexpr
able.
You may wonder why you can't write one constexpr
version of a function and one that's used at runtime, and I'd agree that would be nice to have, but the standard says you can't overload on constexpr
ness. Maybe in C++17...
来源:https://stackoverflow.com/questions/5462388/relation-between-constexpr-and-pure-functions