246

For one class I want to store some function pointers to member functions of the same class in one map storing std::function objects. But I fail right at the beginning with this code:

#include <functional>

class Foo {
    public:
        void doSomething() {}
        void bindFunction() {
            // ERROR
            std::function<void(void)> f = &Foo::doSomething;
        }
};

I receive error C2064: term does not evaluate to a function taking 0 arguments in xxcallobj combined with some weird template instantiation errors. Currently I am working on Windows 8 with Visual Studio 2010/2011 and on Win 7 with VS10 it fails too. The error must be based on some weird C++ rules i do not follow

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Christian Ivicevic
  • 10,071
  • 7
  • 39
  • 74

6 Answers6

417

A non-static member function must be called with an object. That is, it always implicitly passes "this" pointer as its argument.

Because your std::function signature specifies that your function doesn't take any arguments (<void(void)>), you must bind the first (and the only) argument.

std::function<void(void)> f = std::bind(&Foo::doSomething, this);

If you want to bind a function with parameters, you need to specify placeholders:

using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, std::placeholders::_1, std::placeholders::_2);

Or, if your compiler supports C++11 lambdas:

std::function<void(int,int)> f = [=](int a, int b) {
    this->doSomethingArgs(a, b);
}

(I don't have a C++11 capable compiler at hand right now, so I can't check this one.)

plasmacel
  • 8,183
  • 7
  • 53
  • 101
Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 1
    As i am not dependant on boost i will use lambda expressions ;) Nevertheless thanks! – Christian Ivicevic Sep 28 '11 at 12:01
  • 3
    @AlexB : Boost.Bind doesn't use ADL for the placeholders, it puts them in an anonymous namespace. – ildjarn Sep 28 '11 at 16:34
  • 64
    I recommend to avoid global capture [=] and use [this] to make it clearer what is captured (Scott Meyers - Effective Modern C++ Chapter 6. item 31 - Avoid default capture modes) – Max Raskin Aug 29 '16 at 13:57
  • 7
    Just add a little tip: member function pointer can be implicitly cast to `std::function`, with extra `this` as it's first parameter, like `std::function = &Foo::doSomethingArgs` – landerlyoung Nov 25 '19 at 06:44
  • @landerlyoung: Add the name of the function say as "f" above to fix the sample syntax. If you don't need the name you could use mem_fn(&Foo::doSomethingArgs). – Val May 23 '20 at 20:41
  • To do this, ``` #include``` need. – Minwoo Yu Jan 25 '22 at 07:45
116

Either you need

std::function<void(Foo*)> f = &Foo::doSomething;

so that you can call it on any instance, or you need to bind a specific instance, for example this

std::function<void(void)> f = std::bind(&Foo::doSomething, this);
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
18

If you need to store a member function without the class instance, you can do something like this:

class MyClass
{
public:
    void MemberFunc(int value)
    {
      //do something
    }
};

// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);

// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);

What would the storage type look like without auto? Something like this:

std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable

You can also pass this function storage to a standard function binding

std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call

Past and future notes: An older interface std::mem_func existed, but has since been deprecated. A proposal exists, post C++17, to make pointer to member functions callable. This would be most welcome.

