简体   繁体   中英

std::function with non-static member functions

i'm trying to understand a concept and an error. what's wrong with this?

class A
{
public:
    A()
    {
        std::function<void(int)> testFunc(&A::func);
    }

private:
    void func(int) {}
}

my question, is it possible to create any sort of object that is able to call a member of a specific instance where std::function acts like a member function pointer, except without the wacky type definition that can't be used as function parameters in inheriting classes. for example:

class A
{
public:
    A()
    {
         index[WM_CREATE] = &A::close;
         index[WM_DESTROY] = &A::destroy;
    }

protected:
    map<UINT msg, void (A::*)(HWND, UINT , WPARAM, LPARAM)> index;
    void close(HWND,UINT, WPARAM, LPARAM);
    void destroy(HWND, UINT, WPARAM, LPARAM);
};

class B : public A
{
public:
    B()
    {
        index[WM_CREATE] = &B::create; // error because it's not a pointer of type A::*
    }
private:
    void create(HWND, UINT, WPARAM, LPARAM);

};

I'm thinking i'm on the right track of using std::functions like so:

class A
{
public:             //         Gigantic stl error with these two
    A()             //                         |
    {               //                         V
         index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::close);
         index[WM_DESTROY] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::destroy);
    }

protected:
    map<UINT msg, std::function<void(HWND, UINT, WPARAM, LPARAM)> > index;
    void close(HWND,UINT, WPARAM, LPARAM);
    void destroy(HWND, UINT, WPARAM, LPARAM);
};

class B : public A
{
public:                    //               and this one
    B()                    //                     |
    {                      //                     V
        index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM)>(&B::create);
    }
private:
    void create(HWND, UINT, WPARAM, LPARAM);

};

if someone could explain what these giant cryptic errors mean and how to fix them, i would greatly appreciate it.

I think the problem you are having is that a member function requires not only a function pointer, but a pointer to the calling object. In other words, member functions have an additional implicit argument that is the pointer to the calling object.

To set a member function to a std::function, you need to use std::bind like this:

std::function<void(int)> testFunc(std::bind(&A::func, this, _1));

This binds the this pointer of the current A instance to the function so it has the function pointer and the object instance, which is enough information to properly call the function. The _1 argument indicates that the first explicit argument will be provided when the function is called.

With c++11 you can also use lambdas which are slightly easier to read than std::bind :

index[WM_CREATE] = [this](HWND h, UINT u, WPARAM w, LPARAM l)
{
  create(h, u, w, l);
}

my question, is it possible to create any sort of object that is able to call a member of a specific instance

In this case the only information that is missing is in fact what specific instance the std::function object should use: &A::func can't be used on its own (for instance (this->*&A::func)(0) uses &A::func with instance *this ). Try:

std::function<void(int)> testFunc = std::bind(&A::func, this);

(Be careful that std::bind(&A::func, *this) and std::bind(&A::func, this) have slightly different semantics.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM