Can a std::function store pointers to data members?
Asked Answered
R

1

37

From cppreference, I found that:

Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

I cannot see why a std::function should be able to store such a pointer and I've never heard before about that feature.
Is it really possible, I missed something or that's an error in the documentation?

How should the operator() behave in such a case?
As from the documentation:

Invokes the stored callable function target with the parameters args.

Anyway, there is no stored callable function target to invoke here. Am I wrong?

To be honest, I cannot even figure out what's the right syntax for such a function, otherwise I'd have written an example to test it.
How could the following template be used to define a pointer to data member?

template< class R, class... Args >
class function<R(Args...)>
Roquefort answered 16/2, 2016 at 17:41 Comment(10)
coliru.stacked-crooked.com/a/e7fda761edce7eceMiser
Sorry, I misread. :(Genuflect
Ok, so the idea is the same used for member methods: the signature is exactly the same, but for the first parameter that is the instance on which to invoke them. A similar approach can be used for data members, is it? Interesting.Roquefort
std::bind can be assigned to a std::function.Gassing
@Alex So? bind returns a callable object, it's fine.Roquefort
The data member could be a callable object.Caporetto
@Caporetto see the example in the first comment, that's not because of what you say, I'm sorryRoquefort
@Roquefort Yeah, I figured it out already. Nice to know.Caporetto
@Roquefort another example?Miser
@PiotrSkotnicki A good one for sure, even more with a few details of context. That's a bounty for the sake of curiosity, so I'll assign it the last day, each example is welcome till that day. Thank you. :-)Roquefort
M
26

The effect of a call to the function call operator of std::function<R(ArgTypes...)>:

R operator()(ArgTypes... args) const

is equivalent to (§ 20.9.11.2.4 [func.wrap.func.inv]/p1):

INVOKE<R>(f, std::forward<ArgTypes>(args)...)

whose definition includes the following bullet (§ 20.9.2 [func.require]/p1):

Define INVOKE(f, t1, t2, ..., tN) as follows:

[...]

1.3t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;

then, when f is a pointer to a data member stored in an internal invoker of a std::function, then the std::function itself should define a single argument, e.g.:

std::function<int(std::pair<int,int>)> f = &std::pair<int,int>::first;

f(std::make_pair(1, 2));

DEMO

Miser answered 16/2, 2016 at 18:7 Comment(5)
Being the return type of the function the actual type of the data member, right?Roquefort
That R at the end of INVOKE means "implicitly convertible to R", so the type of the stored data member can be convertible to what std::function definesMiser
Wow, even more powerful than what I guessed. Still I can't see any real use of such a feature, but this cannot lessen its beauty!! Really thank you for your responses, as usual, very appreciated. :-)Roquefort
@Roquefort They are very useful as projections.Kymric
@Kymric It sounds interesting and you know that I want to understand!! :-) ... Would it be possible that you add one more answer with such an example of use? It will have my upvote for sure.Roquefort

© 2022 - 2024 — McMap. All rights reserved.