我还能如何访问位域成员?

How else can I access a bit field members?

所以我知道你不能有指向位域的指针,因为指针只能区分字节级别的地址,而不是位级别。也不允许引用位域。还有其他方法可以间接引用位域的成员吗?理想情况下,我可以使用类似于下面的 mys1array 行的数组语法来访问它们。我知道引用数组是非法的,但也许有人对其他一些可以实现类似目标的机制有一定的了解。

typedef struct{
    unsigned short a : 5;
    unsigned short b : 3;
    unsigned short c : 8;
}myStruct;

class myClass{
public:
    myStruct s1;
    //unsigned short &mys1array[] = {&s1.a, &s1.b ,&s1.c};
};

您只能通过 class 访问位域。您可以通过指向封闭的 class 对象的指针或引用来获得间接寻址。

如果您想迭代 class 中的位域,您可以编写自定义迭代器,但实现此类迭代器可能需要一些明确的 hard-coding,因为 C++ 缺乏反射功能来使其自动化。这是一个不完整的 proof-of-concept:

struct myStruct {
    unsigned short a : 5;
    unsigned short b : 3;
    unsigned short c : 8;

    struct reference {
        myStruct* parent;
        unsigned char field;
        
        operator unsigned short() {
            switch(field) {
                case 0: return parent->a;
                case 1: return parent->b;
                case 2: return parent->c;
                default: assert(false);
            }
        }
        
        reference& operator=(unsigned short u) {
            switch(field) {
                case 0: parent->a = u; return *this;
                case 1: parent->b = u; return *this;
                case 2: parent->c = u; return *this;
                default: assert(false);
            }
        }
        
        void operator++() {
            ++field;
        }
        
        friend auto operator<=>(const reference&, const reference&) = default;
    };
    
    struct iterator
    {
        //TODO add missing member definitions, const overloads etc.
        
        reference current;
        reference operator*() {
            return current;
        }
        void operator++() {
            ++current;
        }
        
        friend auto operator<=>(const myStructIterator&, const myStructIterator&) = default;
    };
    
    iterator begin() {
        return {this, 0};
    }
    
    iterator end() {
        return {this, 3};
    }
};

int main()
{
    myStruct s {};
    for(int i=3; auto f : s) {
        f = i++;
    }
    for(auto f : s) {
        std::cout << f << '\n';
    }
}

reference class 足以表示位字段的间接寻址,iterator 允许将这些字段视为可迭代范围。

您可以使用由 lambda 初始化的函数指针数组来访问具有不同函数的位域的每个元素。

class myClass {
public:
    myStruct s1;
    static constexpr unsigned short (*accessors)(myStruct const &s)[] = {
        +[](myStruct const &s) -> unsigned short { return s.a; }
        // ...
    };
};

有了这个,你必须将 myStruct 的实例传递给函数。另一种方法是使用 std::function 并使用捕获 lambdas:

class myClass {
public:
    myStruct s1;
    std::function<unsigned short()> accessors[3];

    myClass(myStruct s)
        : s1(s),
          accessors{
              [this]() -> unsigned short { return this->s1.a; },
              // ...
          }
    {}

    // ...
};

不要忘记,您必须实现复制和移动构造函数以及赋值运算符,因为 lambda 捕获 this