使用常量初始化constexpr,-- int与float

28

我想知道为什么整数ii在编译时初始化,但这里的浮点数ff却不是:

int main() {
  const int i = 1;
  constexpr int ii = i;

  const float f = 1.0;
  constexpr float ff = f;
 }

这是我尝试编译时所发生的情况:

> g++ -std=c++11 test.cc
test.cc: In function ‘int main()’:
test.cc:6:24: error: the value of ‘f’ is not usable in a constant expression
   constexpr float ff = f;
                        ^
test.cc:5:15: note: ‘f’ was not declared ‘constexpr’
   const float f = 1.0;

2
常量整数在C++中有些特殊。 - bolov
我的钱投在编译器实现标准不完整或有缺陷上。虽然我没有检查过,但直觉告诉我是这样的……你尝试过其他编译器(例如clang++)吗? - Parthian Shot
@Parthean g++ -std=gnu++11 test.cc 产生了完全相同的结果,而clang在它自己的“语言”中也是如此。 - Don Slowik
3
基本上是出于历史原因。最近,CWG 决定不改变 这里的规则。 - T.C.
1
可能是重复问题:将const赋值给constexpr变量 - NathanOliver
我相信相关的标准规范可以在N3337中的§5.19 ¶ 2的第9项找到,但我不确定。 - 5gon12eder
2个回答

23

具有常量初始化器的整数类型的常量变量是整数常量表达式(实际上隐式地视为constexpr;请参见 ISO C++ 中的 expr.const)。float 不是整数类型,没有使用 constexpr 无法满足常量表达式的要求。(一个类似的例子是为什么int可以但float不能成为模板参数。)


这可以解释事情。其他整数类型(bool,short-long long)也确认了类似的行为。此外,请参见@T.C.上面提供的链接,以了解为什么事情会变成这样的讨论。 - Don Slowik
所以Bjarne在10.4.2节中说错了话,他说“使用常量表达式初始化的const可以在常量表达式中使用。”他给出了int情况作为例子,而不是float... - Don Slowik
简单的解决方法是在 OP 中明确标记 const float f 为 constexpr float f。这就是标准人员从 T.C. 的链接中讨论的可能要求 ints 的方式。 - Don Slowik
是的,我认为Bjarne的定义相当模糊。即使在他下面的例子中,使用“const string”不可能遵守非文字类型的规则。 - StenSoft
是的,constexpr string s = "asdf"; //error更好地说明了constexpr需要一个字面类型。 - Don Slowik

11

C++中,常量整数与其他常量类型不同对待。如果它们使用编译时常量表达式进行初始化,则可以在编译时表达式中使用它们。这是为了使数组大小可以是const int而不是像C语言中强制使用#define

(假设没有VLA扩展)

const int s = 10;
int a[s];          // OK in C++

3
"and if you don't take their address" -- 这不是规则的一部分。你可以取得 s 的地址,仍然可以将其用作数组长度。这是安全的,因为即使你可以获取 s 的地址,你也不能修改被定义为 const 类型的对象。 - user743382
1
@hvd 谢谢。那个规则是用于在类中初始化非静态 const 整数数据成员的。我以为它也适用于这里。 - bolov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接