Resolve const and non-const member function pointer

Viewed 483

In the below code snippet, I want to be able to call A::foo from doWork.

However because there are two overloads of foo( const and non-const ), compiler is unable to resolve which one I mean in call of doWork. Is there a way to tell compiler that I meant which one.

I cannot change struct A.

Can I do something in signature of doWork or call of doWork to always pick say the const one.

One solution I know is to give function pointer type as argument of doWork instead of the template(like this) void doWork(void (A::*fun)(void) const){ But this is little ugly and I wish to find a template based solution(if one exists)

struct A{
    void foo() const {
    }
    void foo(){
    }
    void bar(){
    }
    void bar() const {
    }
};

template<typename F>
void doWork(F fun){
    const A a;
    (a.*fun)();
}

int main()
{
    doWork(&A::foo); //error: no matching function for call to ‘doWork()’
    doWork(&A::bar); // error: no matching function for call to ‘doWork()’
    return 0;
}
2 Answers

You can use static_cast to specify which one should be used.

static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type, as in

std::for_each(files.begin(), files.end(),
              static_cast<std::ostream&(*)(std::ostream&)>(std::flush));

e.g.

doWork(static_cast<void (A::*)(void) const>(&A::foo));
doWork(static_cast<void (A::*)(void) const>(&A::bar));

Or specify the template argument explicitly.

doWork<void (A::*)(void) const>(&A::foo);
doWork<void (A::*)(void) const>(&A::bar);

You may use:

template <typename T>
void doWork(void (T::*fun)() const){
    const A a;
    (a.*fun)();
}

A more generic function template would use const T a.

template <typename T>
void doWork(void (T::*fun)() const){
    const T a;
    (a.*fun)();
}

Note that the second version does not assume A anywhere.

Related