包装一个采用 std::function 的函数,以便传递采用更多参数的函数

2024-05-26

Problem

我有一个函数double subs(std::function<double(double)> func),我想将它包装在一个如下所示的新函数中

template<typename... Args> double subsWrap(std::function<double(Args... args)> func)

适用subs某些需要更多输入的函数

subs( subs( subs( ... func(...) ) ) )

与每个subs仅适用于其中一个参数func一次。

最小的例子

假设我们有一个函数

auto subs = [] (std::function<double(double)> func){return func(2) + func(5.3);};

我们想把它应用到

auto f2=[](double x, double y){return std::sin(x*std::exp(x/y)); };

as

subs( [&f2](double y){ return  subs( [&y,&f2](double x){ return f2(x,y); } ); } ) 

For f2,这很简单,因此不需要包装器。但是,如果我们想对具有更多参数的函数执行相同的操作(例如double(double,double,double,double,double))事情开始变得复杂。

必须有一种方法可以自动执行此操作,但我什至不知道如何开始。


与可变参数 lambda 一起使用怎么样?std::is_invocable输入特征来终止递归?

template<class Fn>
double subs_wrap(Fn func) {
    if constexpr (std::is_invocable_v<Fn, double>)
        return subs(func);
    else
        return subs([=](double x) {
            return subs_wrap(
                [=](auto... xs) -> decltype(func(x, xs...))
                { return func(x, xs...); }
            );
        });
}

这里需要 lambda 的显式返回类型规范来传播“可调用性”属性。[=](auto... xs) { return func(x, xs...); }可以用任意数量的参数正式调用,无论是否func(x, xs...)是否可调用。当使用显式指定返回类型时decltype,SFINAE 介入。

通过这个实现,两个表达式

subs([=](double y) { 
    return subs([=](double x) {
        return f2(x, y);
    });
});

and

subs_wrap(f2);

会产生相同的结果。

有趣的是,与-O3GCC 和 Clang 都可以优化优化所有这些代码 https://godbolt.org/z/z5TqrsnvM并替换subs_wrap(f2)带有编译时常量。使用类似的代码编写std::function他们不这样做的论点。


如果我们想将参数传递给 subs,我们如何进行解包(每个递归都不同)

这是通过稍微修改代码来实现此目的的方法:

template<class Fn, class P, class... Ps>
double subs_wrap(Fn func, P p, Ps... ps) {
    if constexpr (std::is_invocable_v<Fn, double>) {
        static_assert(sizeof...(Ps) == 0);
        return subs(func, p);
    }
    else {
        static_assert(sizeof...(Ps) > 0);
        return subs([=](double x) {
            return subs_wrap(
                [=](auto... xs) -> decltype(func(x, xs...))
                { return func(x, xs...); },
                ps...);
        }, p);
    }
}

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

包装一个采用 std::function 的函数,以便传递采用更多参数的函数 的相关文章

  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