There is no way to directly get the address of a lambda object within a lambda prior to c++23.
Now, as it happens this is quite often useful. The most common use is in order to recurse.
The y_combinator
comes from languages where you could not talk about yourself until you where defined. It can be implemented pretty easily in c++:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( f, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( f, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator(F)->y_combinator<F>;
now you can do this:
y_combinator{ [](auto& self)-> void {
std::cout<<"Address of this lambda function is => "<< &self;
} }();
There are a few useful variations. One variation I find particularly useful is:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( *this, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( *this, std::forward<Args>(args)... );
}
};
where the self
passed can be called without passing in self
as the first argument.
The second matches the real y combinator (aka the fixed point combinator) I believe. Which you want depends on what you mean by 'address of lambda'.
There is also this pithy one:
template<class R, class...Args>
auto Y = [] (auto f) {
auto action = [=] (auto action) -> std::function<R(Args...)> {
return [=] (Args&&... args)->R {
return f( action(action), std::forward<Args>(args)... );
};
};
return action(action);
};
which returns a std function.
In c++23 accessing this
within a lambda gets easier:
auto fib = [](this auto& self, int n) {
if (n < 2) return n;
return self(n-1) + self(n-2);
};
you can tag the first argument as this
, and it becomes itself. It even works with the overload set trick, where self
is the most-deduced type.