質問

I was playing around with polymorphic variadic lambdas on Clang and noticed that Clang doesn't like this one

#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);
}

It's intended to putput "1234". A 0 is appended to the parameter list (and in turn one of the parameters from the front is taken away each time) and a counter watches when we need to stop because we would be hitting a dummy 0.

But Clang complains about

fatal error: recursive template instantiation exceeded maximum depth of 256

In its backtract, most of the function frames are

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);
                   ^

This seems like a recursive function template that calls itself, and I can't see the infinite template instantiation madness. Can someone please shed some light? Does the Standard perpahs forbid recursion like that for lambdas?

役に立ちましたか?

解決

That should be [dcl.spec.auto]/11 (quoting n3797)

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. Once a return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.

So, by reverting the return-statements, the return type deduction can succeed:

#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

他のヒント

My guess would be it's looping forever trying to deduce your return type. When it sees return me( ... ), it tries to figure out what THAT function's return is, which is also auto which requires figuring out what return me( ... ) is and so on.

Maybe try

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

or try decltype(a) as the return type.

I don;t have a 1y compiler handy at the moment, or I'd be able to say for certain.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top