C ++ 11 - 不能使用constexpr函数定义constexpr文字吗?

时间:2016-12-08 20:42:25

标签: c++ c++11 gcc constexpr

我遇到了似乎违反直觉的错误,即无法将constexpr函数的值分配给constexpr字面(希望我使用该语言)对)。这是一个例子:

class MyClass {
 public:
  static constexpr int FooValue(int n) { return n + 5; }
  static constexpr int Foo5 = FooValue(5);  // compiler error
  static constexpr int Foo5Alt(void) { return FooValue(5); }  // OK
};

在GCC 4.8.4中,Foo5被标记为field initializer is not constant。发现this thread表明旧版GCC可能是罪魁祸首。所以我将其插入Coliru(GCC 6.2.0)并收到错误'static constexpr int MyClass::FooValue(int)' called in a constant expression before its definition is complete。我添加了Foo5Alt(),它将其值作为constexpr函数而不是文字返回,并且编译得很好。

我想我没有注意为什么FooValue(5)无法用作Foo5的初始值设定项。 FooValue(int n)的定义已经完成,不是吗? { return n + 5; }是整个定义。 constexpr表示可以在编译时完全评估的表达式,那么为什么不能用它来定义constexpr字面值的返回值?

我错过了C ++的微妙之处?

2 个答案:

答案 0 :(得分:5)

在C ++中,只有在类的声明完成后才会解析类的成员函数的内联定义。

所以即使编译器“知道”了MyClass::FooValue(int),它还没有“看到”它的定义,因此它不能用在constexpr表达式中。

一般的解决方法是坚持constexpr成员函数,或在类外声明constexpr常量。

答案 1 :(得分:4)

根据标准,当您尝试调用MyClass初始化FooValue时,Foo5被视为不完整类型。因此,您不能像过去那样使用其成员 在结束} 时,该类型被视为完全定义的对象类型(或完整类型)。
另一方面,该类在函数体中被视为完整。这就是Foo5Alt编译得很好的原因 有关详细信息,请参阅[class.mem]/6