#include <functional>
#include <memory>
#include <iostream>
#include <queue>
template<class Sig>
struct recursive;
template<class R, class... As>
struct recursive< R(As...) > {
using base_type = std::function<R(recursive, As...)>;
private:
std::shared_ptr< base_type > base;
public:
template<typename...Ts>
auto operator()(Ts&&... ts) const
-> typename std::result_of< base_type( recursive, Ts... ) >::type
{
return (*base)(*this, std::forward<Ts>(ts)...);
}
recursive(recursive const&)=default;
recursive(recursive&&)=default;
recursive& operator=(recursive const&)=default;
recursive& operator=(recursive &&)=default;
recursive() = default;
template<typename L, typename=typename std::result_of< L(recursive, As...) >::type>
explicit recursive( L&& f ):
base( std::make_shared<base_type>(std::forward<L>(f)))
{}
explicit operator bool() const { return base && *base; }
};
typedef std::queue<std::function<void (void)>> my_queue;
std::function<void (int)> get_recursive_function(my_queue& queue) {
my_queue* pqueue = &queue;
// Closure to allow self-reference
auto f = [pqueue](recursive<void(int)> self, int recurse) {
std::cout << recurse << std::endl;
if (recurse == 0)
return;
pqueue->push( [self,recurse](){ self(recurse-1); } );
};
return recursive<void(int)>( f );
}
int main(int, char **) {
my_queue queue;
queue.push([&](){ get_recursive_function(queue)(10); } );
while (!queue.empty()) {
queue.front()();
queue.pop();
}
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxtZW1vcnk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHF1ZXVlPgoKICAgIHRlbXBsYXRlPGNsYXNzIFNpZz4KICAgIHN0cnVjdCByZWN1cnNpdmU7CiAgICB0ZW1wbGF0ZTxjbGFzcyBSLCBjbGFzcy4uLiBBcz4KICAgIHN0cnVjdCByZWN1cnNpdmU8IFIoQXMuLi4pID4gewogICAgICB1c2luZyBiYXNlX3R5cGUgPSBzdGQ6OmZ1bmN0aW9uPFIocmVjdXJzaXZlLCBBcy4uLik+OwogICAgcHJpdmF0ZToKICAgICAgc3RkOjpzaGFyZWRfcHRyPCBiYXNlX3R5cGUgPiBiYXNlOwogICAgcHVibGljOgogICAgICAKICAgICAgdGVtcGxhdGU8dHlwZW5hbWUuLi5Ucz4KICAgICAgYXV0byBvcGVyYXRvcigpKFRzJiYuLi4gdHMpIGNvbnN0CiAgICAgIC0+IHR5cGVuYW1lIHN0ZDo6cmVzdWx0X29mPCBiYXNlX3R5cGUoIHJlY3Vyc2l2ZSwgVHMuLi4gKSA+Ojp0eXBlCiAgICAgIHsKICAgICAgICByZXR1cm4gKCpiYXNlKSgqdGhpcywgc3RkOjpmb3J3YXJkPFRzPih0cykuLi4pOwogICAgICB9CgogICAgICByZWN1cnNpdmUocmVjdXJzaXZlIGNvbnN0Jik9ZGVmYXVsdDsKICAgICAgcmVjdXJzaXZlKHJlY3Vyc2l2ZSYmKT1kZWZhdWx0OwogICAgICByZWN1cnNpdmUmIG9wZXJhdG9yPShyZWN1cnNpdmUgY29uc3QmKT1kZWZhdWx0OwogICAgICByZWN1cnNpdmUmIG9wZXJhdG9yPShyZWN1cnNpdmUgJiYpPWRlZmF1bHQ7CiAgICAgIHJlY3Vyc2l2ZSgpID0gZGVmYXVsdDsKICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgTCwgdHlwZW5hbWU9dHlwZW5hbWUgc3RkOjpyZXN1bHRfb2Y8IEwocmVjdXJzaXZlLCBBcy4uLikgPjo6dHlwZT4KICAgICAgZXhwbGljaXQgcmVjdXJzaXZlKCBMJiYgZiApOgogICAgICAgIGJhc2UoIHN0ZDo6bWFrZV9zaGFyZWQ8YmFzZV90eXBlPihzdGQ6OmZvcndhcmQ8TD4oZikpKQogICAgICB7fQogICAgICBleHBsaWNpdCBvcGVyYXRvciBib29sKCkgY29uc3QgeyByZXR1cm4gYmFzZSAmJiAqYmFzZTsgfQogICAgfTsKCnR5cGVkZWYgc3RkOjpxdWV1ZTxzdGQ6OmZ1bmN0aW9uPHZvaWQgKHZvaWQpPj4gbXlfcXVldWU7CgpzdGQ6OmZ1bmN0aW9uPHZvaWQgKGludCk+IGdldF9yZWN1cnNpdmVfZnVuY3Rpb24obXlfcXVldWUmIHF1ZXVlKSB7CglteV9xdWV1ZSogcHF1ZXVlID0gJnF1ZXVlOwogICAgLy8gQ2xvc3VyZSB0byBhbGxvdyBzZWxmLXJlZmVyZW5jZQogICAgYXV0byBmID0gW3BxdWV1ZV0ocmVjdXJzaXZlPHZvaWQoaW50KT4gc2VsZiwgaW50IHJlY3Vyc2UpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgcmVjdXJzZSA8PCBzdGQ6OmVuZGw7CiAgICAgICAgaWYgKHJlY3Vyc2UgPT0gMCkKICAgICAgICAJcmV0dXJuOwogICAgCXBxdWV1ZS0+cHVzaCggW3NlbGYscmVjdXJzZV0oKXsgc2VsZihyZWN1cnNlLTEpOyB9ICk7CiAgICB9OwogICAgcmV0dXJuIHJlY3Vyc2l2ZTx2b2lkKGludCk+KCBmICk7Cn0KCmludCBtYWluKGludCwgY2hhciAqKikgewoJbXlfcXVldWUgcXVldWU7CiAgICBxdWV1ZS5wdXNoKFsmXSgpeyBnZXRfcmVjdXJzaXZlX2Z1bmN0aW9uKHF1ZXVlKSgxMCk7IH0gKTsKCiAgICB3aGlsZSAoIXF1ZXVlLmVtcHR5KCkpIHsKICAgICAgICBxdWV1ZS5mcm9udCgpKCk7CiAgICAgICAgcXVldWUucG9wKCk7CiAgICB9Cn0K