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

2023-12-28

假设有一个类型 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% 的。我问我们是否可以期望某些编译器会在统一字段之间放置非统一填充。


您的代码不适用于非 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 };

只需确保将 const every 与指向数据成员的指针表一起使用即可获得优化。查看here http://www.gamedev.net/community/forums/viewreply.asp?ID=1507506看看我在说什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用数组下标运算符访问结构成员 的相关文章

随机推荐

  • jQuery $('html, body').not()

    here http jsfiddle net m2eqS 1 我希望当您单击任意位置但不在 div 上时发出警报 当我单击 div 时 也会显示警报 JS 您可以使用事件参数来查看单击了哪个目标并返回 false html body cli
  • ksoap2 铸造 getResponse()

    使用 ksoap2 lib 从 android 调用 net SOAP1 1 Web 服务时 我遇到了将响应转换为自定义对象的问题 例如 下面的代码在 httpTransport call soapAction soapEnvelope 之
  • 复制依赖项,排除某些配置

    假设项目布局如下 allprojects apply plugin java configurations provided compile extendsFrom provided project a dependencies compi
  • C# PropertyGrid 拖放

    我正在尝试使用 VS2005 NET 2 0 在 C 中实现对 propertygrid 的拖 放支持 propertygrid 可以处理 Dragenter 等事件 但似乎没有办法在拖动事件期间获取指针下的 griditem 到目前为止
  • Style.Triggers 与 ControlTemplate.Triggers

    我应该什么时候选择Style Triggers我应该什么时候选择ControlTemplate Triggers 使用其中一种比另一种有什么好处吗 假设我有这些样式可以达到相同的结果
  • 读取 pandas 中除最后一行之外的所有 CSV 文件

    我有 CSV 文件 我在 pandas 中读取这些文件 usr bin env python import pandas as pd import sys filename sys argv 1 df pd read csv filenam
  • Django Formset 中的自定义标签

    如何将自定义标签添加到我的表单集中
  • google-services.json - 更改了 package_name - 我需要创建一个新的配置文件

    我当前的环境已经有一个 google services json 文件并且一切正常 但现在由于不可预见的情况 我必须重命名我的项目的包 我现在已经成功地重命名了包 我还进入了 google services json 文件并重命名了那里的包
  • SwiftUI LazyVGrid - 顶部对齐

    我有很多卡片需要在 vGrid 中显示 但是 卡片具有动态高度 我想要做的是将列中的卡片与顶部对齐 这是当前的设置 let resultGridLayout GridItem adaptive minimum 160 spacing 10
  • 如何使用 Rx.Observable.prototype.let 运算符?

    的例子和解释let操作员 https github com Reactive Extensions RxJS blob master doc api core operators let md https github com Reacti
  • 如何在android中制作可滚动的按钮

    Hello i m trying to make an equalizer for my app but i can t figure out how to make the buttons I don t really know how
  • 多次修改后的SVN性能

    我的项目目前正在使用 svn 存储库 每天都会获得数百个新修订 该存储库驻留在 Win2k3 服务器上 并通过 Apache mod dav svn 提供服务 我现在担心随着时间的推移 性能会由于太多的修改而下降 这种恐惧合理吗 我们已经计
  • 多处理中的Python日志记录:AttributeError:'Logger'对象没有属性'flush'

    基于此code https stackoverflow com a 5916874我创建了一个 python 对象 它既将输出打印到终端 又将输出保存到日志文件 并在其名称后附加日期和时间 import sys import time cl
  • TeamCity MSTest 和 TestList?

    为了自动化单元测试TeamCity我必须在我的中创建一个测试列表vsmdi配置文件表明每个测试都是我调用的列表的一部分CompleteCoverage 我非常不喜欢这个 因为为了自动运行新测试 我必须记住将它们包含在此列表中 有没有办法使用
  • SpecialFolder.ApplicationData 返回默认用户

    我正在尝试获取当前登录用户的应用程序数据文件夹的路径 我在用着 Environment GetFolderPath Environment SpecialFolder ApplicationData 但返回的路径是 C Documents
  • 面向互联网的 SSRS 报告

    我正在使用 PHP 5 2 9 和 MS Sql Server 2005 设计一个网站 我有一个 SSRS 报告 我想对其进行设置 以便互联网上的人们可以访问它 在输入用户名和密码后 但我可以弄清楚那部分 我们的网站托管在本地网络服务器上
  • 从嵌套表单中调用 $builder->getData() 始终返回 NULL

    我试图获取以嵌套形式存储的数据 但是在调用时 builder gt getData 我总是得到NULL 有谁知道如何获取嵌套表单中的数据 这是 ParentFormType php class ParentFormType extends
  • JUnit 5:如何断言抛出异常?

    在 JUnit 5 中是否有更好的方法来断言方法抛出异常 目前 我必须使用 Rule 来验证我的测试是否引发异常 但这不适用于我期望多个方法在测试中引发异常的情况 您可以使用assertThrows https github com jun
  • Jquery Datatables,初始化后更改行回调

    我需要掌握现有数据表的 fnRowCallback 设置 但我尝试的一切似乎都失败了 我尝试过什么 1 var dt table dataTable bRetrieve true fnRowCallback function nRow aD
  • 使用数组下标运算符访问结构成员

    假设有一个类型 T 和一个仅包含 T 类型的统一元素的结构 struct Foo T one T two T three 我想通过以下方式访问它们 struct Foo T one T two T three T operator int