介绍
constexpr
并不是为了告诉实现可以在需要常量表达式的上下文中评估某些东西的方式而引入的;一致的实现能够在C ++ 11之前证明这一点。
实现无法证明的是某段代码的意图:
- 开发人员想用这个实体表达什么?
- 我们是否应该仅仅因为代码恰好起作用而就盲目地在常量表达式中使用代码?
没有这个世界会是constexpr
什么?
假设您正在开发一个库,并且意识到您希望能够计算interval中每个整数的总和(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];
}
结果
通过引入愚蠢的优化,您打破了恰好在需要常量表达式的情况下使用函数的所有用法。
您从未保证过该函数可以在常量表达式中使用,否则constexpr
就无法提供这种保证。
那么,为什么需要constexpr
呢?
constexpr的主要用法是声明intent。
如果一个实体没有被标记为constexpr
-绝不打算在常量表达式中使用它;即使是这样,我们也依靠编译器来诊断此类上下文(因为它无视我们的意图)。
constexpr
?如果是这样,我可以看到用法。