Reputation: 1490
Browsing some internet board I encountered this little challenge:
"Implement a recursive anonymous function in your favorite language"
Obviously this is easy using a std::function/function pointer.
What I'm really interested in is if this is possible without binding the lambda to an identifier?
Something like (ignoring the obvious infinite recursion):
[](){ this(); }();
Upvotes: 7
Views: 1018
Reputation: 179442
Of course, in C++, to call any function you have to bind it to an identifier somewhere, simply owing to syntax constraints. But, if you will accept parameters as being sufficiently unnamed, then it is possible to create a version of the y-combinator in C++ which recurses nicely without being "named".
Now, this is really ugly because I don't know how to do a typedef for a recursive lambda. So it just uses a lot of cast abuse. But, it works, and prints FLY!!
until it segfaults due to stack overflow.
#include <iostream>
typedef void(*f0)();
typedef void(*f)(f0);
int main() {
[](f x) {
x((f0)x);
} ([](f0 x) {
std::cout<<"FLY!!\n";
((f)x)(x);
});
}
The two lambdas are unnamed in the sense that neither is explicitly assigned to name anywhere. The second lambda is the real workhorse, and it basically calls itself by using the first lambda to obtain a reference to itself in the form of the parameter.
Here's how you would use this to do some "useful" work:
#include <iostream>
typedef int param_t;
typedef int ret_t;
typedef void(*f0)();
typedef ret_t(*f)(f0, param_t);
int main() {
/* Compute factorial recursively */
std::cout << [](f x, param_t y) {
return x((f0)x, y);
} ([](f0 x, param_t y) {
if(y == 0)
return 1;
return y*((f)x)(x, y-1);
}, 10) << std::endl;
}
Upvotes: 5
Reputation: 1490
I seem to have come up with a solution of my own:
#include <iostream>
int main()
{
std::cout<<"Main\n";
[&](){
std::cout<<"Hello!\n";
(&main+13)();
}();
}
First call to cout is present just to show that it's not calling main.
I came up with the 13 offset by trial and error, if anyone could explain why it's this value it would be great.
Upvotes: 0
Reputation: 56479
No identifier for functions/methods, Close enough or not !?
struct A
{
void operator()()
{
[&]()
{
(*this)();
}();
}
};
To call
A{}(); // Thanks MooningDuck
Upvotes: 1
Reputation: 131799
Are you allowed to cheat?
void f(){
[]{ f(); }();
}
It's recursive - indirectly, atleast.
Otherwise, no, there is no way to refer to the lambda itself without assigning it a name.
Upvotes: 3