lambda 中的递归调用 (C++11)
可能的重复:
c++0x 中的递归 lambda 函数
为什么我不能递归调用 lambda 如果我将其写为:
auto a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a(); //recursive call
};
它给出编译错误(ideone):
prog.cpp:8:18: error: '((const main()::<lambda()>*)this)->main()::<lambda()>::a' cannot be used as a function
prog.cpp: In function 'int main()':
prog.cpp:9:9: error: variable 'auto a' with 'auto' type used in its own initializer
什么错误是什么意思?
我明白我不能写这个的原因:
auto i=i+1; //error: unable to deduce 'auto' from '<expression error>'
我们不能写这个,因为 i
的类型必须从它的初始化中推断出来,这意味着如果 i 则无法推断出类型
本身出现在初始化中 (ideone)。但对于 lambda 来说这有什么关系呢?如果我没记错的话,lambda 的类型是由它的参数和返回类型决定的;如果它不返回任何内容,则它不依赖于主体(在这种情况下,返回类型将被推导为 void
,无论 lambda 主体中的其他语句如何)。
无论如何,我有一个解决方法,我可以使用 std::function
代替:
std::function<void()> a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a();
};
编译罚款 (ideone)。但我仍然有兴趣知道 auto
版本无法编译的原因。
Possible Duplicate:
Recursive lambda functions in c++0x
Why can't I call a lambda recursively if I write it as:
auto a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a(); //recursive call
};
It gives compilation error (ideone):
prog.cpp:8:18: error: '((const main()::<lambda()>*)this)->main()::<lambda()>::a' cannot be used as a function
prog.cpp: In function 'int main()':
prog.cpp:9:9: error: variable 'auto a' with 'auto' type used in its own initializer
What does the error mean?
I understand the reason why I can't write this:
auto i=i+1; //error: unable to deduce 'auto' from '<expression error>'
We can't write this because the type of i
has to be deduced from it's initialization, which means the type cannot be deduced if i
itself appears in the initialization (ideone). But how does it matter in case of lambda? If I'm not wrong, the type of a lambda is determined by it's parameter(s) and the return type; it doesn't depend on the body if it returns nothing (in which case, the return type is deduced as void
, irrespective of other statements in the lambda-body).
Anyway, I got a workaround, and I can use std::function
instead as:
std::function<void()> a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a();
};
which compile fines (ideone). But I'm still interested to know the reason why the auto
version doesn't compile.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
原因是
auto
变量的 lambda 表达式初始值设定项没有特殊情况。这种特殊情况很容易出现错误和误用。当您建议像
a()
这样的东西应该起作用时,您需要定义规则。operator()
是如何查找的?a
类型的精确状态是什么?类型会完整吗? (这意味着您已经知道 lambda 的捕获列表)。一旦您以适合规范的合理格式制定了该内容,就可以更轻松地对其进行陈述。允许您的用例意味着您需要在代码中提前扫描的另一种情况,因为要确定
a()
中的a
的类型,您必须确保初始化程序没有任何可以“unlambda”类型的内容结束。在这种情况下,x() 将调用
y::operator()
,而不是 lambda。现在,
a
被禁止在其整个初始值设定项中提及。因为在 C++ 中,auto
不是一种类型。它只是一个类型说明符,代表要推导的类型。因此,表达式永远不能具有 auto 类型。The reason is that there is no special case for lambda-expression initializers of
auto
variables.Such special cases would be prone to errors and misuses. You need to define the rules when you propose that something like
a()
should work. How is theoperator()
looked up? What is the precise state ofa
's type? Will the type be complete? (which implies that you already know the capture list of the lambda). Once you have formulated that in a format reasonable for a spec, it would be easier to make statements on it.Allowing your use case would mean yet another case where you need to scan ahead in code, because to determine the type of
a
ina()
you must be sure that the initializer ends with nothing that could "unlambda" the typeIn this case,
x()
would cally::operator()
, not the lambda.As it is now,
a
is simply forbidden to be mentioned in its entire initializer. Because in C++,auto
is not a type. It is merely a type specifier standing for a to-be-deduced type. As a consequence, an expression can never have type auto.正如我所见, auto a 情况和 std::function之间的重要区别是:一种情况是类型 std::function不知道/关心它所引用的实际函数的类型到底是什么。写作:
完全没问题,而 as:
毫无意义。因此,当需要合成捕获时,如果您使用 std::function,则所有需要了解的类型都已经知道,而使用
auto
代码> 目前还不知道。As I see it the important difference between the
auto a
case and thestd::function<void()> a
case is that the typestd::function<void()>
doesn't know/care about what the type of the real function it refers to really is. Writing:is perfectly fine, where as:
makes little sense. So when the time comes to synthesize the capture if you use
std::function<void()>
all that needs to be known about the type is already known, whereas withauto
it's not yet known.在递归函数中,
f
由f
定义,在以下情况下,f
的返回类型也由f
确定auto
所以它会导致无限递归。当
auto
尝试派生类型时。 decltype(f()) 将进一步推导出另一个 decltype(f)`,因为 f 派生为 f,例如对任何递归的调用也是递归的。当应用于递归函数时,返回类型确定会变成递归。在递归函数中,递归结束可以在运行时完成。但决定只是静态的In a recursive function
f
is defined byf
and return type off
is also determined byf
in case ofauto
so it leads to infinite recursion.when
auto
tries to derive a type. decltype(f()) will further deduce to another decltype(f)` as f derives to f e.g. a call on anything recursive is recursive too. return type determination turns recursive when applied on a recursive function. in a recursive function end of the recursion may be done on runtime. but determination is static only