在Can templates be used to access struct variables by name?有一個模板函數的例子允許設置給定結構的任意成員。 簡化示例:可以使用C++中的模板名稱來訪問Bitfield成員嗎?
#include <iostream>
#include <ostream>
#include <string>
template < typename T, typename M, typename V >
void set(T *obj, M mem, V val)
{
obj->*mem = val;
}
struct Obj1
{
int a;
double b;
};
struct Obj2
{
std::string foo;
float bar;
};
int main()
{
Obj1 o1;
o1.a=10;
o1.b=10;
Obj2 o2;
o2.foo="foobarbaz";
o2.bar=3.2f;
std::cout<<"o1.a="<<o1.a<<", o1.b="<<o1.b<<std::endl;
set(&o1, &Obj1::a, 30);
std::cout<<"o1.a="<<o1.a<<", o1.b="<<o1.b<<std::endl;
std::cout<<"o2.foo="<<o2.foo<<", o2.bar="<<o2.bar<<std::endl;
set(&o2, &Obj2::foo, "example text");
std::cout<<"o2.foo="<<o2.foo<<", o2.bar="<<o2.bar<<std::endl;
return 0;
}
這個按預期工作。但是,它不適用於位域,因爲不能指向位域成員。所以,我的問題是,有沒有辦法爲這樣的字段寫這樣的東西?再說了,我想訪問的成員:
struct Obj3
{
unsigned char first:3;
unsigned char second:5;
};
問候,
MOX
編輯: 如果我擴展代碼來
#include <iostream>
#include <ostream>
#include <string>
template < typename T, typename M, typename V >
void set(T *obj, M mem, V val)
{
obj->*mem = val;
}
struct Obj1
{
int a;
double b;
};
struct Obj2
{
std::string foo;
float bar;
};
struct Obj3
{
unsigned char first:3;
unsigned char second:5;
};
int main()
{
Obj1 o1;
o1.a=10;
o1.b=10;
Obj2 o2;
o2.foo="foobarbaz";
o2.bar=3.2f;
Obj3 o3;
o3.first=1;
o3.second=1;
std::cout<<"o1.a="<<o1.a<<", o1.b="<<o1.b<<std::endl;
set(&o1, &Obj1::a, 30);
std::cout<<"o1.a="<<o1.a<<", o1.b="<<o1.b<<std::endl;
std::cout<<"o2.foo="<<o2.foo<<", o2.bar="<<o2.bar<<std::endl;
set(&o2, &Obj2::foo, "example text");
std::cout<<"o2.foo="<<o2.foo<<", o2.bar="<<o2.bar<<std::endl;
std::cout<<"o3.first="<<o3.first<<", o1.second="<<o3.second<<std::endl;
set(&o3, &Obj3::second, 2);
std::cout<<"o3.first="<<o3.first<<", o1.second="<<o3.second<<std::endl;
return 0;
}
我收到以下錯誤信息:
$ g++ main.cpp && ./a.out
main.cpp: In function ‘int main()’:
main.cpp:56:18: error: invalid pointer to bit-field ‘Obj3::second’
set(&o3, &Obj3::second, 2);
編輯:(我的use_case) 我寫一種驅動程序與只讀的i2c設備進行通信。 這樣做的通常的舊C方法需要#定義寄存器地址,寄存器中每個位的偏移量,然後保存一堆uint16_t my_register_whatever值。訪問將通過按位操作完成。我想嘗試更類似C++的方法:
struct __attribute__((__packed__))
{
unsigned char address : 7;
unsigned char DAC : 4;
unsigned char ADC : 1;
unsigned char MIC : 3;
unsigned char LINE : 1;
} power_down_control;
這將增加類型安全性和更清晰,更易讀的語法。 現在,由於我的I²C設備不允許讀取,並且在進行I²C傳輸時可能會出現錯誤,因此我想複製寄存器結構,更改一個或多個值,將其發送到設備,並且如果傳輸完成,使用更改後的副本覆蓋寄存器結構。
你試過了嗎?編譯器說了什麼? – luk32
對於這種繁瑣的價值設置(除了學術),用例是什麼? –
同意Dieter。你可以在你感興趣的位域中實現一個帶有偏移量的「uberpointer」,但是我強烈建議不要這樣做(此外它在C中是**不可移植的)。這看起來像一個XY問題或純學術問題。 –