Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind one of member functions of the same name in a class, with c++11 std::bind

Tags:

c++

c++11

class Test{
public:

    int work(){
        cout << "in work " << endl;
        return 0;
    }

    void work(int x){
        //cout << "x = " << x << endl;
        cout << "in work..." << endl;
    }
};  

int main(){
    Test test;
    std::function<void()> f = std::bind(&Test::work, &test);
    thread th(f);
    th.join();
    return 0;
}

As above code, I want to bind member function void work(void) of a class (let's name it Test) , but occurs compiler error saying that can not determine which overrided function to use.

I can not change class Test since it belongs to a lib, how to achieve my goal? Thanks in advance!

like image 299
debugman Avatar asked Nov 05 '15 09:11

debugman


4 Answers

Why don't skip std::bind altogether and use a lambda?

auto fp = [&t]() { t.test()};

As a bonus, your executable size will be smaller and your compiler has much easier time to inline the code if appropriate.

like image 184
TheROE Avatar answered Nov 02 '22 15:11

TheROE


When deducing the template arguments to bind, the compiler is not in a context that allows function overload resolution - to be simplistic about it, it hasn't got that far yet.

Having deduced that the first argument is indeed the name of a member function pointer, it finds that there are two functions of the same name but of different types.

At this stage, they're both equally valid candidates (from the point of template argument deduction), therefore it's ambiguous

A static cast disambiguates because we're pushing the compiler beyond the stage where it has to deduce a template type - we have taken on the responsibility to template type deduction ourselves - by specifying the type in the static_cast.

So now all it has to do is overload resolution.

#include <functional>
#include <thread>
#include <iostream>

using namespace std;

class Test{
public:

    int work(){
        cout << "in work " << endl;
        return 0;
    }

    void work(int x){
        //cout << "x = " << x << endl;
        cout << "in work..." << endl;
    }
};

int main(){
    Test test;

    // only overload resolution required here 
    auto fp = static_cast<int (Test::*)()>(&Test::work);

    // type is now unambiguous and overload resolution is already done
    std::function<void()> f = std::bind(fp, &test);

    thread th(f);
    th.join();
    return 0;
}
like image 43
Richard Hodges Avatar answered Nov 02 '22 14:11

Richard Hodges


By casting it to the correct type:

std::function<void()> f = std::bind( static_cast<int (Test::*)()>(&Test::work), &test);
like image 4
jrok Avatar answered Nov 02 '22 15:11

jrok


try this(member function ptr):

int main(){
    Test test;
    typedef int(Test:: *WKPtr)(void);
    WKPtr p = &Test::work;
    std::function<int()> f = std::bind(p, &test);
    f();
    return 0;
}
like image 1
user2986683 Avatar answered Nov 02 '22 13:11

user2986683