让我们有一个类型 T 和一个只有 T 类型的统一元素的结构。
struct Foo {
T one,
T two,
T three
};
我想以休闲的方式访问它们:
struct Foo {
T one,
T two,
T three
T &operator [] (int i)
{
return *(T*)((size_t)this + i * cpp_offsetof(Foo, two));
}
};
其中cpp_offsetof
宏(被认为是正确的)是:
#define cpp_offsetof(s, m) (((size_t)&reinterpret_cast<const volatile char&>((((s*)(char*)8)->m))) - 8)
C++ 标准不保证这一点,但我们可以假设成员之间有一个固定的偏移量,以上是正确的跨平台解决方案吗?
100% 兼容的解决方案是:
struct Foo {
T one,
T two,
T three
T &operator [] (int i) {
const size_t offsets[] = { cpp_offsetof(Foo, one), cpp_offsetof(Foo, two), cpp_offsetof(Foo, three) };
return *(T*)((size_t)this + offsets[i]);
}
};
[编辑] snk_kid 使用指向数据成员的指针提供了标准、合规和更快的版本[/edit]
但它需要额外的查找表,我试图避免这种情况。
//编辑
还有一个。我不能只使用数组和常量来索引这些字段,它们必须被命名为结构的字段(某些宏需要)。
//EDIT2
为什么必须命名结构的字段?什么是宏?它是一个更大项目的设置系统。简化它是这样的:
struct Foo {
int one;
int two;
}
foo;
struct Setting { void *obj, size_t filed_offset, const char *name, FieldType type }
#define SETTING(CLASS, OBJ, FIELD, TYPE) { OBJ, cpp_offsetof(CLASS, FIELD), #OBJ #FIELD, TYPE }
Setting settings[] = {
SETTING(Foo, foo, one, INT_FIELD),
SETTING(Foo, foo, two, INT_FIELD)
};
再一次:我不是在寻找 100% 兼容的解决方案,而是 99%。我在问我们是否可以期望一些编译器会在统一字段之间放置非统一填充。