那家伙关于 constexpr 的说法是正确的
if double
被使用(或者当然是 float
)。但是,如果将 var 类型从 double
更改为整数类型(如 int、char 等),则一切正常。为什么会出现这种情况?
int main()
{
const int PI1 = 3;
constexpr int PI2 = 3;
constexpr int PI3 = PI1; // works
static_assert(PI1 == 3, ""); // works
const double PI1__ = 3.0;
constexpr double PI2__ = 3.0;
constexpr double PI3__ = PI1__; // error
static_assert(PI1__ == 3.0, ""); // error
return 0;
}
Update
:下面这行是一个错误,我的意思是PI3__ = PI1__
constexpr double PI3__ = PI1; // I meant PI1__
问题:
为什么
const int = 3
是编译时间常数而const double = 3.0
不是? 有什么理由让我应该使用
constexpr const int val;
而不是constexpr int val
?他们俩的做法似乎完全一样。根据您在评论中的回答,这就是我的答案。 C++ 标准已经说得很清楚了。不过,GCC 5.1 在这里工作得很好:https://godbolt.org/g/2oV6Hk
T 类型的转换常量表达式是一个隐式转换为 T 类型的表达式,其中转换后的常量表达式 表达式是常量表达式,隐式转换序列仅包含 § 5.20 134 c ISO/IEC N4567
[...]
(4.6) — 积分促销 (4.5),
(4.7) — 除窄化转换 (8.5.4) 之外的积分转换 (4.7),
[...]
n4567 中缩小转换 (8.5.4/7) 的参考:
缩小转换是隐式转换
- 从浮点类型到整数类型,或者
- 从 long double 到 double 或 float,或者从 double 到 float,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使无法精确表示),或者
- 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式,并且转换后的实际值将适合目标类型,并且在转换回原始类型时将产生原始值,或
- 从整数类型或无作用域枚举类型到无法表示原始类型所有值的整数类型,除非源是常量表达式,并且转换后的实际值将适合目标类型并产生原始值当转换回原始类型时。
从评论来看,OP似乎要求标准引用,它将
const int
定义为编译时常量,但 const double
不是。
相应的细节可以在5.19,
Constant Expressions
找到。特别是:
...左值到右值的转换(4.1),除非它应用于 整数或枚举类型的非易失性左值,指的是 具有先前初始化的非易失性 const 对象,已初始化 用恒定的表达...
int
是整型,double
不是整型。
编译器不允许在 constexpr 变量初始化期间进行隐式缩小或非整数提升。
这会起作用:
int main()
{
const int PI1 = 3;
constexpr int PI2 = 3;
constexpr int PI3 = PI1; // works
static_assert(PI1 == 3, ""); // works
const double PI1__ = 3;
constexpr double PI2__ = 3;
constexpr double PI3__ = double(PI1); // works with explicit cast
static_assert(PI2__ == 3, ""); // works now. PI1__ isn't constexpr
return 0;
}