我发现在 C++11 中跳过constexpr
变量时交叉初始化仍然会计算编译时错误(至少在我的编译环境中(
请考虑以下代码:
t foo()
{
return 1;
}
int main()
{
int T = foo();
if (T == 0)
goto JumpLabel;
constexpr int lowBound = 3;
constexpr int upBound = 10;
if (T >= lowBound && T <= upBound)
return 1;
JumpLabel:
return 0;;
}
goto
语句在 C++11 中触发编译时错误。 这个错误合理吗? 它只是constexpr
变量的交叉,它们什么都不初始化! 我只有 C++11 编译器。 任何人都可以告诉我,它仍然是更高标准的错误,例如C++14,C++17?
=== 更新 ===
另一个不使用goto
的程序有同样的问题:
int bar()
{
return 3;
}
int foo()
{
return 1;
}
int main()
{
int T = foo();
int U = bar();
switch (T) {
case 0:
constexpr int lowBound = 3;
constexpr int upBound = 10;
if (U >= lowBound && U <= upBound)
return 1;
default:
T = -1;
}
return T;
}
任何人都可以告诉我,在更高的标准中,它仍然是错误吗,例如C++14,C++17?
是的,它显然仍然是。
您可以引入一个范围来解决问题,这也消除了有关初始化、生存期等的任何担忧。
您不能用goto
(或switch
结构内的跳转(交叉任何初始化,无论它是const
、constexpr
还是两者都不是。 使用 GCC,您可以使用-fpermissive
编译代码,但如果您真的认为需要goto
,请将变量初始化放在局部范围内(也可以在switch
标签之后(:
if (T == 0)
goto JumpLabel;
{
constexpr int lowBound = 3;
constexpr int upBound = 10;
if (T >= lowBound && T <= upBound)
return 1;
}
JumpLabel:
return 0;
或者在跳转之前(或在switch
外(初始化它们
constexpr int lowBound = 3;
constexpr int upBound = 10;
switch (T) {
case 0:
if (U >= lowBound && U <= upBound)
return 1;
default:
T = -1;
}
我不知道标准的相应部分,但我想这是不允许的原因是,对于非constexpr
,在访问在goto
和标签之间初始化的变量时,您会得到不清楚的行为。并且只允许它用于constexpr
并没有真正的意义(您可以在跳转之外或本地范围内初始化它(。