Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 675
Johannes Schaub - litb Avatar asked Mar 06 '14 21:03

Johannes Schaub - litb


People also ask

Can lambda call recursive?

A recursive lambda expression is the process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. Using a recursive algorithm, certain problems can be solved quite easily.

Is it possible to write a recursive lambda expression C++?

But a lambda cannot be recursive, it has no way to invoke itself. A lambda has no name and using this within the body of a lambda refers to a captured this (assuming the lambda is created in the body of a member function, otherwise it is an error).

How do you write a lambda function in C++?

Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.

Can lambdas be Constexpr?

constexpr lambda expressions in C++ Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.


2 Answers

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

like image 184
dyp Avatar answered Nov 15 '22 17:11

dyp


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.

like image 39
KitsuneYMG Avatar answered Nov 15 '22 17:11

KitsuneYMG