这种递归多态 C++1y lambda 调用有什么问题?

What's wrong with this recursive polymorphic C++1y lambda call?

本文关键字:什么 问题 调用 lambda 递归 多态 C++1y      更新时间:2023-10-16

我在clang上玩多态variadic lambdas,并注意到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);
                   ^

这似乎是一个自称为自我的递归函数模板,我看不到无限模板的瞬间疯狂。有人可以放光吗?标准的Perpah是否禁止这样的递归?

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

如果需要具有未支配占位符类型的实体的类型来确定表达式的类型, 该程序形式不佳。但是,一旦在函数中看到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);
}

实时示例

我的猜测是,它永远在尝试推断出您的返回类型。当它看到return me( ... )时,它试图弄清楚该功能的返回是什么,这也是auto,它需要弄清楚return me( ... )是什么,等等。

也许尝试

if(sizeof...(p) <= cnt) return a;
return me(++cnt, me, a << p1, p..., 0);

或尝试decltype(a)作为返回类型。

我目前没有一个方便的编译器,否则我可以肯定地说。