我正在玩Clang上的多态变量lambda并注意到Clang不喜欢这个
#include <iostream>
int main() {
auto append = [](auto &&cnt, auto &&me,
auto &&a, auto &&p1, auto &&...p) -> decltype(auto)
{
if(sizeof...(p) > cnt)
return me(++cnt, me, a << p1, p..., 0);
return a;
};
append(0, append, std::cout, 1, 2, 3, 4);
}
打算输出“1234”。参数列表中会附加一个0(并且每次都会从前面拿走一个参数),当我们需要停止时,计数器会监视,因为我们会遇到一个虚拟0
。
但Clang抱怨
fatal error: recursive template instantiation exceeded maximum depth of 256
在其反向中,大多数功能框架都是
main.cpp:6:20: note: in instantiation of function template specialization 'main()::<anonymous class>::operator()<int &, <lambda at main.cpp:4:19> &, std::basic_ostream<char> &, int &, int &, int &, int>' requested here
return me(++cnt, me, a << p1, p..., 0);
^
这似乎是一个自我调用的递归函数模板,我无法看到无限模板实例化的疯狂。有人可以解释一下吗?标准perpahs是否禁止像lambdas那样的递归?
答案 0 :(得分:10)
那应该是[dcl.spec.auto] / 11(引用n3797)
如果需要具有undeduced占位符类型的实体类型来确定表达式的类型, 该计划格式不正确。但是,在函数中看到
return
语句后,返回类型 从该语句中推导出的可以在函数的其余部分中使用,包括在其他return
语句中。
因此,通过恢复return语句,返回类型推断可以成功:
#include <iostream>
int main() {
auto append = [](auto &&cnt, auto &&me,
auto &&a, auto &&p1, auto &&...p) -> decltype(auto)
{
if(sizeof...(p) <= cnt)
return a;
return me(++cnt, me, a << p1, p..., 0);
};
append(0u, append, std::cout, 1, 2, 3, 4);
}
答案 1 :(得分:2)
我的猜测是,它会永远循环,试图推断出你的回归类型。当它看到return me( ... )
时,它会试图找出该函数的返回值,这也是auto
,它需要确定return me( ... )
是什么等等。
也许试试
if(sizeof...(p) <= cnt) return a;
return me(++cnt, me, a << p1, p..., 0);
或尝试decltype(a)
作为返回类型。
我现在没有1y编译器,或者我可以肯定地说。