这个递归多态C++ 1y lambda调用出了什么问题?

Joh*_*itb 8 c++ lambda variadic-templates c++14

我正在玩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);
}
Run Code Online (Sandbox Code Playgroud)

它打算投入"1234".一个0被附加到参数列表(并且反过来每次从前面拿走一个参数)并且计数器在我们需要停止时观察,因为我们将击中一个假人0.

但是Clang抱怨道

fatal error: recursive template instantiation exceeded maximum depth of 256
Run Code Online (Sandbox Code Playgroud)

在其反向中,大多数功能框架都是

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);
                   ^
Run Code Online (Sandbox Code Playgroud)

这似乎是一个自我调用的递归函数模板,我无法看到无限模板实例化的疯狂.有人可以解释一下吗?标准perpahs是否禁止像lambdas那样的递归?

dyp*_*dyp 10

那应该是[dcl.spec.auto]/11(引用n3797)

如果需要具有未减少占位符类型的实体的类型来确定表达式的类型,则该程序是不正确的.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);
}
Run Code Online (Sandbox Code Playgroud)

实例