C++11 在C++;11如何将函数合并为新函数?

C++11 在C++;11如何将函数合并为新函数?,c++11,lambda,functional-programming,function-composition,C++11,Lambda,Functional Programming,Function Composition,这更是一种理论问题。在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 第一次尝试: template&

这更是一种理论问题。在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
第一次尝试:

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);
}
其中
get_x
get_y
只返回一个坐标,而
print_coord
获取两个坐标并打印它们

要在C++中仿真这一点,我们需要一些奇特的机器。函数将返回
tuple
s(或类似tuple的?),这些值将在逻辑上“推送到参数堆栈上”

函数还将消耗此参数堆栈中的内容

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

对于这个更高级的
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;
  };
}

你可以写一些大致如下的内容:

#include <functional>
#include <iostream>

template<class F>
F compose(F f, F g)
{
  return [=](int x) { return f(g(x)); };
}

int main()
{
  std::function<int (int)> f = [](int i) { return i * 2; };
  std::function<int (int)> g = [](int i) { return i + 10; };

  auto c = compose(f, g);
  std::cout << c(20) << '\n';  // prints 60
}
#包括
#包括
模板
F组合(F,F g)
{
return[=](int x){return f(g(x));};
}
int main()
{
函数f=[](inti){returni*2;};
函数g=[](inti){返回i+10;};
自动c=合成(f,g);

你不能自动做c=[](inti){return f(g(i));}哦,是的,你是对的,但我忘了一半的问题……:(无论如何,谢谢你。皮尤,学了这么多新东西。无论如何,你说服了我,我不想这么做。)@AquilaRapax第一个compose没有什么特别的错误。它只是不支持您想要的那么多。@AquilaRapax注意,这个版本(A)不必要地复制函数对象,(B)只支持一个
int
参数,(C)一次只支持组合两个函数。
compose(F,unsigned)如果将lambda(未包装在
std::function
中)作为其第一个参数传递,则该函数将不起作用。它还执行n级类型擦除,这可能会非常慢。但是,是的,它更简单。:)
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";    
2
6
18
54
#include <functional>
#include <iostream>

template<class F>
F compose(F f, F g)
{
  return [=](int x) { return f(g(x)); };
}

int main()
{
  std::function<int (int)> f = [](int i) { return i * 2; };
  std::function<int (int)> g = [](int i) { return i + 10; };

  auto c = compose(f, g);
  std::cout << c(20) << '\n';  // prints 60
}
template<class F>
F compose(F f, unsigned n)
{
  auto g = f;

  for (unsigned i = 0; i < n; ++i)
    g = compose(g, f);

  return g;
}

int main()
{
  std::function<int (int)> h = [](int i) { return i * i; };

  auto d = compose(h, 1);
  auto e = compose(h, 2);
  std::cout << d(3) << "\n"    // prints 81
            << e(3) << "\n";   // prints 6561
}