Member Variable Pointer

1.1k views Asked by At

For a given struct:

struct foo
{
    void fooFunc(){}
    int fooVar = 0;
};

I can create a call wapper to the function: std::mem_fn( &foo::fooFunc ) such that I can pass it into another method and call it on an object.
I want to know if there is a similar call wrapper but for member variables.

For example I'm using a pointer to a member variable here and but I'd like to use an call wrapper:

void bar( std::function< void( foo ) > funcPtr, int foo::* varPtr )
{
    foo myFoo;
    funcPtr( myFoo );
    foo.*varPtr = 13;
}
2

There are 2 answers

8
Jonathan Wakely On BEST ANSWER

N.B. Nothing in your question is from the STL (which is a library from the 1990s), std::function and std::mem_fn are part of the C++ Standard Library, which is not the same thing.

std::mem_fn supports member functions and member variables, so you can just do this to access the member variable and set it:

foo f;
std::function<int&(foo&)> var( std::mem_fn( &foo::fooVar ) );
var(f) = 1;
4
Praetorian On

In addition to member functions, std::mem_fn can wrap data members too, and allow read access to them. So the following works:

void print_fooVar(foo& f, std::function<int(foo)> varAccess)
{
    std::cout << varAccess(f) << std::endl;
}

foo f;
print_fooVar(f, std::mem_fn(&foo::fooVar)); // prints 0

As JonathanWakely mentions in the comments, you can use the (unspecified) type returned by mem_fn itself to set the data member.

foo f;
std::mem_fn(&foo::fooVar)(f) = 13;

Or to transform it into an std::function use

void bar( foo& f, std::function<int&(foo&)> fooVarSet )
{
    fooVarSet(f) = 26;
}

If all you're looking for is a way to generate a callable to set the fooVar data member, and not using std::mem_fn specifically to do this, you can get the job done using a lambda expression as well.

void bar( foo& f, std::function<void(foo)> funcPtr, 
                  std::function<void(foo&, int)> fooVarSet )
{
    funcPtr( f );
    fooVarSet(f, 13);
}

foo f;
bar(f, std::mem_fn(&foo::fooFunc), [](foo& f, int i) {f.fooVar = i;});

Live demo