我如何传递一个元素以便能够在某个专业化范围内进行评估?

How can i pass an element to be able to evaluate within a certain specialization?

我正在尝试制作一个在编译时生成大部分指令的 CHIP-8 仿真器。

所以我有一个像这样的 constexpr 数组:

constexpr uint16_t hardCodedROM[] = {
    0x8001, 0x8002, 0x8003, 0xA0F0, 0xB0FE
};

我对数组的每一项都有一个专门化,如下所示:

template<uint16_t instruction> struct Opcode 
{
    static inline void Task(uint16_t code)
    { 
        printf("Unknown Opcode \n");
    }
};

template<> struct Opcode<0x8000>
{

    static inline auto Task(uint16_t code)
    {
        static constexpr unsigned char submask = code & 0x000F; //error here, code can not use as a constant

        if constexpr (submask == 0x0001)
        {
            printf("Opcode 0x8xx1 \n");
        }

        if constexpr (submask == 0x0002)
        {
            printf("Opcode 0x8xx2 \n");
        }

        if constexpr (submask == 0x0003)
        {
            printf("Opcode 0x8xx2 \n");
        }

        if constexpr (submask == 0x0000)
        {
            printf("Opcode 0x8xx0 \n");
        }
    }
};

template<> struct Opcode<0xA000>
{
    static inline auto Task(uint16_t code)
    {
        printf("Opcode 0xAxxx \n");
    }
};

template<> struct Opcode<0xB000>
{
    static inline auto Task(uint16_t code)
    {
        printf("Opcode 0xBxxx \n");
    }
};

然后我遍历每个元素并以这种方式调用特化:

[&] <std::size_t...p>(std::index_sequence<p...>)
{
    (Opcode<(hardCodedROM[p] & 0xF000)>::Task(hardCodedROM[p]), ...); //How should i pass the element, to be able to evaluate depending on each submask?
}
(std::make_index_sequence<5>{});

我应该如何传递元素 (hardCodedROM[p]),以便能够根据特定专业化中的每个子掩码进行评估?

如果 code 在编译时总是已知的,将其设为模板参数:

template<std::uint16_t code>
static void Task() {
    constexpr unsigned char submask = code & 0x000F;
    // ...
}

然后不要忘记 template 消歧器:

[&]<std::size_t...p>(std::index_sequence<p...>) {
    (Opcode<(hardCodedROM[p] & 0xF000)>::template Task<hardCodedROM[p]>(), ...);
}
(std::make_index_sequence<5>{});

您也可以将 code 包装成类似于 Opcode 的类型并将其作为函数参数传递,以避免非常难看的 template 关键字。例如:

template<std::uint16_t> struct Instruction {};

// ...
    template<std::uint16_t code>
    static void Task(Instruction<code>) { 
        constexpr unsigned char submask = code & 0x000F;
        // ...
    }
// ...

[&]<std::size_t...p>(std::index_sequence<p...>) {
    (Opcode<(hardCodedROM[p] & 0xF000)>::Task(Instruction<hardCodedROM[p]>{}), ...);
}
(std::make_index_sequence<5>{});