Introduction
constexpr
was not introduced as a way to tell the implementation that something can be evaluated in a context which requires a constant-expression; conforming implementations has been able to prove this prior to C++11.
Something an implementation cannot prove is the intent of a certain piece of code:
- What is it that the developer want to express with this entity?
- Should we blindly allow code to be used in a constant-expression, just because it happens to work?
What would the world be without constexpr
?
Let's say you are developing a library and realize that you want to be able to calculate the sum of every integer in the interval (0,N]
.
int f (int n) {
return n > 0 ? n + f (n-1) : n;
}
The lack of intent
A compiler can easily prove that the above function is callable in a constant-expression if the argument passed is known during translation; but you have not declared this as an intent - it just happened to be the case.
Now someone else comes along, reads your function, does the same analysis as the compiler; "Oh, this function is usable in a constant-expression!", and writes the following piece of code.
T arr[f(10)]; // freakin' magic
The optimization
You, as an "awesome" library developer, decide that f
should cache the result when being invoked; who would want to calculate the same set of values over and over?
int func (int n) {
static std::map<int, int> _cached;
if (_cached.find (n) == _cached.end ())
_cached[n] = n > 0 ? n + func (n-1) : n;
return _cached[n];
}
The result
By introducing your silly optimization, you just broke every usage of your function that happened to be in a context where a constant-expression was required.
You never promised that the function was usable in a constant-expression, and without constexpr
there would be no way of providing such promise.
So, why do we need constexpr
?
The primary usage of constexpr is to declare intent.
If an entity isn't marked as constexpr
- it was never intended to be used in a constant-expression; and even if it is, we rely on the compiler to diagnose such context (because it disregards our intent).
constexpr
? If so, I can see an usage. – ereOnconst
. In fact, mandated intent is useful! Array dimensions are the canonical example. – Lightness Races in Orbit