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

标签 c++ visual-c++ c++11 struct constexpr

我正在用 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 expression not constant”。

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)以尝试利用 C++11 中的 constexpr,但我遇到了同样的问题,它无法编译。在这里,我将我的结构转换为类并尝试利用 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?或者,有没有更好的方法来做到这一点,同时仍然保留一些组织?如果您能提供任何帮助或见解,我将不胜感激,谢谢!

编辑:抱歉,我应该更清楚地说明 next_instruction 只是一个 int,而不是 instruction struct/object

最佳答案

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

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;
        }
}

编辑以添加一些引号:

The C++ Programming Language (Fourh Edition) 关于 switch 语句中的标签的说法:

The expression in the case labels must be a constant expression of integral or enumeration type.” (9.4.2 switch Statements”).

摘自第 10.4 节常量表达式:

C++ offers two related meaning of “constant”:

  • constexpr: Evaluate at compile time
  • const: Do not modify in this scope

Basically, constexpr’s role is to enable and ensure compile-time evaluation, whereas const’s primary role is to specify immutability in interfaces.

[…]

10.4.2 const’s in Constant Expressions

[…] A const initialized with a constant expression can be used in a constant expression. A const differs from a constexpr in that it can be initialized by something that is not a constant expression; in that case, the const cannot be used as a constant expression.

switch 语句中的标签需要 constexpr,以便在编译时完成评估。 因此,const instruction HALT {0x76,1} 似乎不能确保编译时评估,而 constexpr instruction HALT {0x076,1} 可以。

关于C++:switch 语句中的结构成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25801763/

相关文章:

c++ - 没有针对该函数的警告 int f() 不返回任何值?

C++11 完美转发和引用折叠

c++ - 加入线程时无限循环

c++ - 如何替换 std multimap 中的 <key, value>

c++ - 解析 HTTP 摘要认证的正确正则表达式模式是什么?

c++ - 如何将 TCHAR 数组与字符串连接起来?

C++11:需要额外声明的模板特化的 constexpr 成员的标准引用?

c++ - 简单的拼写检查算法

C++ 访问子类中的数据

c++ - c++什么时候实例化方法?