具有数据成员语法的零成本属性

2024-03-24

我(重新?)发明了这种使用数据成员语法实现零成本属性的方法。我的意思是用户可以写:

some_struct.some_member = var;
var = some_struct.some_member;

并且这些成员访问以零开销重定向到成员函数。

虽然初步测试表明该方法在实践中确实有效,但我还不确定它是否不存在未定义的行为。下面是说明该方法的简化代码:

template <class Owner, class Type, Type& (Owner::*accessor)()>
struct property {
    operator Type&() {
        Owner* optr = reinterpret_cast<Owner*>(this);
        return (optr->*accessor)();
    }
    Type& operator= (const Type& t) {
        Owner* optr = reinterpret_cast<Owner*>(this);
        return (optr->*accessor)() = t;
    }
};

union Point
{
    int& get_x() { return xy[0]; }
    int& get_y() { return xy[1]; }
    std::array<int, 2> xy;
    property<Point, int, &Point::get_x> x;
    property<Point, int, &Point::get_y> y;
};

测试驱动程序证明该方法有效,并且确实是零成本(属性不占用额外的内存):

int main()
{
    Point m;
    m.x = 42;
    m.y = -1;

    std::cout << m.xy[0] << " " << m.xy[1] << "\n";
    std::cout << sizeof(m) << " " << sizeof(m.x) << "\n";
}

真正的代码有点复杂,但方法的要点就在这里。它基于使用真实数据的并集(xy在此示例中)和空属性对象。 (真实数据必须是标准布局类才能正常工作)。

需要联合,因为否则属性尽管是空的,但会不必要地占用内存。

为什么我觉得这里没有UB?该标准允许访问标准布局联合成员的公共初始序列。这里,公共初始序列为空。数据成员x and y根本不被访问,因为没有数据成员。我对标准的阅读表明这是允许的。reinterpret_cast应该没问题,因为我们正在将一个联合成员强制转换为其包含的联合,并且这些是指针可相互转换的。

标准确实允许这样做,还是我在这里遗漏了一些 UB?


TL;DR 这是 UB。

[基本生活] https://timsong-cpp.github.io/cppwp/basic.life#7

类似地,在对象的生命周期开始之前但在分配该对象将占用的存储空间之后,或者在对象的生命周期结束之后并且在重用或释放该对象占用的存储空间之前,引用的任何泛左值原始对象可以被使用,但只能以有限的方式使用。对于正在构造或销毁的对象,请参阅[class.cdtor]。否则,这样的泛左值指的是分配的存储,并且使用不依赖于其值的泛左值的属性是明确定义的。如果出现以下情况,则程序具有未定义的行为:[...]

  • 泛左值用于调用对象的非静态成员函数,或者

By 定义 https://timsong-cpp.github.io/cppwp/class.union#1,联合体的非活动成员不在其生命周期内。


一个可能的解决方法是使用 C++20[[no_unique_address]] https://en.cppreference.com/w/cpp/language/attributes/no_unique_address

struct Point
{
    int& get_x() { return xy[0]; }
    int& get_y() { return xy[1]; }
    [[no_unique_address]] property<Point, int, &Point::get_x> x;
    [[no_unique_address]] property<Point, int, &Point::get_y> y;
    std::array<int, 2> xy;
};

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

具有数据成员语法的零成本属性 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 如何使用 zlib 制作 .zip 文件

    我正在阅读zlib的文档 它相当详细 但我读到了这一行 输出数据将位于zlib格式 与 gzip 或zip formats http www zlib net zlib how html http www zlib net zlib how
  • 在 C++ 中将成对向量转换为两个独立向量的最快方法

    假设我有一个vector of pair
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • SFINAE 如何使用省略号?

    过去 当使用 SFINAE 选择构造函数重载时 我通常使用以下内容 template
  • 获取尚未实例化的类的函数句柄

    我对 C 相当陌生 我想做的事情可能看起来很复杂 首先 我想获取一些函数的句柄以便稍后执行它们 我知道我可以通过以下方式实现这一目标 List
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • 将带有 glut 的点击坐标添加到向量链接列表中

    我想创建一个向量链接列表 并在 GLUT 库的帮助下获取点击的位置并将它们附加到链接列表中 这些是我写的结构 typedef struct vector int x int y Vector typedef struct VectorLis
  • 如何在 C++ 中将 CString 转换为 double?

    我如何转换CString to a double在 C 中 Unicode 支持也很好 Thanks A CString可以转换为LPCTSTR 这基本上是一个const char const wchar t 在 Unicode 版本中 知
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • C# 委托责任链

    为了我的理解目的 我实现了责任链模式 Abstract Base Type public abstract class CustomerServiceDesk protected CustomerServiceDesk nextHandle
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • 二叉树中的 BFS

    我正在尝试编写二叉树中广度优先搜索的代码 我已将所有数据存储在队列中 但我不知道如何访问所有节点并消耗它们的所有子节点 这是我的 C 代码 void breadthFirstSearch btree bt queue q if bt NUL
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • 在 Xamarin 中获取 OutOfMemoryException

    java lang OutOfMemoryError 考虑增加 JavaMaximumHeapSize Java 执行时内存不足 java exe 我的 Visualstudio Xamarin 项目出现内存不足异常 请帮助我如何解决此问题

