首页 > 解决方案 > 这是合理的跳转到标签编译错误与 constexpr 变量的初始化

问题描述

我发现在 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++c++11c++14c++17

解决方案


您不能使用 a (或结构内的跳转)来交叉任何初始化,无论它是还是两者都不是。使用 GCC,您可以使用 编译代码,但如果您真的认为需要,可以将变量初始化放在本地范围内(也可以在标签之后):gotoswitchconstconstexpr-fpermissivegotoswitch

    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您在访问在 agoto和标签之间初始化的变量时会得到不清楚的行为。并且仅仅允许它constexpr并没有真正的意义(您可以在跳转之外或在本地范围内初始化它)。


推荐阅读