使用数组下标运算符访问struct成员 [英] Accessing struct members with array subscript operator
问题描述
让一个类型T和一个只有T类型的统一元素的结构。
struct Foo {
T一,
T二,
T三
};
我想以轻松的方式访问它们:
struct Foo {
T一,
T二,
T三
T& ](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)
$ b b
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]);
}
};
href =http://stackoverflow.com/questions/3178347/accessing-struct-members-with-array-subscript-operator/3178461#3178461>使用指向数据成员的指针的snk_kid ]
,但它需要额外的查找表,我试图避免。
// EDIT
另一个。我不能只使用数组和常量来索引这些字段,它们必须是struct的命名字段(有些宏需要这样)。
// EDIT2
为什么这些必须是struct的命名字段?什么是宏?它是一个更大的项目的设置系统。简化它是这样的:struct Foo {
int one;
int two;
}
foo;
struct设置{void * obj,size_t filed_offset,const char * name,FieldType type}
#define SETTING(CLASS,OBJ,FIELD,TYPE){OBJ,cpp_offsetof (Foo,foo,one,INT_FIELD),
设置(Foo,foo,one,INT_FIELD),
设置设置[] = foo,two,INT_FIELD)
};
再次:我不是100%兼容的解决方案,而是99%。我要问,如果我们可以期望一些编译器会在统一字段之间添加不均匀填充。
解决方案使用NON-POD类型,如使用虚拟成员函数的那些。使用指向数据成员的指针,可以使用标准的(高效的)方式来实现您想要做的操作:
template<类型名T>
struct Foo {
typedef size_t size_type;
private:
typedef T Foo< T> :: * const vec [3];
static const vec v;
public:
T one;
T two;
T三;
const T& operator [](size_type i)const {
return this-> * v [i];
}
T& operator [](size_type i){
return this-> * v [i];
}
};
template<类型名T>
const typename Foo< T> :: vec Foo< T> :: v = {& Foo T&:: one,& Foo T&:: two,& Foo T三};
只要确保使用const每个指向数据成员的表来获得优化。请检查这里,看看我在说什么。
Let have a type T and a struct having ONLY uniform elements of T type.
struct Foo { T one, T two, T three };
I'd like to access them in fallowing way:
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
macro (it is considered to be correct) is:#define cpp_offsetof(s, m) (((size_t)&reinterpret_cast<const volatile char&>((((s*)(char*)8)->m))) - 8)
The C++ standard doesn't guarantee it, but can we assume that members are distanced by a fixed offset and above is correct, cross-platform solution?
100% compatible solution would be: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]); } };
[edit]standard, compliant and faster version was presented by snk_kid using pointers to data members[/edit]
but it requires extra lookup table which I'm trying to avoid.//EDIT
And one more. I cannot use just an array and constants to index these fields, they have to be named fields of a struct (some macro requires that).//EDIT2
Why those have to be named fields of a struct? What is the macro? It is settings system of a bigger project. Simplifying it's sth like this: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) };
And once again: I'm not looking form 100% compatible solution but 99%. I'm asking if we can expect that some compilers will put non-uniform padding between uniform fields.
解决方案Your code doesn't work with NON-POD types such those which using virtual member functions. There is a standard compliant (and efficient) way to achieve what you're trying to do, using pointer to data members:
template< typename T > struct Foo { typedef size_t size_type; private: typedef T Foo<T>::* const vec[3]; static const vec v; public: T one; T two; T three; const T& operator[](size_type i) const { return this->*v[i]; } T& operator[](size_type i) { return this->*v[i]; } }; template< typename T > const typename Foo<T>::vec Foo<T>::v = { &Foo<T>::one, &Foo<T>::two, &Foo<T>::three };
Just make sure you use const every with the table of pointer to data-members to get optimizations. Check here to see what I'm talking about.
这篇关于使用数组下标运算符访问struct成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!