以下代码没问题:
constexpr double square_cstxpr(double x) { return x * x; }
int main() {
const int test = 5;
constexpr double result = square_cstxpr((double)test);
}
但是,如果test
的类型从const int
更改为const double
,则g ++会出现以下错误:the value of 'test' is not usable in a constant expression
。
请在此处查看g ++的代码和输出:http://coliru.stacked-crooked.com/a/2fe9b176c2b23798
有人可以解释这种行为吗?
答案 0 :(得分:7)
来自constant expression(核心常量表达式):
10)任何其他左值到右值的隐式转换,除非 左值...
a)具有整数或枚举类型,并指完整的非易失性 const对象,用常量表达式
初始化
这意味着,在这里:
const int test1 = 5;
constexpr double result1 = square_cstxpr((double)test1);
test1
是一个常量表达式,square_cstxpr
可以在编译时使用test1
作为参数调用,其结果可以分配给 constexpr变量 { {1}}。
另一方面,这里:
result
const double test2 = 5;
constexpr double result2 = square_cstxpr((double)test2);
不是常量表达式,因为它不是整数或枚举类型。因此,在test2
作为参数的情况下,无法在编译时调用square_cstxpr
。
答案 1 :(得分:6)
非constexpr
但const
变量必须是整数或枚举类型才能在常量表达式中使用。见[expr.const]/2:
除非将应用于,否则左值到右值的转换
(2.7.1)整数或枚举类型的非易失性glvalue 它指的是一个带有前面的完整的非易失性const对象 初始化,用常量表达式初始化,或[..]
这种限制的原因必须主要是历史性的。在涉及常量表达式时,浮点数已经小心处理;想想非类型模板参数。这是由于它们强烈依赖于平台的行为,这使得编译时计算的数学性能低于应有的数学时间。