简体   繁体   English

预期常量表达式在switch语句中失败

[英]Expected constant expression fails miserably in switch statement

Say I have a class "Code" defined like this, with a user specified type conversion to int: 假设我有一个这样定义的“代码”类,并且用户指定了将类型转换为int的类型:

class Code
{
public:    
    int code;
    std::string description;

    Code (const int c, const std::string& d) : code(c), description(d) { ; }

    operator int() const { return code; }
};

And a second class "Master" using the code class: 第二类“大师”使用代码类:

class Master
{
public:
    Code master_code;
};

As well as a bunch of pre-specified codes, like this: 以及一堆预先指定的代码,例如:

const Code CODE_ONE    (1, "This is code one");
const Code CODE_TWO    (2, "This is code two");
const Code CODE_THREE  (3, "This is code three");

One would think (ie I would think) that one could use it like this: 一个人会认为(即我会认为)可以这样使用它:

Master master_obj;
switch (master_obj.master_code)
{
    case CODE_ONE:
        // ...
        break;

    case CODE_TWO:
        // ...
        break;

    case CODE_THREE:
        // ...
        break;

    default:
        // ...
}

due to the automatic type conversion to int, but this is apparently not the case. 由于将类型自动转换为int,但事实并非如此。 GCC tells me that CODE_ONE, CODE_TWO and CODE_THREE "can not appear in a constant-expression". GCC告诉我CODE_ONE,CODE_TWO和CODE_THREE“不能出现在常量表达式中”。

This does not work either, by the way: 顺便说一句,这也不起作用:

Master master_obj;
switch (master_obj.master_code)
{
    case CODE_ONE.code:
        // ...
        break;

    case CODE_TWO.code:
        // ...
        break;

    case CODE_THREE.code:
        // ...
        break;

    default:
        // ...
}

The above returns the exact same error: "'CODE_ONE' can not appear in a constant-expression" in addition to a "'.' 上面的代码返回完全相同的错误:除了“'”之外,“'CODE_ONE'不能出现在常量表达式中”。 can not appear in a constant-expression". 不能出现在常量表达式中”。

But this does work: 但这确实有效:

Master master_obj;
switch (master_obj.master_code)
{
    case 1:
        // ...
        break;

    case 2:
        // ...
        break;

    case 3:
        // ...
        break;

    default:
        // ...
}

So CODE_ONE etc. can't be resolved as constant expressions? 所以CODE_ONE等不能解析为常量表达式吗? That seems weird... Or am I doing something wrong? 看起来很奇怪...还是我做错了什么?

The labels in a switch statement must be "integral constant-expressions" (§6.4.2/2). switch语句中的标签必须是“整数常量表达式”(第6.4.2 / 2节)。 An integral constant expression" is defined as (§5.19/1): 整数常量表达式”定义为(§5.19/ 1):

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. 整数常量表达式只能包含用常量表达式(8.5)初始化的整数或枚举类型的文字(2.13),枚举数,const变量或静态数据成员,整数或枚举类型的非类型模板参数以及sizeof表达式。 Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. 浮动文字(2.13.3)仅在将其强制转换为整数或枚举类型时才能显示。 Only type conversions to integral or enumeration types can be used. 只能使用类型转换为整数或枚举类型。 In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used. 特别是,除了sizeof表达式外,不得使用函数,类对象,指针或引用,并且不应使用赋值,递增,递减,函数调用或逗号运算符。

So, you can't have a function call (including a conversion function), and a data member must be static (which yours isn't). 因此,您不能进行函数调用(包括转换函数),并且数据成员必须是静态的(不是您的)。

The switch labels must be compile-time constants. 开关标签必须是编译时常量。 The values you want to compare aren't available until after the CODE_XXX objects have been created at runtime. 在运行时创建CODE_XXX对象之前,要比较的值不可用。

Case labels of a switch case statements should be compile time constants and shall be integral. 开关case语句的case标签应为编译时间常数,并且应为整数。 CODE_ONE, CODE_TWO etc are not compile time integral constants. CODE_ONE,CODE_TWO等不是编译时积分常数。

Refer 6.4.2/2 参照6.4.2 / 2

The fact that CODE_ONE, ... etc are defined as const does not mean they are actually constant expressions. CODE_ONE,...等被定义为const的事实并不意味着它们实际上是常量表达式。 All const does is 'try' and enforce that those class instances do not change by const defined rules. 所有const所做的只是“尝试”并强制那些类实例不被const定义的规则更改。 In the end a class(or struct for that matter) instance is never considered a fully constant expression since it is a dynamic object. 最后,由于类(或结构)实例是动态对象,因此它永远不会被视为完全常量表达式。

What a switch statement needs is a "compile-time constant expression" which for all intents and purposes regarding C++98 is an int literal or an enum value(also int literal in the end). switch语句需要的是一个“编译时常量表达式”,对于C ++ 98的所有意图和目的,该表达式都是int文字或枚举值(最后也是int文字)。

C++0x' constexpr will let you do more complex things like use constant functions, but not what you are asking for. C ++ 0x的constexpr可以让您做更复杂的事情,例如使用常量函数,而不是您要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM