C++11 中是否可以将函数组合成一个新函数?

2024-01-08

这更多的是一种理论问题。 C++11 中是否可以将函数组合成一个新函数?例如 :

auto f = [](int i){return i * 2;};
auto g = [](int i){return i + 10;};

所以这有效:

auto c = f(g(20)); // = 60

但我想要一个存储组合的对象,比如

auto c = f(g);
std::cout << c(20) << std::endl; //prints 60

Edit:另外我想创建的是一个函数 a,你可以给它一个函数 b 和一个int n,并返回给定函数 b 的第 n 个组合。例如(不可编译)

template<typename T>
auto combine(T b, int i) -> decltype(T)
{
   if (i == 0)
      return b;

   return combine(b, i - 1);      
}

auto c = combine(f, 2); //c = f(f(f(int)))

第一次尝试:

template<class First, class Second>
auto compose( Second&& second, First&& first ) }
  return [second = std::forward<Second>(second), first=std::forward<First>(first)]
  (auto&&...args)->decltype(auto) {
    return second( first( decltype(args)(args)... ) );
  };
}
template<class A, class B, class...Rest>
auto compose(A&& a, B&& b, Rest&&... rest) {
  return compose( compose(std::forward<A>(a), std::forward<B>(b)), std::forward<Rest>(rest)... );
}
template<class A>
std::decay_t<A> compose(A&& a) {
  return std::forward<A>(a);
}

在 C++14 中。现在,这并不完美,因为该模式在 C++ 中运行得不太好。

为了完美地做到这一点,我们必须了解组合编程。在这里,函数与抽象的参数堆栈交互。每个函数都会从堆栈中弹出一些参数,然后再将一些参数弹出。

这将允许您执行以下操作:

compose( print_coord, get_x, get_y )

where get_x and get_y除了返回坐标之外什么也不消耗,并且print_coord获取两个坐标并打印它们。

为了在 C++ 中模拟这一点,我们需要一些奇特的机制。函数将返回tuples(或类似元组?),这些值将逻辑上“推入参数堆栈”。

函数也会消耗这个参数堆栈中的东西。

在每次调用时,我们解压当前的参数元组,找到可以调用该函数的最长集合,调用它,获取其返回值,如果它是元组,则将其解压,然后将任何此类返回值粘回参数堆栈。

对于这个更高级的compose要与自身组合,它需要 SFINAE 检查,并且它需要能够获取一个可调用对象和一个参数元组,并找到正确数量的参数来调用可调用对象,加上剩余的参数。

这是一个棘手的元编程,我在这里不会做。


第二部分,因为我第一次错过了,看起来像:

template<class F>
auto function_to_the_power( F&& f, unsigned count ) {
  return [f=std::forward<F>(f),count](auto&& x)
    -> std::decay_t< decltype( f(decltype(x)(x)) ) >
  {
    if (count == 0) return decltype(x)(x);
    auto r = f(decltype(x)(x));
    for (unsigned i = 1; i < count; ++i) {
      r = f( std::move(r) );
    }
    return r;
  };
}

这不使用类型擦除。

测试代码:

auto f = [](int x){ return x*3; };
auto fs = std::make_tuple(
    function_to_the_power( f, 0 ),
    function_to_the_power( f, 1 ),
    function_to_the_power( f, 2 ),
    function_to_the_power( f, 3 )
);

std::cout << std::get<0>(fs)(2) << "\n";    
std::cout << std::get<1>(fs)(2) << "\n";    
std::cout << std::get<2>(fs)(2) << "\n";    
std::cout << std::get<3>(fs)(2) << "\n";    

prints:

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

C++11 中是否可以将函数组合成一个新函数? 的相关文章

  • double 类型的静态类成员的常量表达式初始值设定项

    在 C 11 和 C 14 中 为什么我需要constexpr在下面的代码片段中 class Foo static constexpr double X 0 75 而这会产生编译器错误 class Foo static const doub
  • 继承层次结构中接口与实现的分离(C++ 新手)

    我正在想办法如何安排一些课程 这就是我到目前为止所得到的 继承层次结构的顶层 自然 是 T T h namespace foo class T public virtual void method1 std string a paramet
  • 将 lambda 表达式传递给 lambda 参数 c++11

    我想做这样的事情 int main auto f some variables take lambda function something with lambda function f other variables variables
  • ASP.NET MVC 3 Razor DisplayFor 委托

    我收到此错误 模板只能与字段访问 属性访问 一维数组索引或单参数自定义索引器表达式一起使用 这是我的代码 自定义 HTML 帮助程序 包装 DisplayFor 以便我可以选择模板 public static string DisplayL
  • Travis CI 与 Clang 3.4 和 C++11

    Travis CI 是否可以与支持 C 11 的 Clang 一起使用 我想要 Clang 而不是 GCC 我已经在 Travis CI 中使用了 GCC 4 8 看来预安装的版本不支持 C 11 我安装任何新版本的所有尝试都结束了因为这个
  • 中继命令和无参数执行方法

    我目前正在学习 WPF 和 MVVM 我想我已经了解了大部分内容及其工作原理 但我在使用 RelayCommand 或 DelegateCommand 时遇到了一些我不明白的问题 我认为这与代表的工作方式有关 请注意 下面的代码目前仅处于测
  • 对于所有对象类型 T 来说,sizeof(T) >=alignof(T) 总是这样吗?

    对于任何对象类型T是不是总是这样sizeof T 至少与alignof T 直观上似乎是这样 因为即使您调整对象的对齐方式 例如 struct small char c 高于通常的情况 它们的 大小 也会向上调整 以便数组中的对象之间的关系
  • 理解 Scala FP 库

    只是为了让那些想要开始使用 Scala FP 库 在纯 FP 方面变得更好的人快速清晰地了解 有人能澄清猫和猫效应 猫效应 IO 之间的区别 关系吗 最重要的是 齐奥和莫尼克斯对此有何看法 最后 与 ScalaZ 7 8 有何关系 到目前为
  • 使用 lambda 对多列进行分组

    如何使用 lambda 对多列进行分组 我看到了如何使用 linq toEntity 执行此操作的示例 但我正在寻找 lambda 形式 var query source GroupBy x gt new x Column1 x Colum
  • “功能性”Rust 对性能有哪些影响?

    我正在关注 Rust 轨道运动 io https exercism io 我有相当多的 C C 经验 我喜欢 Rust 的 功能 元素 但我担心相对性能 我解决了 行程编码 问题 https exercism io tracks rust
  • Haskell 入门

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 几天来 我一直试图理解 Haskell 中的函数式编程范例 我通过阅读教程和观看截屏视频
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • Emacs Lisp 可以将 lambda 形式分配给像Scheme 这样的变量吗?

    在研究 Emacs Lisp 的符号单元时 我发现像这样的示例函数 defun a rest x x 我可以打电话 symbol function a 返回 lambda rest x x 如果我愿意的话我可以使用它 gt lambda r
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • 模板化的 typedef?

    我正在使用 libgc 一个用于 C 和 C 的垃圾收集器 为了使 STL 容器可被垃圾回收 必须使用 gc allocator 而不是写作 std vector
  • Android Studio:lambda 不起作用[重复]

    这个问题在这里已经有答案了 当尝试使用 lambda 表达式时 我遇到了一些 Gradle 构建错误 错误 41 100 错误 source 1 7 不支持 lambda 表达式 使用 source 8 或更高版本来启用 lambda 表达
  • 在不支持线程的程序加载的共享库中使用 C++11 多线程

    我目前正在尝试在共享库中使用 C 11 多线程 该库加载到 Linux 上的主程序 用 C 编写 中 这是一个大型模拟程序的一部分 我无法更改有关库加载的任何内容或更改一般的主程序 主程序是用 gcc 4 1 2 编译的 我没有它的源代码
  • virtual对类模板成员使用的影响

    我 模糊地 知道模板不会被实例化 如果它是not used 例如 以下代码即使在以下情况下也能正常编译 T type没有意义时T int template
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include

随机推荐