OP 想要的(或可接受的类似的东西)可以使用 nested struct
s 来实现。
只是为了好玩,我试图模拟 OP 的意图:
#include <bitset>
struct Registers
{
int8_t A;
int8_t X;
int8_t Y;
uint8_t SP;
static constexpr uint8_t PSSize = 8;
struct PS: std::bitset<PSSize> {
enum Flags {
Carry = 0,
Zero = 1,
InterruptDisable = 2,
Decimal = 3,
Break = 4,
Unknown = 5,
Overflow = 6,
Negative = 7
};
static constexpr unsigned Size = PSSize;
constexpr PS(std::uint8_t value):
std::bitset<PSSize>((unsigned long long)value)
{ }
std::uint8_t value() const { return (std::uint8_t)to_ulong(); }
} PS;
uint16_t PC;
constexpr Registers() noexcept :
A(0),
X(0),
Y(0),
SP(0xFF),
PS(0x24),//PS(0b00100100),
PC(0)
{
}
} r;
一个小测试来证明这一点:
#include <iomanip>
#include <iostream>
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout << std::hex << std::setfill('0');
DEBUG(std::cout << Registers::PS::Flags::Carry << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::Carry] << '\n');
DEBUG(std::cout << Registers::PS::Flags::InterruptDisable << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::InterruptDisable] << '\n');
DEBUG(std::cout << Registers::PS::Flags::Break << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::Break] << '\n');
DEBUG(std::cout << Registers::PS::Size << '\n');
DEBUG(std::cout << "0x" << std::setw(2) << (unsigned)r.PS.value() << '\n');
// done
return 0;
}
输出:
std::cout << Registers::PS::Flags::Carry << '\n';
0
std::cout << r.PS[Registers::PS::Flags::Carry] << '\n';
0
std::cout << Registers::PS::Flags::InterruptDisable << '\n';
2
std::cout << r.PS[Registers::PS::Flags::InterruptDisable] << '\n';
1
std::cout << Registers::PS::Flags::Break << '\n';
4
std::cout << r.PS[Registers::PS::Flags::Break] << '\n';
0
std::cout << Registers::PS::Size << '\n';
8
std::cout << "0x" << std::setw(2) << (unsigned)r.PS.value() << '\n';
0x24
笔记:
关于命名嵌套结构Registers::PS
和Registers::PS
具有相同名称的成员是我期望的工作。不过,通常我使用大写的开始字符作为类型标识符和小写的开始字符作为变量。因此,我通常没有这个问题。
由于对此有疑问,我struct Registers
针对各种编译器进行了测试(尽管我不会将此视为对标准的证明):Compiler Explorer
从std::
容器派生应该小心(即最好不要)。可能出于性能原因,没有一个std::
容器提供virtual
具有相应后果的析构函数。在上面的代码中,这应该不是问题。
6502让我想起了我第一次尝试的Commodore 64(尽管 C64 拥有更现代的6510 CPU)。但是,那是很久以前的事了... ;-)