我是C++11的新手,我正在写下面的递归lambda函数,但是它不能编译。
sum.cpp
#include <iostream>
#include <functional>
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = [term,next,&sum](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
int main(){
std::cout<<sum(1,10)<<std::endl;
return 0;
}
编译错误:
vimal@linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp
sum.cpp:在lambda函数中: sum.cpp:18:36: error:‘((<lambda(int, int)>*)this)-><lambda(int, int)>::sum
’不能用作函数
gcc版
gcc版本4.5.0 20091231 (实验版) (GCC)
但是,如果我像下面这样更改sum()
的声明,它就会起作用:
std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
有没有人能帮我解释一下?
发布于 2016-11-30 02:56:19
有了C++14,现在只需几行代码就可以很容易地创建一个高效的递归lambda,而不必产生std::function
的额外开销:
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
return f(*this, std::forward<Args>(args)...);
}
};
// helper function that deduces the type of the lambda:
template <class F>
y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
return {std::forward<F>(f)};
}
使用它,您的原始sum
尝试将变成:
auto sum = make_y_combinator([term,next](auto sum, int a, int b) {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
});
在C++17中,通过CTAD,我们可以添加一个扣减指南:
template <class F> y_combinator(F) -> y_combinator<F>;
这消除了对助手函数的需要。我们可以直接编写y_combinator{[](auto self, ...){...}}
。
在C++20中,使用CTAD进行聚合,就不需要演绎指南了。
发布于 2012-12-31 02:45:26
我有另一个解决方案,但只能使用无状态lambda:
void f()
{
static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };
std::cout<<self(10);
}
这里的诀窍是lambdas可以访问静态变量,您可以将无状态变量转换为函数指针。
您可以将其与标准lambdas一起使用:
void g()
{
int sum;
auto rec = [&sum](int i) -> int
{
static int (*inner)(int&, int) = [](int& _sum, int i)->int
{
_sum += i;
return i>0 ? inner(_sum, i-1)*i : 1;
};
return inner(sum, i);
};
}
它在GCC 4.7中的工作
发布于 2017-08-23 02:41:55
要在不使用外部类和函数(如std::function
或定点组合器)的情况下使lambda递归,可以在C++14 (live example)中使用以下结构:
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list< tree > children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
打印:
1
2
8
3
5
7
6
4
注意,lambda的结果类型应该显式指定。
https://stackoverflow.com/questions/2067988
复制相似问题