使用数组下标运算符访问struct成员

adf*_*f88 1 c++ cross-platform memory-alignment

设T型和只具有T型均匀元素的结构.

struct Foo {
    T one,
    T two,
    T three
};
Run Code Online (Sandbox Code Playgroud)

我想以下面的方式访问它们:

struct Foo {
    T one,
    T two,
    T three

    T &operator [] (int i)
    {
        return *(T*)((size_t)this + i * cpp_offsetof(Foo, two));
    }
};
Run Code Online (Sandbox Code Playgroud)

其中cpp_offsetof宏(它被认为是正确的)是:

#define cpp_offsetof(s, m)   (((size_t)&reinterpret_cast<const volatile char&>((((s*)(char*)8)->m))) - 8)
Run Code Online (Sandbox Code Playgroud)

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]);
    }
};
Run Code Online (Sandbox Code Playgroud)

[编辑]标准,兼容和更快的版本由 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)
};
Run Code Online (Sandbox Code Playgroud)

再一次:我不是在寻找100%兼容的解决方案,而是99%.我问我们是否可以期望某些编译器会在统一字段之间放置非均匀填充.

snk*_*kid 7

您的代码不适用于使用虚拟成员函数的NON-POD类型.使用指向数据成员的指针,有一种标准的(并且有效的)方式来实现您正在尝试的操作:

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 };
Run Code Online (Sandbox Code Playgroud)

只需确保将const every与指向数据成员的指针表一起使用即可获得优化.点击这里查看我在说什么.

  • @ adf88:它没有摆脱查找表 - 它使查找表语言兼容(因此它将在所有编译器,平台,架构,优化等等下工作).您的实施不能说同样的事情. (2认同)