这是一种理论问题。在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
修改
另外我想要创建的是一个函数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)))
答案 0 :(得分:2)
第一次尝试:
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 )
其中get_x
和get_y
只消耗一个坐标,而print_coord
只占用两个坐标并打印出来。
要在C ++中模拟它,我们需要一些奇特的机器。函数将返回tuple
s(或tuple-likes?),这些值将在逻辑上“推入参数堆栈”。
函数也会消耗此参数堆栈中的内容。
在每次调用时,我们解包当前的参数元组,找到可以调用函数的最长集合,调用它,获取其返回值,如果它是一个元组则解压缩它,然后粘贴任何这样的返回值回到论坛上。
对于这个更高级的compose
自己组合,它需要SFINAE检查,它需要能够获取一个可调用的对象和一个参数元组,并找到正确数量的参数来调用invokable对象,加上左侧参数。
这是一个棘手的元编程,我不会在这里做。
答案 1 :(得分:1)
您可以按照以下方式写点东西:
#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
}
注意。在这里使用std::function
。它不是lambda,而是以性能成本包装lambda。