Nfys
Nfys

Reputation: 804

C++ - Pass member function to member object with std::function

I am trying to pass a member function object to a member object but I am getting the following error in VS 2013:

error C2664: 'void std::_Func_class<_Ret,>::_Set(std::_Func_base<_Ret,> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,> *'

Here's the code:

#include <iostream>
#include <functional>

class Bar {
public:
    Bar(){};
    Bar(std::function<void(void)> funct_) : funct(funct_){}

    void setFunct(std::function<void(void)> funct_){
        funct = funct_;
    }
    void run(){
        for (int k = 0; k < 10; k++)
            funct();
    };
    std::function<void(void)> funct;

};

class Foo{
public:
    Foo(){
        bar.setFunct(&Foo::printSimpleFoo);
    }

    void printSimpleFoo(){
        std::cout << "Hello World" << std::endl;
    }

    void start(){
        bar.run();
    }

private:
    Bar bar;
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo foo;
    foo.start();

    system("pause");
    return 0;
}

So I want Bar to be able to take an arbitrary function with the specific signature, i.e. void(void) from its parent object and the call it in its run() member function (which will be called by the parent's start() member function)

I have looked into similar questions. Many suggest using std::mem_fn but when it is not clear to me how to use it in this setting (where the function has to be passed to different object).

Upvotes: 0

Views: 154

Answers (1)

James Adkison
James Adkison

Reputation: 9602

The desired function signature is void (*)(void) however the signature of printSimpleFoo is void (Foo::*)(void).

You can use std::bind to capture the object instance. The object instance is necessary because you cannot call a member function with the associated object instance. The std::bind essentially stores the object instance so that the function has the appropriate signature.

bar.setFunct(std::bind(&Foo::printSimpleFoo, this));

Example Code

#include <iostream>
#include <functional>

class Bar
{
public:
    Bar() {}

    Bar(std::function<void(void)> funct_) : funct(funct_) {}

    void setFunct(std::function<void(void)> funct_)
    {
        funct = funct_;
    }

    void run()
    {
        for (int k = 0; k < 10; ++k)
        {
            funct();
        }
    };

    std::function<void(void)> funct;
};

class Foo
{
public:
    Foo()
    {
        bar.setFunct(std::bind(&Foo::printSimpleFoo, this));
    }

    void printSimpleFoo()
    {
        std::cout << "Hello World\n";
    }

    void start()
    {
        bar.run();
    }

private:
    Bar bar;
};

int main()
{
    Foo foo;
    foo.start();

    return 0;
}

Example Code Output

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

Live Example

Upvotes: 1

Related Questions