C++17:使用通用可变参数 lambda 包装可调用对象

2024-01-09

我想将任何类型的可调用对象(例如 lambda)透明地包装在另一个可调用对象中以注入附加功能。包装器的类型应与原始可调用对象具有相同的特征:

  • 相同的参数类型
  • 相同的返回类型
  • 完美转发传递的参数
  • 在 SFINAE 构造中使用时具有相同的行为

我尝试使用通用可变参数 lambda 作为包装器:

#include <iostream>
#include <type_traits>

template<class TCallable>
auto wrap(TCallable&& callable) {
    return [callable = std::forward<TCallable>(callable)](auto&&... args) -> std::invoke_result_t<TCallable,decltype(args)...> {
        std::cout << "This is some additional functionality" << std::endl;
        return callable(std::forward<decltype(args)>(args)...);
    };
}

int main(int argc, char *argv[])
{
    auto callable1 = []() {
        std::cout << "test1" << std::endl;
    };

    auto callable2 = [](int arg) {
        std::cout << "test2: " << arg << std::endl;
    };

    auto wrapped1 = wrap(callable1);
    auto wrapped2 = wrap(callable2);

    static_assert(std::is_invocable_v<decltype(callable1)>); // OK
    static_assert(std::is_invocable_v<decltype(wrapped1)>); // fails
    static_assert(std::is_invocable_v<decltype(callable2), int>); // OK
    static_assert(std::is_invocable_v<decltype(wrapped2), int>); // fails
}

正如评论中的static_asserts 表明,包装器可调用对象的调用方式与原始可调用对象不同。为了实现所需的功能需要改变什么?

给定的示例是使用 Visual Studio 2017 (msvc 15.9.0) 编译的。


这可能是 MSVC 实现中的一个错误std::invoke_result or std::is_invocable(即使使用 Visual Studio 15.9.2,我也可以在此处重现该问题)。你的代码与 clang (libc++) 和 gcc 配合良好 https://godbolt.org/z/-rWdOy我看不出有什么理由不应该这样做。然而,你并不真正需要std::invoke_result无论如何,你可以让你的 lambda 推断出返回类型:

template<class TCallable>
auto wrap(TCallable&& callable) {
    return [callable = std::forward<TCallable>(callable)](auto&&... args) -> decltype(auto) {
        std::cout << "This is some additional functionality" << std::endl;
        return callable(std::forward<decltype(args)>(args)...);
    };
}

那么似乎也可以与 MSVC 配合使用 https://godbolt.org/z/ounjrj

编辑:正如 Piotr Skotnicki 在下面的评论中指出的那样,decltype(auto)将禁止SFINAE https://stackoverflow.com/questions/17608637/sfinae-and-decltypeauto。要解决此问题,您可以使用尾随返回类型:

template<class TCallable>
auto wrap(TCallable&& callable) {
    return [callable = std::forward<TCallable>(callable)](auto&&... args) -> decltype(callable(std::forward<decltype(args)>(args)...)) {
        std::cout << "This is some additional functionality" << std::endl;
        return callable(std::forward<decltype(args)>(args)...);
    };
}

这会需要更多的打字,但应该可以与 SFINAE 配合使用似乎也可以与 MSVC 配合使用 https://godbolt.org/z/e92TkX

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

