C++:switch 语句中的结构成员

2024-01-26

我正在用 C++ 编写一个微处理器模拟器,我的目标之一是使其代码非常可读。为了实现操作码,我有一个结构体,用于表示各个处理器指令,它包含操作码以及程序计数器前进的距离。这个想法是将每条指令的相关信息分组。

struct instruction
{
    const int opcode; // instruction opcode
    const int op_size; // how far to advance Program Counter
};

const instruction HALT{0x76, 1};
const instruction NOP {0x00, 1};

我最初的计划是使用这个结构定义所有操作码,因为我的印象是const首选使用#define对于 C++ 常量。此外,我将能够清晰地对操作码的所有相关属性进行分组。

然而,这似乎不适用于 switch 语句,正如我最初的意图。以下代码将无法编译,并且 Visual Studio 会给出错误“case 表达式不是常量”。

switch (next_instruction) { // next_instruction is an int parsed from a file
    case HALT.opcode:
        // do stuff
        break;
    case NOP.opcode:
        // do stuff
        break;
    default:
        std::cout << "Unrecognized opcode" << std::endl;
            break;
    }

我还下载了最新的 Visual Studio 编译器(MSVC 2013 年 11 月 CTP)来尝试利用constexpr来自 C++11,但我遇到了同样的问题,并且无法编译。在这里,我将结构转换为类并尝试利用constexpr,以确保成员instruction可以用作编译时常量。

class Instruction
{
  public:
    constexpr Instruction(int code, int size) : opcode(code), op_size(size) {}
    const int opcode; // instruction opcode
    const int op_size; // how far to advance Program Counter
};

constexpr Instruction HALT(0x76, 1);
constexpr Instruction NOP (0x00, 1);

我不太确定此时该怎么做,因为编译器似乎不明白结构值被分配为常量。

那么有什么方法可以在 switch 语句中使用结构成员,或者我应该切换到使用#define?或者,是否有更好的方法来做到这一点,同时仍然保留一些组织?我非常感谢您提供的任何帮助或见解,谢谢!

EDIT:抱歉,我应该更清楚地表明 next_instruction 只是一个 int,而不是一个instruction结构/对象


我已经使用 MinGW 4.8.3 编译器在 Qt Creator 3.1.2 中测试了您的代码。 只需在每个指令定义中将 const 替换为 constexpr 就可以让编译器满意:

struct instruction
{
    const int opcode; // instruction opcode
    const int op_size; // how far to advance Program Counter
};

// Replacing "const" by "constexpr" int these two lines
constexpr instruction HALT{0x76, 1};
constexpr instruction NOP {0x00, 1};

int main() {
    int next_instruction = 0x76;
    switch (next_instruction) { // next_instruction is an int parsed from a file
        case HALT.opcode:
            // do stuff
            break;
        case NOP.opcode:
            // do stuff
            break;
        default:
            std::cout << "Unrecognized opcode" << std::endl;
                break;
        }
}

编辑以添加一些引号:

C++ 编程语言(第四版)对于 switch 语句中的标签有这样的说法:

case 标签中的表达式必须是常量表达式整数或枚举类型。”(9.4.2 switch 语句”)。

来自第 10.4 节常量表达式:

C++ 提供了“常量”的两个相关含义:

  • constexpr:在编译时评估
  • const:不要在此范围内修改

基本上,常量表达式的作用是启用和ensure编译时求值,而 const 的主要作用是指定 接口的不变性。

[…]

10.4.2 常量表达式中的 const

[...] 用常量表达式初始化的 const 可以在 常数表达式。 const 与 constexpr 的不同之处在于它可以 由非常量表达式的内容初始化;在那里面 这种情况下,const 不能用作常量表达式。

switch 语句中的标签需要 constexpr,以便在编译时完成评估。 所以看来const instruction HALT {0x76,1}不确保编译时评估constexpr instruction HALT {0x076,1} does.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++:switch 语句中的结构成员 的相关文章

随机推荐