随机推荐

  • 使用 AJAX 并操作 window.location 时不使用弹出窗口拦截器的 window.open

    在处理来自服务器 例如 Twitter 和 Facebook 的 OAuth 时 您很可能会将用户重定向到请求应用程序权限的 URL 通常 单击链接后 您通过 AJAX 向服务器发送请求 然后返回授权 URL 但是当你尝试使用window
  • Azure Web应用服务时区更改问题

    我们正在使用 Azure Web 应用程序服务进行多租户应用程序 但应用程序服务的默认时区是 UTC 我只想更改该地区的时区 我已经在应用程序设置中尝试了 WEB TIMEZONE 变量 但不起作用 You are setting wron
  • 生成 MD5 密钥并保存在文本文件中

    我正在使用 MD5 命令行实用程序 可以从此处获取http www fourmilab ch md5 http www fourmilab ch md5 我想要做的就是生成一个文件夹中所有文件的 MD5 密钥并将它们保存在一个文件中 但是
  • AADSTS70007:请求令牌时,“query”不是“response_mode”受支持的值

    因此 几天前我在 Azure AD 中创建了一个应用程序 请求授权码时 当我请求两者时 我收到以下错误code and id token in response type范围 AADSTS70007 当以下情况时 query 不是 resp
  • 无法访问 Web 控件的 Page_Load 事件中的公共方法

    我想打电话给我的Public String Function 方法来自我的 ascx s Page Load事件 该函数和包含的类位于与 Web 控件相同的代码后面 但我无法访问该功能 我该如何解决这个问题 Example public c
  • 包含闭包的 swift 函数的空返回值

    我创建了一个函数 该函数应该返回一个字典 其中填充了在线检索的数据 使用 json 基于 Ray Wenderlich tut 该代码位于闭包中 问题是首先返回一个空字典 然后才填充它 不知道这是否与获取远程数据的延迟有关 但显然我需要在返
  • Clang-Tidy 找不到我的头文件

    这里是 clang 和 clang tidy 的新手 我有一个具有这种结构的项目 project build cmake component1 src someFile cpp someFile2 cpp someFile hpp some
  • grunt-terser 给出语法错误:“VARIABLE_NAME”被重新声明

    我在用着咕噜语 https www npmjs com package grunt terser缩小我的 es6 文件 我有两个文件 文件1 js 文件2 js 在这两个文件中 我需要一个具有相同变量名称的模块 如下所示 const VAR
  • 如何使用group-concat mysql创建json格式?

    如何使用group concat mysql创建json格式 我使用MySQL 示例1 table1 email name phone email protected cdn cgi l email protection Ben 65553
  • OS X 崩溃日志符号

    我无法使用 XCode 4 6 来符号化来自测试人员和用户的 OS X 不是 iOS 崩溃日志 崩溃日志无法拖到管理器中 并且管理器不会显示 Library Logs DiagnosticReports 中的任何崩溃日志 尽管某些日志位于该
  • Linux/Windows 中的 C/C++ 内存使用 API

    我想获取每个进程和系统范围的内存使用信息 在 Windows 中 这非常简单 GetProcessMemoryInfo 和 GlobalMemoryStatusEx 可以非常轻松地完成这些工作 例如 GetProcessMemoryInfo
  • 有没有人找到一种方法来合并 Xcode 项目或 Core Data 模型文件中的更改?

    有没有办法使用 VCS 我正在使用 git 并让它与 Xcode 文件合并 例如 如果我的同事向项目添加了一个新组 当我合并他的更改时 我会合并该组吗 或者 如果他向核心数据实体添加一个属性 我会在我的核心数据模型中获得该属性吗 核心数据和
  • 无法在 Android Studio 中解析符号 HttpGet、HttpClient、HttpResponce

    我只是复制所有的jar文件Http but Android Studio无法导入所有这些 jar 文件 它给出一个错误 Cannot resolve symbol HttpGet HttpClient HttpResponse My Act
  • 浮点精度显示(Android)

    我正在尝试制作一个程序 它接受一些用户输入 运行一些计算并输出答案 我的问题是 这个答案有时会长很多小数位 这会导致一些美观和布局问题 我只需要显示小数点后 4 位的数据 是否有办法在输出时限制这些数字的精度 数字存储在浮点数中 我正在为
  • 如何创建可滚动的结果集?

    我得到了这个简单的代码来从 MSSQL Server 2008 检索记录集 由于我设置了 ResultSet TYPE SCROLL INSENSITVE 该记录集必须是可滚动的 与 Javadocs 中的示例相同 String qry S
  • 带有私有标识符参数的符号

    我想创建一个与私有 MethodMirror 的简单名称相同的符号 但是 Symbol 的文档指出 new Symbol 的参数必须是有效的公共标识符 如果我尝试创建一个const Symbol privateIdentifier dart
  • Python 浮点除法不精确[重复]

    这个问题在这里已经有答案了 可能的重复 Python float str 浮动怪异 https stackoverflow com questions 1778368 python float str float weirdness Pyt
  • Redis CLI 未通过 Laravel 显示最近存储的密钥

    我正在尝试使用缓存我的结果redis in Laravel通过做这个 result Cache remember orders cache 10 function use orders return orders return result
  • 我有一个 contentEditable="true" 的 div,需要对输入的数字进行着色

    这是我的代码 非常适合为可编辑 div 中的数字着色 但光标将转到 div 的开头 当我按键盘箭头按钮遍历字符串时 以及当我单击 home 和 end 按钮 光标应该按预期移动 jQuery document ready function
  • 具有数据成员语法的零成本属性

    我 重新 发明了这种使用数据成员语法实现零成本属性的方法 我的意思是用户可以写 some struct some member var var some struct some member 并且这些成员访问以零开销重定向到成员函数 虽然初