【问题标题】:Can I use an array in a case statement?我可以在 case 语句中使用数组吗?
【发布时间】:2015-05-30 18:26:20
【问题描述】:

我想在 C++ 的 switch/case 语句中使用 const int 数组。是否可以?到目前为止,我已经尝试过类似的东西:

int main()
{
    int const tab[3] = {1,2,3};
    int value(2);
    switch(value)
    {
        case tab[1]:
            cout << "result is: " << tab[0]<< endl;
    }
    return 0;
}

但是编译器一直告诉我:

.../main.cpp|11|error: the value of ‘tab’ is not usable in a constant expression

好吧,我将我的数组声明为“int const”,这还不够吗?

【问题讨论】:

    标签: c++ arrays switch-statement case


    【解决方案1】:

    每个case 语句都必须采用一个常量表达式,其定义为:

    一个条件表达式 e是一个核心常量表达式,除非e的求值,遵循规则的 抽象机器(1.9),将评估以下表达式之一:

    • [...]
    • 左值到右值的转换 (4.1),除非它应用于
      • 一个整数或枚举类型的非易失性左值,它引用一个非易失性常量对象 前面的初始化,用常量表达式初始化 [ 注意: 字符串字面量 (2.14.5) 对应于此类对象的数组。 ——尾注],或
      • 一个非易失性泛左值,它引用一个用constexpr 定义的非易失性对象,或者引用 到此类对象的非可变子对象,或
      • 文字类型的非易失性左值,它引用一个生命周期开始的非易失性对象 在 e 的评估范围内;
    • [...]

    您的案例是左值到右值的转换,但这三个要点都不适用,因此tab[1] 不是核心常量表达式。然而,第二个子要点为我们提供了一个线索:如果对象是用constexpr 定义的!这将使tab[1] 成为一个常量表达式,因此可以编译:

    constexpr int tab[3] = {1,2,3};
    int value(2);
    switch(value)
    {
        case tab[1]:
            cout << "result is: " << tab[0]<< endl;
    }
    

    const 不会使对象成为常量表达式。它只是使它不可变。请注意,以下是完全有效的代码:

    int x;
    cin >> x;
    const int y = x; // obviously, y can't be a constant expression
    

    【讨论】:

    • 为什么 l.t.r 条件的第一个要点不适用?
    • @0x499602D2 tab 不是整数或枚举类型。如果是const int tab = 1;,您可以使用case tab
    • 所以转换应用于tab而不是tab[1]?
    • @0x499602D2:它们都必须转换。如果 any 表达式违反条件,则适用规则。完整表达式 tab[1] 是整数类型这一事实还不够,因为评估子表达式 tab 仍然需要右值转换,并且抽象机必须评估 tab 才能评估 tab[1] .
    【解决方案2】:

    不,你不需要const,你需要constexpr。重写你的代码:

    int main()
    {
        constexpr int tab[3] = {1,2,3};
        int value(2);
        switch(value)
        {
            case tab[1]:
                cout << "result is: " << tab[0]<< endl;
        }
        return 0;
    }
    

    由于您在编译时需要 tab 的值,因此它应该是 constexpr 表达式。此外,每个 case 语句都采用 constant-expression not constant-valueconst 将使其成为常量值,而constexpr 将使其成为常量表达式

    【讨论】:

      猜你喜欢
      • 2017-05-07
      • 1970-01-01
      • 2012-05-02
      • 2011-02-24
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      相关资源
      最近更新 更多