gpt4 book ai didi

c++ - 为什么通用 lambda 不能调用自己,但将它包装在一个类中允许它?

转载 作者:IT老高 更新时间:2023-10-28 21:41:22 26 4
gpt4 key购买 nike

这是完整的例子:

auto callSelf = [](auto& func) {func(func);};

class wrapper : public decltype(callSelf) {
using base = decltype(callSelf);
public:
wrapper() : base(callSelf) {}

template<class T>
void operator()(T& func) {
base::operator()(func);
}
};

int main()
{
//callSelf(callSelf); // Error
wrapper w;
w(w); // OK, nice endless recursion
}

为什么用wrapper可以,而直接做会导致如下错误?

main.cpp:30: error: use of '<lambda(auto:1&)> [with auto:1 = <lambda(auto:1&)>]' before deduction of 'auto'
auto callSelf = [&](auto& func) {func(func);};
~~~~^~~~~~

最佳答案

这实际上相当棘手。您违反的规则在 [dcl.spec.auto] 中:

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed.

这就是这里的问题:

auto callSelf = [](auto& func) {func(func);};
callSelf(callSelf);

我们需要知道callSelf的类型来确定func(func)的表达式的类型,它本身就是循环的。这很容易通过简单地指定返回类型来解决:

auto callSelf = [](auto& func) -> void {func(func);};
callSelf(callSelf); // ok. I mean, infinite recursion, but otherwise ok. ish.

但是,当您包装 lambda 时,您会得到不同的行为。这一行在这里:

w(w);

wrapper 类型的对象有效地传递给 lambda。那不是它自己的类型。 lambda 的主体在其自身上调用该对象,但我们知道该表达式的类型。你声明了它:

template<class T>
void operator()(T& func) {
~~~~~

这个函数(对于工作的某些定义)与 void 一起工作,原因与我们添加 -> void 时 lambda 工作的原因相同。它不再是一个未推断的占位符。我们已经知道返回类型。要获得与 lambda 相同的行为,请将 operator() 的声明更改为 auto

关于c++ - 为什么通用 lambda 不能调用自己,但将它包装在一个类中允许它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42321573/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com