我还能如何访问位域成员?
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
。
所以我知道你不能有指向位域的指针,因为指针只能区分字节级别的地址,而不是位级别。也不允许引用位域。还有其他方法可以间接引用位域的成员吗?理想情况下,我可以使用类似于下面的 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
。