C++17:使用通用可变参数 lambda 包装可调用对象 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • 强制gcc在64位平台上编译32位程序

    我有一个专有程序 正在尝试在 64 位系统上使用 当我启动安装程序时 它工作正常 但是在它尝试更新自身并编译一些模块后 它无法加载它们 我怀疑这是因为它使用 gcc 并且 gcc 尝试为 64 位系统编译它们 因此该程序无法使用这些模块 有
  • 即时将文件上传到 Azure Blob

    我正在尝试创建一个文件并将其放入 blob 中CloudBlockBlob UploadFromStreamAsync method 这是代码 private async void CreateCsvFile int recId using
  • Android OnLayout何时调用?

    我开发一个自定义View它延伸自ViewGroup 这意味着我需要实施onLayout方法 我认为当视图显示在屏幕上时会调用此方法 但我认为这是不对的 你能解释一下什么时候onLayout方法调用以及我需要在该方法中实现什么 它让我崩溃 因
  • 如何在选择选项的 HTML 标签中应用字体系列

    我正在应用字体系列
  • 从 ArrayNode 创建 Java 8 流

    是否可以创建流com fasterxml jackson databind node ArrayNode 我试过 ArrayNode files ArrayNode json get files Stream
  • 如何在 PDF 完全下载之前使其显示在网络浏览器中

    我有一个客户一直在努力解决网络上 pdf 文件加载缓慢的问题 我的客户有一些非常大的 pdf 文件 几乎有 10 Mb 下载它们需要 3 4 分钟以上 在加载整个文件之前 这些文件不会显示 我们和他们已经看到其他网站的 pdf 一次加载一页
  • topLevelAwait 对 babel-loader 无效:'await' 只允许在异步函数中使用

    webpack5支持topLevelAwait 只需添加以下选项 webpack config js module exports experiments topLevelAwait true 现在我们可以愉快地使用顶级等待 如下所示 im
  • 尽管启用了 kapt. CorrectErrorTypes,kapt 仍将生成的类引用替换为 error.NonExistentClass

    我有一个自定义注释处理器 大致执行以下操作 生成注释类型 使用此类型的类被推迟到后面的轮次 在后面的一轮中 使用这种类型处理类并为它们生成更多文件 到目前为止 这在 Java 中运行良好 但最近 我将一些类从 Java 转换为 Kotlin
  • Xcode 无法导入 tapku 或 kal 库

    我在导入 tapku 库 使用它提供的日历 api 时遇到问题 我也尝试过 Kal 遇到同样的问题 这是我导入它的方法 如果我遗漏了什么 请告诉我 使用 Xcode 4 5 转到文件 gt 将文件添加到项目 gt TapkuLibrary
  • .NET 7 Blazor MAUI - 需要使用 Azure 用户登录进行身份验证

    我正在开发 Blazor MAUI 应用程序 并且我试图要求组织中的用户使用其 Microsoft 工作帐户登录才能访问该应用程序 我在 Blazor MAUI 中找不到太多有关身份验证的文档 并且一直在努力寻找可行的解决方案 目前 我一直
  • Android:View.getTag/setTag 和 IllegalArgumentException

    是的 我知道在调用这些需要密钥的函数版本时 您需要一个唯一的资源 ID 但我一生都无法弄清楚如何创建可以这种方式使用的资源 ID 我的类中的最终变量不起作用 硬编码值也不起作用 两者都抛出了 IllegalArgumentException
  • 如何获取维基百科页面的所有链接及其维基数据 ID?

    什么时候 以下的事情可能实现 在单个查询 API 调用中获取维基百科页面上的所有链接及其各自的维基数据 ID 的列表 通过查询接收各个维基数据项的附加信息 例如属性值 要获取您必须使用的所有维基百科页面链接维基百科API https en
  • 如何从 PDF 中提取数据?

    我的公司通过 Excel 从外部公司接收数据 我们将其导出到 SQL Server 以运行数据报告 他们现在正在更改为PDF格式 有没有办法可靠地从PDF中移植数据并将其插入到我们的SQL Server 2008数据库中 这是否需要编写一个
  • 如何使用GCC将C代码编译为8088汇编?

    我一直在寻找一条信息 但似乎找不到它 也许你们可以帮助我 这是一个简单的问题 如何使用GCC将C代码编译成8088汇编 我正在用 8088 汇编语言编写一个小程序 想知道编译器是如何完成某些事情的 这真的很棒 Thanks djgpp 有一
  • 如何在 Python 中创建 Socket.io 客户端以与 Sails 服务器通信

    我正在运行一个SailsJS我有一个控制器的实例 v0 12 3 我的模型控制器处理 WebSocket socket io 如果用户已通过身份验证 则允许连接 我的模型控制器 module exports Socket connectio
  • 如何使 VS2010 优先选择一个包含目录而不是另一个?

    我正在尝试使用XInput h来自 DirectX SDK 的文件 但此文件也存在于 Windows SDK 中 并且它是该文件的不同变体 我尝试过添加 DXSDK DIR Include 到在项目设置中包含目录 之前和之后 Include
  • 保持分支与 master 保持同步

    我有一个远程存储库 我已从该存储库中提取并从中分支 我想让新分支与 master 所做的更改保持同步 我正在考虑下面的工作流程 它是否有意义或者是否有更好的方法来做到这一点 初始分支和结账 git checkout master git p
  • 未定义的偏移量:1

    在我当前的 PHP 脚本中出现此错误 未定义的偏移量 1 我的代码在这里 query SELECT item id username item content FROM updates ORDER BY update time DESC L
  • 有没有办法在Android中使用Paging Library 3.0实现基于光标的分页?

    我正在使用一个 REST API 它使用基于游标的分页来显示一些结果 我想知道我是否可以使用分页库3 0 https developer android com topic libraries architecture paging v3
  • C++17:使用通用可变参数 lambda 包装可调用对象

    我想将任何类型的可调用对象 例如 lambda 透明地包装在另一个可调用对象中以注入附加功能 包装器的类型应与原始可调用对象具有相同的特征 相同的参数类型 相同的返回类型 完美转发传递的参数 在 SFINAE 构造中使用时具有相同的行为 我