Search code examples
c++c++11lambdametaprogrammingfunction-pointers

Using std::function/mem_fn in C++11 with member functions


Long story short, is there a simple/defined way to treat function objects/lambdas and member functions in a streamlined way?

If I understand right, if I use std::mem_fn, I need to pass an object of the correct type to the function call, i.e.

Object o;
ftncall std::mem_fun(&Object::function);
ftncall(o);

Ideally, there would be some way to 'attach' o to that function object, perhaps as a std::weak_ptr, so we know if o got deleted. For example, if there were a way to do something vaguely like this:

Object o;
ftncall std::mem_fn(&Object::function, o); // Or maybe std::mem_fn<Object>
ftncall();

Now, obviously, this doesn't exist (to my knowledge). Is there a way to wrap std::mem_fn in such a way that I don't loose the generality (and niceness) of std::mem_fn, but can 'attach' o, AND still play nicely with the other function type, like std::function? Ideally, I'd still be able to use operator() in the way that I do with std::function.

Currently the best solution I can think of is a class that looks like this:

template<class T>
class MemFunWrapper {
public:
    MemFunWrapper(T* t, std::mem_fun funct) : m_t(t), m_function(funct) {}

    std::mem_fun operator*() { return m_function; }
    T* get() { return m_t; }
private:
    T* m_t;
    std::mem_fun m_function;
}

Then you could use it thusly:

(*MemFunWrapper)(MemFunWrapper->get(), args...);

But that seems pretty unwieldy to me. Also, I'd have to create an equivalent class for std::function for that to be usable in the analogous way, and that seems silly since I can already just use std::function. Ideally, I'd also be able to use the end product without knowing if I'm calling a member function or a regular function. I know I'm asking a lot - any direction would be helpful. Many thanks!


Solution

  • What you're looking for is std::bind instead of std::mem_fn:

    #include <iostream>
    #include <functional>
    
    struct Object
    {
      void member()
      {
        std::cout << "yay!" << std::endl;
      }
    };
    
    int main()
    {
      Object o;
      auto fn = std::bind(&Object::member, o);
      fn();
    }
    

    FWIW: There's a proposal for adding an overload to std::mem_fn accepting the object for inclusion in C++14.