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

时间:2014-03-06 21:24:45

标签: 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);
}

打算输出“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那样的递归?

2 个答案:

答案 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);
}

Live example

答案 1 :(得分:2)

我的猜测是,它会永远循环,试图推断出你的回归类型。当它看到return me( ... )时,它会试图找出该函数的返回值,这也是auto,它需要确定return me( ... )是什么等等。

也许试试

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

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

我现在没有1y编译器,或者我可以肯定地说。