使用数组下标运算符访问struct成员 [英] Accessing struct members with array subscript operator

查看:136
本文介绍了使用数组下标运算符访问struct成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让一个类型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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