switch 语句中预期的常量表达式惨败

发布于 2024-09-14 14:06:43 字数 1610 浏览 3 评论 0原文

假设我有一个像这样定义的类“Code”,用户指定类型转换为 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; }
};

以及使用代码类的第二个类“Master”:

class Master
{
public:
    Code master_code;
};

以及一堆预先指定的代码,如下所示:

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");

人们会认为(即我认为)可以这样使用它:

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

    case CODE_TWO:
        // ...
        break;

    case CODE_THREE:
        // ...
        break;

    default:
        // ...
}

由于自动类型转换为 int,但情况显然并非如此。 GCC 告诉我 CODE_ONE、CODE_TWO 和 CODE_THREE“不能出现在常量表达式中”。

顺便说一句,这也不起作用:

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

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

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

    default:
        // ...
}

上面返回完全相同的错误:除了“'.'之外,“'CODE_ONE'不能出现在常量表达式中”。不能出现在常量表达式中”。

但这确实有效:

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

    case 2:
        // ...
        break;

    case 3:
        // ...
        break;

    default:
        // ...
}

所以 CODE_ONE 等不能解析为常量表达式?这看起来很奇怪……还是我做错了什么?

Say I have a class "Code" defined like this, with a user specified type conversion to 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 (i.e. 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. GCC tells me that CODE_ONE, CODE_TWO and CODE_THREE "can not appear in a constant-expression".

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 "'.' 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? That seems weird... Or am I doing something wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小帐篷 2024-09-21 14:06:44

开关标签必须是编译时常量。在运行时创建 CODE_XXX 对象之后,您要比较的值才可用。

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.

一生独一 2024-09-21 14:06:44

switch case 语句的 case 标签应该是编译时常量并且应该是完整的。 CODE_ONE、CODE_TWO 等不是编译时积分常量。

参考6.4.2/2

Case labels of a switch case statements should be compile time constants and shall be integral. CODE_ONE, CODE_TWO etc are not compile time integral constants.

Refer 6.4.2/2

灯下孤影 2024-09-21 14:06:44

CODE_ONE、...等被定义为 const 的事实并不意味着它们实际上是常量表达式。 const 所做的只是“尝试”并强制这些类实例不会按照 const 定义的规则进行更改。最后,类(或结构)实例永远不会被视为完全常量表达式,因为它是动态对象。

switch 语句需要的是一个“编译时常量表达式”,对于 C++98 的所有意图和目的来说,它是一个 int 文字或枚举值(最后也是 int 文字)。

C++0x' constexpr 可以让你做更复杂的事情,比如使用常量函数,但不是您所要求的。

The fact that CODE_ONE, ... etc are defined as const does not mean they are actually constant expressions. All const does is 'try' and enforce that those class instances do not change by const defined rules. 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).

C++0x' constexpr will let you do more complex things like use constant functions, but not what you are asking for.

孤凫 2024-09-21 14:06:43

switch 语句中的标签必须是“整数常量表达式”(第 6.4.2/2 节)。整型常量表达式”定义为 (§5.19/1):

整型常量表达式只能涉及用常量表达式 (8.5) 初始化的整型或枚举类型的文字 (2.13)、枚举数、const 变量或静态数据成员、整型或枚举类型的非类型模板参数以及 sizeof表达式。浮点文字 (2.13.3) 仅在转换为整型或枚举类型时才会出现。只能使用到整型或枚举类型的类型转换。特别是,除了 sizeof 表达式之外,不得使用函数、类对象、指针或引用,并且不得使用赋值、递增、递减、函数调用或逗号运算符。

因此,您不能进行函数调用(包括转换函数),并且数据成员必须是静态的(您的不是静态的)。

The labels in a switch statement must be "integral constant-expressions" (§6.4.2/2). An integral constant expression" is defined as (§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. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. 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.

So, you can't have a function call (including a conversion function), and a data member must be static (which yours isn't).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文