class 范围内的 constexpr 变量的初始值设定项是否允许引用该变量?
Is the initializer of a constexpr variable at class scope allowed to reference the variable?
以下代码:
struct S {
static constexpr int rolling_sum[4]{
0,
rolling_sum[0] + 1,
rolling_sum[1] + 2,
rolling_sum[2] + 3
};
};
被 clang 接受(用版本 12 测试),但被 gcc 拒绝(用版本 11 测试)并出现以下错误:
test.cpp:4:9: error: ‘rolling_sum’ was not declared in this scope
4 | rolling_sum[0] + 1,
| ^~~~~~~~~~~
test.cpp:5:9: error: ‘rolling_sum’ was not declared in this scope
5 | rolling_sum[1] + 2,
| ^~~~~~~~~~~
test.cpp:6:9: error: ‘rolling_sum’ was not declared in this scope
6 | rolling_sum[2] + 3
| ^~~~~~~~~~~
此代码是否有效 C++?
我的猜测是它应该是有效的,因为 [basic.scope.pdecl] p1 指出变量的声明点就在其初始化程序之前,这意味着该变量应该在其初始化程序的范围内;但我不确定我是否忽略了其他可能与此处相关的内容。
你没有遗漏任何东西。这是 GCC bug 99059,在 GCC 11 中报告。
您的情况也适用,因为就像 static inline
一样,constexpr
变量必须在声明时初始化。同样的查找相关错误也会影响 C++14 代码。
正如您引用的 [basic.scope.pdecl]/1 所允许的(因为 /3 的 none 和转发拒绝它),您的程序是合式的。
我们可以研究一个类似的例子,GCC 混淆地拒绝了以下部分:
struct S {
static constexpr int x{42};
static constexpr int y[2]{
S::x, // #1 GCC: OK
S::y[0] + 1 // #2 GCC: error: incomplete type 'S' used in nested name specifier
};
};
在 #2 处有一条错误消息,可以说(如果不是拒绝无效)应该应用于 #1。
代码已被 clang
接受。如果数组在 namespace scope
处声明,它也会被 gcc
接受,这让我相信:
rejecting it at class scope is likely a bug
ICC
和 MSVC
拒绝它类似于 GCC
甚至。
我相信它是有效的,因为变量的 point of declaration
就在其初始化之前,因此变量应该在其初始化程序的范围内。
Point of declaration
但我不是措辞专家,可能是我弄错了,或者忽略了其他可能导致此无效的内容。
以下代码:
struct S {
static constexpr int rolling_sum[4]{
0,
rolling_sum[0] + 1,
rolling_sum[1] + 2,
rolling_sum[2] + 3
};
};
被 clang 接受(用版本 12 测试),但被 gcc 拒绝(用版本 11 测试)并出现以下错误:
test.cpp:4:9: error: ‘rolling_sum’ was not declared in this scope
4 | rolling_sum[0] + 1,
| ^~~~~~~~~~~
test.cpp:5:9: error: ‘rolling_sum’ was not declared in this scope
5 | rolling_sum[1] + 2,
| ^~~~~~~~~~~
test.cpp:6:9: error: ‘rolling_sum’ was not declared in this scope
6 | rolling_sum[2] + 3
| ^~~~~~~~~~~
此代码是否有效 C++?
我的猜测是它应该是有效的,因为 [basic.scope.pdecl] p1 指出变量的声明点就在其初始化程序之前,这意味着该变量应该在其初始化程序的范围内;但我不确定我是否忽略了其他可能与此处相关的内容。
你没有遗漏任何东西。这是 GCC bug 99059,在 GCC 11 中报告。
您的情况也适用,因为就像 static inline
一样,constexpr
变量必须在声明时初始化。同样的查找相关错误也会影响 C++14 代码。
正如您引用的 [basic.scope.pdecl]/1 所允许的(因为 /3 的 none 和转发拒绝它),您的程序是合式的。
我们可以研究一个类似的例子,GCC 混淆地拒绝了以下部分:
struct S {
static constexpr int x{42};
static constexpr int y[2]{
S::x, // #1 GCC: OK
S::y[0] + 1 // #2 GCC: error: incomplete type 'S' used in nested name specifier
};
};
在 #2 处有一条错误消息,可以说(如果不是拒绝无效)应该应用于 #1。
代码已被 clang
接受。如果数组在 namespace scope
处声明,它也会被 gcc
接受,这让我相信:
rejecting it at class scope is likely a bug
ICC
和 MSVC
拒绝它类似于 GCC
甚至。
我相信它是有效的,因为变量的 point of declaration
就在其初始化之前,因此变量应该在其初始化程序的范围内。
Point of declaration
但我不是措辞专家,可能是我弄错了,或者忽略了其他可能导致此无效的内容。