C ++ 11 lambda返回lambda [英] C++11 lambda returning lambda
问题描述
这段代码对JS开发人员来说不是未知的
this piece of code is not something unknown to JS developers
function get_counter()
{
return (
function() {
var c = 0;
return function() { return ++c; };
})();
}
它基本上创建一个创建不同枚举器。所以我想知道如果同样的事情可以做到在C + + 11与新的lambda语义?我最后写这个C ++,不幸的是不能编译!
it basically creates a which creates different enumerators. So I was wondering if same thing can be done in C++11 with new lambda semantics? I ended up writing this piece of C++ which unfortunately does not compile!
int main()
{
int c;
auto a = [](){
int c = 0;
return [&](){
cout << c++;
};
};
return 0;
}
所以我想知道是否有解决方法来编译它,如果有是怎么可以编译器使这段代码正确运行?我的意思是它必须创建单独的枚举器,但它也应该收集垃圾(未使用的c变量)。
so I was wondering if there is a workaround to get it compiled and if there is how can compiler make this code run correctly? I mean it has to create separate enumerators but it should also collect garbage (unused c variables).
通过我使用VS2012编译器的方式,它会生成此错误:
by the way I'm using VS2012 compiler and it generates this error:
Error 2 error C2440: 'return' : cannot convert from 'main::<lambda_10d109c73135f5c106ecbfa8ff6f4b6b>::()::<lambda_019decbc8d6cd29488ffec96883efe2a>' to 'void (__cdecl *)(void)' c:\users\ali\documents\visual studio 2012\projects\test\test\main.cpp 25 1 Test
推荐答案
您的代码有一个错误, ; c
引用将引用外部lambda中的局部变量,当外部lambda返回时将被销毁。
Your code has a bug in that it contains a dangling reference; the c
reference will refer to the local variable in the outer lambda, which will be destroyed when the outer lambda returns.
您应该使用 mutable
按值lambda捕获来写入:
You should write it using a mutable
by-value lambda capture:
auto a = []() {
int c = 0;
return [=]() mutable {
cout << c++;
};
};
这依赖于后标准扩展来允许多个语句在返回类型推导lambda; 有没有理由不允许lambdas推导出返回类型,如果它包含多个语句?修复它的最简单的方法是提供一个参数,使lambda只包含一个语句:
This relies on a post-standard extension to allow multiple statements in a return-type-deducing lambda; Is there a reason on not allowing lambdas to deduce the return type if it contains more than one statement? The easiest way to fix it is to supply a parameter so that the lambda contains only a single statement:
auto a = [](int c) {
return [=]() mutable {
cout << c++;
};
};
不幸的是,lambdas中不允许使用默认参数,因此您必须将其称为 a(0)
。或者以可读性为代价,您可以使用嵌套lambda调用:
Unfortunately default parameters aren't allowed in lambdas, so you'd have to call this as a(0)
. Alternatively at the cost of readability you could use a nested lambda call:
auto a = []() {
return ([](int c) {
return [=]() mutable {
cout << c++;
};
})(0);
};
这种方式的工作原理是当 a
执行内部lambda将所有引用的变量复制到其闭包类型的实例中,这将是:
The way this works is that when a
executes the inner lambda copies all the referenced variables into an instance of its closure type, which here would be something like:
struct inner_lambda {
int c;
void operator()() { cout << c++; }
};
闭包类型的实例由外部lambda返回,可以被调用,
The instance of the closure type is then returned by the outer lambda, and can be invoked and will modify its copy of c
when called.
总之,你的(固定)代码被翻译成:
Overall, your (fixed) code is translated to:
struct outer_lambda {
// no closure
struct inner_lambda {
int c; // by-value capture
// non-const because "mutable"
void operator()() { cout << c++; }
}
// const because non-"mutable"
inner_lambda operator()(int c) const {
return inner_lambda{c};
}
};
如果您将 c
参考捕获,这将是:
If you left c
as a by-reference capture, this would be:
struct outer_lambda {
// no closure
struct inner_lambda {
int &c; // by-reference capture
void operator()() const { cout << c++; } // const, but can modify c
}
inner_lambda operator()(int c) const {
return inner_lambda{c};
}
};
这里 inner_lambda :: c
引用本地参数变量 c
。
Here inner_lambda::c
is a dangling reference to the local parameter variable c
.
这篇关于C ++ 11 lambda返回lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!