5

Since std::function can hold member functions, so it must store a pointer to the object instance somewhere.

How can I fetch the this pointer from a std::function that holds a member function?

danijar
  • 32,406
  • 45
  • 166
  • 297

2 Answers2

9

An object of type std::function holds a callable object. A pointer to member function is a kind of callable object; it can be called with an argument of the appropriate class type, plus any additional arguments that it needs. For example:

struct S {
    void f(int);
};
std::function<void(S, int)> g(&S::f);

To call it, pass an object of type S:

S s;
g(s, 3);

Note that the std::function object does not hold an S object; it's only when you call it that the function pointer gets bound to an object.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 1
    My goal is to unwrap lambdas I passed as `std::function` to another function. How can I do so then? By unwrapping I mean to split it up into a `this` pointer and a static function pointer using `std::function::target` for further processing. – danijar Apr 01 '13 at 17:11
  • 3
    @danijar: Why don't you put your goal into your question instead? Your question makes little sense. – GManNickG Apr 01 '13 at 17:13
  • @danijar you can make your own function object which binds a `this` pointer and allows retrieval. – Pubby Apr 01 '13 at 17:16
  • @danijar if it's a *static function*, there is no bound object instance. – Drew Dormann Apr 01 '13 at 17:17
  • When I store a lambda expression as `std::function`, it the `this` pointer already bound then? – danijar Apr 01 '13 at 17:32
  • @danijar - a lambda function doesn't necessarily have a `this` pointer. Whatever arguments it captures are stored in the object, and there is no mechanism for pulling them out. If you need to do that, a lambda is probably **not** what you should use. – Pete Becker Apr 01 '13 at 18:17
  • @PeteBecker. Thanks, so the reference is kind of bound like `std::bind` would do, if I understand right. But why does `.target()` return a null pointer then? – danijar Apr 01 '13 at 18:19
  • @danijar - `std::function::target` is a template function; when you call it you have to specify the type that you're looking for. If that's the type stored in the object, you get back a pointer to the callable object. If it's not the right type you get back a null pointer. – Pete Becker Apr 01 '13 at 18:21
  • @PeteBecker. The lambda comes as a parameter of the type `function(Arguments const &)>`. I try to cast that to a raw function pointer with the signature `Handle(Arguments const &)`. But, maybe because I used the capture clause, it returns a null pointer. But you answered the question, I asked. If you still want to help me, please follow the link I posted as comment under the question. – danijar Apr 01 '13 at 18:24
0

You can wrap the std::function template in a functionally similar template, but one that exposes the functions you want (like sorting by address or whatever else)

See Stroika Function Template for an example implementation.

It works just like std::function (and lets you retrieve the aggregated std::function), but also keeps extra info to allow sorting and so on (handy to store the function pointers in a map and have object identity to later remove them).

lewis
  • 1,116
  • 1
  • 12
  • 28