什么是自定义点对象以及如何使用它们?

2024-02-14

C++ 标准的最后一个草案引入了所谓的“自定义点对象”([自定义.点.对象] http://eel.is/c++draft/customization.point.object), 被范围库广泛使用。

我似乎明白他们提供了一种编写自定义版本的方法begin, swap, data,等等,它们是 由 ADL 标准库找到。那是对的吗?

这与以前的做法有何不同,以前的做法是用户定义重载,例如begin适合她自己的类型 命名空间?特别是,为什么他们objects?


什么是自定义点对象?

它们是命名空间中的函数对象实例std实现两个目标:first无条件触发对参数的(概念化)类型要求,then分派到命名空间中正确的函数std或通过 ADL。

特别是,为什么他们objects?

这对于绕过第二个查找阶段是必要的,该阶段将通过 ADL 直接引入用户提供的函数(这应该是推迟通过设计)。请参阅下面的更多细节。

...以及如何使用它们?

开发应用程序时:您主要不需要。这是一个标准库功能,它将为未来的定制点添加概念检查,希望能够产生例如当您搞乱模板实例时,会出现清晰的错误消息。但是,通过对此类自定义点的合格调用,您可以直接使用它。这是一个假想的例子std::customization_point符合设计的物体:

namespace a {
    struct A {};
    // Knows what to do with the argument, but doesn't check type requirements:
    void customization_point(const A&);
}

// Does concept checking, then calls a::customization_point via ADL:
std::customization_point(a::A{});

目前这是不可能的,例如std::swap, std::begin等等。

说明(总结N4381 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html)

让我尝试消化标准中本节背后的提案。标准库使用的“经典”定制点存在两个问题。

  • 他们很容易出错。例如,在通用代码中交换对象应该如下所示

    template<class T> void f(T& t1, T& t2)
    {
        using std::swap;
        swap(t1, t2);
    }
    

    但打了一个合格的电话std::swap(t1, t2)相反太简单了 - 用户提供的swap永远不会被调用(参见N4381 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html、动机和范围)

  • 更严重的是,没有办法集中(概念化)对传递给此类用户提供的函数的类型的约束(这也是该主题在 C++20 中变得重要的原因)。再次 从N4381 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html:

    假设未来版本std::begin要求其参数模型是 Range 概念。 添加这样的约束不会对使用的代码产生影响std::begin惯用语:

    using std::begin;
    begin(a);

    如果对 begin 的调用分派到用户定义的重载,则对的约束std::begin已被绕过。

提案中描述的解决方案缓解了这两个问题 通过如下的方法,想象的实现std::begin.

namespace std {
    namespace __detail {
        /* Classical definitions of function templates "begin" for
           raw arrays and ranges... */

        struct __begin_fn {
            /* Call operator template that performs concept checking and
             * invokes begin(arg). This is the heart of the technique.
             * Everyting from above is already in the __detail scope, but
             * ADL is triggered, too. */

        };
    }

    /* Thanks to @cpplearner for pointing out that the global
       function object will be an inline variable: */
    inline constexpr __detail::__begin_fn begin{}; 
}

首先,对例如进行合格的调用std::begin(someObject)总是绕道而行std::__detail::__begin_fn, 这是所期望的。对于不合格调用会发生什么,我再次参考原始论文:

在带入之后 begin 被称为不合格的情况下std::begin范围、情况 是不同的。在查找的第一阶段,名称 begin 将解析为全局对象std::begin。由于查找找到的是对象而不是函数,因此查找的第二阶段不是 执行。换句话说,如果std::begin是一个对象,那么using std::begin; begin(a);是 相当于std::begin(a);正如我们已经看到的,它对 代表用户。

这样,可以在函数对象内执行概念检查std命名空间,before执行对用户提供的函数的 ADL 调用。没有办法规避这一点。

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

什么是自定义点对象以及如何使用它们? 的相关文章

  • Unity3D StartCoroutine 调用一个函数,该函数什么时候返回?

    我知道Unity3D StartCoroutine调用了一个与StartCoroutine在同一线程上运行的函数 但是被调用的函数什么时候返回到原始调用者 我在互联网上查找了一个很好的 Unity3D Coroutine 示例 但找不到完整
  • Windows 上使用 g++ 的 Makefile,链接库

    我已经厌倦了 MSVC 6 以及每个人总是告诉我它是一个蹩脚的编译器等等 所以现在我决定尝试使用 vim 加 g 和 makefile 这是我的问题 我有以下 makefile This is supposed to be a commen
  • MVC 重定向到没有控制器的视图

    希望应该是一个简单的 我创建了一个通用错误视图 当整个站点的操作方法内发生异常时 我想显示该视图 我创建了一个部分页面 所有导航都位于其中 因此我不需要在此视图上使用控制器 那么如何从控制器内的操作方法重定向到它 像这样的东西 HttpPo
  • SetWindowsHookEx 函数返回 NULL

    我正在研究 DLL 注入 但收到错误如下 挂接进程失败 87 参数不正确 目标进程和dll都是64位的 注入代码为 BOOL HookInjection TCHAR target TCHAR dll name https msdn micr
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • WebClient读取错误页面的内容

    我有一个加载页面内容的应用程序 我使用 WebClient 类 即使服务器返回 404 500 等错误 我也需要检索内容 我需要这样的东西 WebClient wc new WebClient string pageContent try
  • 关闭 XDOCUMENT 的实例

    我收到这个错误 该进程无法访问文件 C test Person xml 因为它是 被另一个进程使用 IOException 未处理 保存文件内容后如何关闭 xml 文件的实例 using System using System Collec
  • F10键没被抓住

    I have a Windows Form and there overriden ProcessCmdKey However this works with all of the F Keys except for F10 I am tr
  • 在通过网络发送之前压缩位图

    我正在尝试通过网络发送位图屏幕截图 因此我需要在发送之前对其进行压缩 有一个库或方法可以做到这一点吗 当您将图像保存到流时 您have选择一种格式 几乎所有位图格式 bmp gif jpg png 都使用一种或多种压缩形式 因此 只需选择适
  • 将成员函数作为参数传递/c++

    我想用 C 实现一个类b可以通过封装该迭代器类型的成员集进行某种迭代 喜欢 b object for each x do function f so 函数 f会得到每个人的x成员并做任何事情 比方说 void function f x me
  • 特定设备的不同字体大小

    我目前正在开发通用应用程序 我需要分别处理移动设备和桌面的文本框字体大小 我找到了一些方法 但都不能解决问题 使用 VisualStateManager 和 StateTrigger 为例
  • 用 C# 制作 Vista 风格的应用程序

    我正在运行 Windows Vista 并且希望外观看起来像常规 Vista 程序 有没有关于如何构建 Vista 风格应用程序的真正好的教程 文章 我还想学习如何使用本机代码并将其转换为 C 如this http bartdesmet n
  • 如何在 C# 中使用 XmlDsigC14NTransform 类

    我正在尝试使用规范化 xml 节点System Security Cryptography Xml XMLDsigC14nTransformC net Framework 2 0 的类 该实例需要三种不同的输入类型 NodeList Str
  • Dynamics Crm:获取状态代码/状态代码映射的元数据

    在 Dynamics CRM 2011 中 在事件实体上 状态原因 选项集 也称为状态代码 与 状态 选项集 也称为状态代码 相关 例如看这个截图 当我使用 API 检索状态原因选项集时 如下所示 RetrieveAttributeRequ
  • 微软语音识别速度

    我正在使用微软的语音识别器开发一个小型练习应用程序 对于我正在做的事情来说 我似乎无法让它足够快地识别单个单词 我希望能够正常说话 系统将从我所说的内容中抓取 关键字 并生成一个字符串 目前我正在使用 5 个单词的自定义语法 红 蓝 黄 绿
  • 如何将 CSV 文件读入 .NET 数据表

    如何将 CSV 文件加载到System Data DataTable 根据CSV文件创建数据表 常规 ADO net 功能是否允许这样做 我一直在使用OleDb提供者 但是 如果您正在读取具有数值的行 但希望将它们视为文本 则会出现问题 但
  • 是否有任何不使用公共虚拟方法的正当理由? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 是否有任何不使用公共虚拟方法的正当理由 我在某处读到我们应该避免使用公共虚拟方法 但我想向专家确认这是否是有效的声明 对于良好且稳定的 API
  • 如何使用 ASP.NET Web 表单从代码隐藏中访问更新面板内的文本框、标签

    我在更新面板中定义了一些控件 它们绑定到中继器控件 我需要根据匿名字段隐藏和显示用户名和国家 地区 但问题是我无法以编程方式访问更新面板中定义的控件 我如何访问这些控件 我也在网上查找但找不到很多参考资料 下面是来自aspx页面和 cs页面
  • 通过 cmake 链接作为外部项目包含的 opencv 库[重复]

    这个问题在这里已经有答案了 我对 cmake 比较陌生 经过几天的努力无法弄清楚以下事情 我有一个依赖于 opencv 的项目 它本身就是一个 cmake 项目 我想静态链接 opencv 库 我正在做的是我的项目中有一份 opencv 源
  • 创建带有部分的选项卡式侧边栏 WPF

    我正在尝试创建一个带有部分的选项卡式侧边栏 如 WPF 中的以下内容 我考虑过几种方法 但是有没有更简单 更优雅的方法呢 方法一 列表框 Using a ListBox并将 SelectedItem 绑定到右侧内容控件所绑定的值 为了区分标

随机推荐