假设有一个类型 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));
}
};
where 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 使用指向数据成员的指针 https://stackoverflow.com/questions/3178347/accessing-struct-members-with-array-subscript-operator/3178461#3178461[/edit]
但它需要额外的查找表,我试图避免。
//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% 的。我问我们是否可以期望某些编译器会在统一字段之间放置非统一填充。