C++;:switch语句中的结构成员 我正在编写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 >最好是使用< C++ >定义< > C++常量。此外,我将能够清晰地对操作码的所有相关属性进行分组

C++;:switch语句中的结构成员 我正在编写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 >最好是使用< C++ >定义< > C++常量。此外,我将能够清晰地对操作码的所有相关属性进行分组,c++,visual-c++,c++11,struct,constexpr,C++,Visual C++,C++11,Struct,Constexpr,然而,这似乎不适用于switch语句,正如我最初打算的那样。以下代码将不会编译,VisualStudio会给出错误“case expression not constant” 我现在不确定该怎么办,因为编译器似乎不理解结构值是作为常量分配的 class Instruction { public: constexpr Instruction(int code, int size) : opcode(code), op_size(size) {} const int opcode

然而,这似乎不适用于switch语句,正如我最初打算的那样。以下代码将不会编译,VisualStudio会给出错误“case expression not constant”

我现在不确定该怎么办,因为编译器似乎不理解结构值是作为常量分配的

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语句中使用struct成员,或者我应该切换到使用
#define
?或者,在保留一些组织的同时,是否有更好的方法来做到这一点?我真的很感激你能提供的任何帮助或见解,谢谢


编辑:对不起,我应该说得更清楚,下一条指令只是一个int,而不是一条
指令
struct/object

如果你不想冒险使用模板,没有可怕的宏的可能解决方案如下所示

template<int code, int size>
struct InstructionType
{
    static const int opcode = code ;
    static const int op_size = size;
};
struct Instruction 
{
    int opcode;
    int op_size;
};
typedef  InstructionType<0x76, 1> HALT;
typedef  InstructionType<0x00, 1> NOP;


int main()
{
    Instruction next_instruction;
    switch (next_instruction.opcode) {
    case HALT::opcode:
        // do stuff
        break;
    case NOP::opcode:
        // do stuff
        break;
    default:
        std::cout << "Unrecognized opcode" << std::endl;
        break;
    }
}
模板
结构指令类型
{
静态常量int操作码=代码;
静态常量int op_size=大小;
};
结构指令
{
int操作码;
整数运算单位大小;
};
typedef指令typehalt;
类型定义指令类型NOP;
int main()
{
指令下一个指令;
开关(下一个指令操作码){
案例暂停::操作码:
//做事
打破
案例NOP::操作码:
//做事
打破
违约:

我已经用MingW4.8.3编译器在QtCreator3.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;
        }
}
struct指令
{
常量int操作码;//指令操作码
const int op_size;//程序计数器的前进距离
};
//将这两行中的“const”替换为“constexpr”
constexpr指令暂停{0x76,1};
constexpr指令NOP{0x00,1};
int main(){
int next_指令=0x76;
switch(next_指令){//next_指令是从文件解析的int
case HALT.opcode:
//做事
打破
案例NOP.opcode:
//做事
打破
违约:

std::cout暂时从树中退一步,您编写的8080/Z80仿真器是相当安全的。因此,根本不要使用开关。将指令结构安排在数组中,并使用要执行的操作码作为索引

struct instruction
{
    const int opcode; // instruction opcode
    const int op_size; // how far to advance Program Counter
    const void (*emulator)(parameter list);  // code for this opcode
};

void illegal(parameter list)
{
    std::cout << "Unrecognized opcode" << std::endl;
}

instruction opcodes[] =  // assuming 8080 for now
{
{0x00, 1, nop_emulator},  // NOP
{0x01, 3, lxib_emulator}, // LXI B
etc.
{0x08, 1, illegal},       // 0x08 is invalid on the 8080
etc.
};
您可以选择放弃操作码,或者进行预检查以确保每个操作码都位于表中的正确位置


这还有一个优点,就是通过将代码分解为每个操作码的一个例程,它可以阻止代码成为一个单一例程。若您正在编写Z80仿真器,这将成为一个主要问题,因为0xCB、0xDD、0xED和0xFD组,在切换模式中,每个案例处理程序中都需要第二个切换r这四个伪操作码。

您的
constepr
版本应该可以工作。因此,可能是编译器没有正确实现这一点。但无论如何,您应该显示
next\u指令的定义。
constepr
仅在Visual Studio next(14)中实现,Visual Studio 2013未实现它。此外,VS的最新版本是2013更新3,而不是11月的CTP。此外,您的代码带有“类型切换反模式”的味道。您可能可以在此处使用多态性(动态或静态)而不是条件:。大多数情况下,它可能更快(您需要对其进行分析)@Rimas:你为什么要创建不必要的对象?
struct instruction
{
    const int opcode; // instruction opcode
    const int op_size; // how far to advance Program Counter
    const void (*emulator)(parameter list);  // code for this opcode
};

void illegal(parameter list)
{
    std::cout << "Unrecognized opcode" << std::endl;
}

instruction opcodes[] =  // assuming 8080 for now
{
{0x00, 1, nop_emulator},  // NOP
{0x01, 3, lxib_emulator}, // LXI B
etc.
{0x08, 1, illegal},       // 0x08 is invalid on the 8080
etc.
};
opcodes[next_instruction].emulator(parameter list);