class TestClass1{ public:
static constexpr int getInt(){return 0;};
static constexpr int y = getInt();//why it's wrong?
TestClass1(){}
};
编译失败了,why?
1
enenaaa 2018-06-06 17:36:14 +08:00
constexpr 也要遵守基本法。c++类成员声明不接受赋值啊。
|
3
enenaaa 2018-06-06 17:46:22 +08:00
不好意思, 我忘了 static 变量是可以的
|
4
wens07 2018-06-06 17:48:03 +08:00
getInt 是一个 expresion,这样不行的吧
|
5
paparika OP 编译器报的 error: ‘ static constexpr int TestClass1::getInt()’ called in a constant expression
|
6
wwqgtxx 2018-06-06 17:49:08 +08:00
GCC 的提示说的挺清楚的了吧
error: 'static constexpr int TestClass1::getInt()' called in a constant expression before its definition is complete |
7
wwqgtxx 2018-06-06 17:50:32 +08:00
也就是说这样写是可行的
class TestClass1{ public: static constexpr int getInt(){return 0;}; TestClass1(){} }; class TestClass2{ public: static constexpr int y = TestClass1::getInt();//why it's wrong? TestClass2(){} }; |
9
wwqgtxx 2018-06-06 17:58:15 +08:00
@paparika 他的意思是只能在类的定义完成之后才能以 constexpr 的形式调用,至于为什么,你可能需要翻翻 C++的标准了
|
11
vsomeone 2018-06-06 18:37:09 +08:00
自 https://stackoverflow.com/questions/11522399/constexpr-initializing-static-member-using-static-function:
The most likely reason for this is that constexpr variables have to be available as compile-time constant expressions from inside the bodies of member functions, so the variable initializers are completely defined before the function bodies -- which means the function is still incomplete (undefined) in the context of the initializer, and then this rule kicks in, making the expression not be a constant expression. 大致意思就是,由于 constexpr 必须是 compile-time known 的,所以它们的 initializer 定义位于它们所在的 function/class 之外。因此,你的代码等价于: ```c++ constexpr int TestClass1::y = initializer_for_y(); class TestClass1{ public: static constexpr int getInt(){return 0;}; static constexpr int y;//why it's wrong? TestClass1(){} }; ``` 但是在 initializer_for_y() 试着调用 getInt() 的时候 TestClass1 尚未定义。这也就是为什么编译器会报告: note: undefined function 'getInt' cannot be used in a constant expression |
12
gnaggnoyil 2018-06-06 23:38:50 +08:00
@paparika 然而你现在只能这样强行理解……因为事实上标准中没有任何字句显式要求成员函数的类内定义一定不能在类的内部起效,而只是要求在类内部的时候类是一个不完全类型……换句话说标准没有要求你这种写法一定是错的.事实上你会发现在 Clang 和 GCC 下只要给 TestClass1 加一个模板参数编译错误就嗷的一声不见了…… https://wandbox.org/permlink/MiclIS7tSl4qR91C
我搜了一下发现 CWG1626( http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1626)提到了这个问题,然而很明显 WG21 至今仍在无视这个 2013 年就提出来的 CWG... |
13
gnaggnoyil 2018-06-06 23:44:11 +08:00
@gnaggnoyil 干……发错.演示地址是这个: https://wandbox.org/permlink/hDmeC12PUHPRmoPp
|
14
paparika OP |
15
alqaz 2018-06-08 17:30:31 +08:00
@gnaggnoyil 是不是可以理解成编译器处理模板在处理 constexpr 之前,加了模板参数之后,先扫描一边 TestClass1,此时编译器对 TestClass1::getInt() constexpr 函数已经知道了。然后处理 constper 相关的计算也就可以了。
|
16
gnaggnoyil 2018-06-08 17:49:36 +08:00
没仔细读 GCC 和 Clang 的源码.不过它们都是支持 two-phase lookup 的而你理解的这种行为按照 two-phase lookup 的要求是 ill-formed,虽然没要求有 diagnostics...
|