Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use std::function to wrap non-static member function pointer

I have recently declared similar class to this:

class Foo {
public:
    void run();
private:
    void foo();
    void boo();
    void doo();
    std::function<void()>getFunction(int);
};

In this example I'd like to get pointer to the member function depending on the passed integer.

void Foo::run(){
    std::function<void()> f;
    for(int i = 0; i < 3; i++){
        f = getFunction(i);
        f();
    }
}

std::function<void()>Foo::getFunction(int i){
    switch(i){
        case 0: return foo;
        case 1: return Foo::boo;
        case 2: return this->*doo;
    }
}

All cases cause compiler errors. Adding static to function for case 1 works but I prefer not to use static members.

Is there any way to get these pointers properly without using static keyword?

like image 887
Giebut Avatar asked Feb 08 '26 03:02

Giebut


2 Answers

As an extension to songyuanyao's answer

What about using lambdas? (assuming it's only a matter of being able to call the internal functions and not the function pointers by themselves that are important)

void Foo::run(){
    std::function<void()> f;
    for(int i = 0; i < 3; i++){
        f = getFunction(i);
        f();
    }
}

std::function<void()> Foo::getFunction(int i) {
    switch(i){
        case 0: return [this](){this->foo();};
        case 1: return [this](){this->boo();}; 
        case 2: return [this](){this->doo();}; 
    }
}

LIVE3

like image 121
alefr Avatar answered Feb 09 '26 15:02

alefr


You need to bind an object to call non-static member function with it, in this case it's this. You can use std::bind,

std::function<void()> Foo::getFunction(int i) {
    switch(i){
        case 0: return std::bind(&Foo::foo, *this); // or std::bind(&Foo::foo, this)
        case 1: return std::bind(&Foo::boo, *this); // or std::bind(&Foo::boo, this)
        case 2: return std::bind(&Foo::doo, *this); // or std::bind(&Foo::doo, this)
    }
}

LIVE1

Or change std::function<void()> to std::function<void(Foo&)>, to match for non-static member function. Then

void Foo::run() {
    std::function<void(Foo&)> f;
    for(int i = 0; i < 3; i++) {
        f = getFunction(i);
        f(*this);
    }
}

std::function<void(Foo&)> Foo::getFunction(int i) {
    switch(i){
        case 0: return &Foo::foo;
        case 1: return &Foo::boo;
        case 2: return &Foo::doo;
    }
}

LIVE2

like image 35
songyuanyao Avatar answered Feb 09 '26 17:02

songyuanyao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!