介绍
constexpr
没有引入作为告诉实现可以在需要常量表达式的上下文中评估某些东西的方法;在 C++11 之前,符合标准的实现已经能够证明这一点。
实现无法证明的是某段代码的意图:
- 开发者想用这个实体表达什么?
- 我们是否应该仅仅因为它恰好可以工作就盲目地允许在常量表达式中使用代码?
没有世界会constexpr
怎样?
假设您正在开发一个库并意识到您希望能够计算区间中每个整数的总和(0,N]
。
int f (int n) {
return n > 0 ? n + f (n-1) : n;
}
缺乏意图
如果传递的参数在翻译期间已知,编译器可以很容易地证明上述函数可以在常量表达式中调用;但是您还没有将其声明为意图-恰好是这种情况。
现在其他人出现,读取您的函数,进行与编译器相同的分析;“哦,这个函数可以在常量表达式中使用!” ,并编写以下代码。
T arr[f(10)]; // freakin' magic
优化
作为“了不起”的库开发人员,您决定f
在调用时缓存结果;谁会想一遍又一遍地计算同一组值?
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];
}
结果
通过引入您愚蠢的优化,您只是破坏了恰好在需要常量表达式的上下文中的函数的所有用法。
您从未承诺该函数可用于constant-expression,否则constexpr
将无法提供此类承诺。
那么,我们为什么需要constexpr
?
constexpr的主要用途是声明意图。
如果实体未标记为constexpr
- 它从未打算用于常量表达式;即使是这样,我们也依赖编译器来诊断这种上下文(因为它无视我们的意图)。