Search code examples
c++refactoringstdbind

How can I avoid this code duplication?


I have two methods which have almost the same code except for two methods they call (and some other details I can easily parameterize). However, those method calls have the same signature, so I think I can generalize them into a single method.

class A{
    IApi* m_pApi;
    void M1();
    void M2();
public:
    void DoThings();
}

void A::M1(){
    int i;
    bool b;    
    m_pApi->method1( &i, &b );    
    //Other stuff...
}

void A::M2(){
    int i;
    bool b;    
    m_pApi->method2( &i, &b );
    //Other stuff...
}

void A::DoThings(){
    M1();
    M2();
}

I can figure out how to "parameterize" the "Other stuff" code, but the problem are the calls to method1 and method2. I think I have to use std::bind somehow, but I can't do something like this...

void A::M( std::function<void(int*,bool*)> f ){
    int i;
    bool b;
    f( &i, &b );
}

void A::DoThings(){
    M( std::bind( ???, m_pApi ) ); //M1
    M( std::bind( ???, m_pApi ) ); //M2
}

The problem here is that m_pApi is not a concrete class (it's an interface implemented by a bunch of concrete classes), so I'm not sure if I can do the usual &Class::Method thing. Suggestions?


Solution

  • Use pointers to member function.

    #include <iostream>
    using namespace std;
    
    struct IApi {
        void method1(int * i, bool * b) {
            *i = 1; *b = true;
        }
        void method2(int * i, bool * b) {
            *i = 2; *b = false;
        }
    };
    
    class A {
        IApi* m_pApi;
        void M(void (IApi::*)(int*, bool*));
    public:
        A() : m_pApi(new IApi()) {}
        void DoThings();
    };
    
    void A::M(void (IApi::*mptr)(int*, bool*)) {
        int i;
        bool b;    
        (m_pApi->*mptr)( &i, &b );    
        cout << i << ' ' << b << endl;
    }
    
    void A::DoThings(){
        M(&IApi::method1);
        M(&IApi::method2);
    }
    
    int main() {
        A a;
        a.DoThings();
    }