How to get the address of a C++ lambda function within the lambda itself?

C++C++11LambdaC++14C++17

C++ Problem Overview


I'm trying to figure out how to get the address of a lambda function within itself. Here is a sample code:

[]() {
    std::cout << "Address of this lambda function is => " << ????
}();

I know that I can capture the lambda in a variable and print the address, but I want to do it in place when this anonymous function is executing.

Is there a simpler way to do so?

C++ Solutions


Solution 1 - C++

There is no way to directly get the address of a lambda object within a lambda.

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 [tag: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.


Now, there is a proposal -- in particular, recursive lambdas are really easy.

> auto fib = [](auto& this self, int n) { > if (n < 2) return n; > return self(n-1) + self(n-2); > };

(This proposal got very positive reviews at the standard meeting).

Solution 2 - C++

It is not directly possible.

However, lambda captures are classes and the address of an object coincides with the address of its first member. Hence, if you capture one object by value as the first capture, the address of the first capture corresponds to the address of the lambda object:

int main() {
    int i = 0;
    auto f = [i]() { printf("%p\n", &i); };
    f();
    printf("%p\n", &f);
}

Outputs:

0x7ffe8b80d820
0x7ffe8b80d820

Alternatively, you can create a decorator design pattern lambda that passes the reference to the lambda capture into its call operator:

template<class F>
auto decorate(F f) {
    return [f](auto&&... args) mutable {
        f(f, std::forward<decltype(args)>(args)...);
    };
}

int main() {
    auto f = decorate([](auto& that) { printf("%p\n", &that); });
    f();
}

Solution 3 - C++

One way to solve this, would be to replace the lambda with a hand written functor class. It's also what the lambda essentially is under the hood.

Then you can get the address through this, even without ever assigning the functor to a variable:

#include <iostream>

class Functor
{
public:
    void operator()() {
        std::cout << "Address of this functor is => " << this;
    }
};

int main()
{
    Functor()();
    return 0;
}

>Output: >none >Address of this functor is => 0x7ffd4cd3a4df >

This has the advantage that this is 100% portable, and extremely easy to reason about and understand.

Solution 4 - C++

Capture the lambda:

std::function<void ()> fn = [&fn]() {
  std::cout << "My lambda is " << &fn << std::endl;
}

Solution 5 - C++

It is possible but highly depends on the platform and compiler optimization.

On most of the architectures I know, there is register called instruction pointer. The point of this solution is to extract it when we are inside the function.

On amd64 Following code should give you addresses close to the function one.

#include <iostream>

void* foo() {
	void* n;
	asm volatile("lea 0(%%rip), %%rax"
	  : "=a" (n));
	return n;
}

auto boo = [](){
	void* n;
	asm volatile("lea 0(%%rip), %%rax"
	   : "=a" (n));
	return n;
};

int main() {
	std::cout<<"foo"<<'\n'<<((void*)&foo)<<'\n'<<foo()<<std::endl;	
	std::cout<<"boo"<<'\n'<<((void*)&boo)<<'\n'<<boo()<<std::endl;
}

But for example on gcc https://godbolt.org/z/dQXmHm with -O3 optimization level function might be inlined.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDeepak Kr GuptaView Question on Stackoverflow
Solution 1 - C++Yakk - Adam NevraumontView Answer on Stackoverflow
Solution 2 - C++Maxim EgorushkinView Answer on Stackoverflow
Solution 3 - C++ruoholaView Answer on Stackoverflow
Solution 4 - C++Vincent FourmondView Answer on Stackoverflow
Solution 5 - C++majkrzakView Answer on Stackoverflow