Greg
  • 1,181
  • 13
  • 13
  • @Danh `std::mem_fn` was **not** removed; a bunch of unnecessary overloads were. On the other hand `std::mem_fun` was deprecated with C++11 and will be removed with C++17. – Max Truxa Nov 03 '16 at 15:47
  • @Danh That's exactly what I'm talking about ;) The very first "basic" overload is still there: `template unspecified mem_fn(R T::*);`, and it won't go away. – Max Truxa Nov 03 '16 at 15:56
  • @Danh Read [the DR](https://cplusplus.github.io/LWG/lwg-defects.html#2048) carefully. 12 out of 13 overloads were removed by the DR. That last one *was not* (and won't be; neither in C++11 or C++14). – Max Truxa Nov 03 '16 at 16:01
  • 1
    Why the down vote? Every other response said you must bind the class instance. If you are creating a binding system for reflection or scripting, you will not want to do that. This alternative method is valid and relevant for some people. – Greg Nov 03 '16 at 23:06
  • Thanks Danh, I've edited with some comments about related past and future interfaces. – Greg Nov 07 '16 at 06:39
14

Unfortunately, C++ does not allow you to directly get a callable object referring to an object and one of its member functions. &Foo::doSomething gives you a "pointer to member function" which refers to the member function but not the associated object.

There are two ways around this, one is to use std::bind to bind the "pointer to member function" to the this pointer. The other is to use a lambda that captures the this pointer and calls the member function.

std::function<void(void)> f = std::bind(&Foo::doSomething, this);
std::function<void(void)> g = [this](){doSomething();};

I would prefer the latter.

With g++ at least binding a member function to this will result in an object three-pointers in size, assigning this to an std::function will result in dynamic memory allocation.

On the other hand, a lambda that captures this is only one pointer in size, assigning it to an std::function will not result in dynamic memory allocation with g++.

While I have not verified this with other compilers, I suspect similar results will be found there.

Ajay
  • 18,086
  • 12
  • 59
  • 105
plugwash
  • 9,724
  • 2
  • 38
  • 51
  • Both solutions are bad IMO. Bad in terms of it's too much code for something like this(I mean for C++, not you). It should be just: `std::function g = doSomething;` for a variable, and for a function that takes the std function as an argument: `void MyFunction(std::function callback);`, when we call it, we should be able to just do `MyFunction(doSomething);` and be done with it, instead of wrapping it in a lambda capturing this or std::bind, the `this` should be implied if other object is not provided(same as it is implied in functions already). – KulaGGin Oct 29 '22 at 10:29
  • And when we want to provide a different object for the member function, we should be able to just do `MyFunction({someOtherObject, doSomething});`. Less typing, often less lines, and easier to comprehend than std::bind or a capturing-this lambda. – KulaGGin Oct 29 '22 at 10:30
8

You can avoid std::bind doing this:

std::function<void(void)> f = [this]-> {Foo::doSomething();}
aggsol
  • 2,343
  • 1
  • 32
  • 49
1

You can use functors if you want a less generic and more precise control under the hood. Example with my win32 api to forward api message from a class to another class.

IListener.h

#include <windows.h>
class IListener { 
    public:
    virtual ~IListener() {}
    virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
};

Listener.h

#include "IListener.h"
template <typename D> class Listener : public IListener {
    public:
    typedef LRESULT (D::*WMFuncPtr)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

    private:
    D* _instance;
    WMFuncPtr _wmFuncPtr; 

    public:
    virtual ~Listener() {}
    virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override {
        return (_instance->*_wmFuncPtr)(hWnd, uMsg, wParam, lParam);
    }

    Listener(D* instance, WMFuncPtr wmFuncPtr) {
        _instance = instance;
        _wmFuncPtr = wmFuncPtr;
    }
};

Dispatcher.h

#include <map>
#include "Listener.h"

class Dispatcher {
    private:
        //Storage map for message/pointers
        std::map<UINT /*WM_MESSAGE*/, IListener*> _listeners; 

    public:
        virtual ~Dispatcher() { //clear the map }

        //Return a previously registered callable funtion pointer for uMsg.
        IListener* get(UINT uMsg) {
            typename std::map<UINT, IListener*>::iterator itEvt;
            if((itEvt = _listeners.find(uMsg)) == _listeners.end()) {
                return NULL;
            }
            return itEvt->second;
        }

        //Set a member function to receive message. 
        //Example Button->add<MyClass>(WM_COMMAND, this, &MyClass::myfunc);
        template <typename D> void add(UINT uMsg, D* instance, typename Listener<D>::WMFuncPtr wmFuncPtr) {
            _listeners[uMsg] = new Listener<D>(instance, wmFuncPtr);
        }

};

Usage principles

class Button {
    public:
    Dispatcher _dispatcher;
    //button window forward all received message to a listener
    LRESULT onMessage(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
        //to return a precise message like WM_CREATE, you have just
        //search it in the map.
        return _dispatcher[uMsg](hWnd, uMsg, w, l);
    }
};

class Myclass {
    Button _button;
    //the listener for Button messages
    LRESULT button_listener(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
        return 0;
    }

    //Register the listener for Button messages
    void initialize() {
        //now all message received from button are forwarded to button_listener function 
       _button._dispatcher.add(WM_CREATE, this, &Myclass::button_listener);
    }
};

Good luck and thank to all for sharing knowledge.