lancegerday
lancegerday

Reputation: 762

Issues with templated methods used with templated function pointer to an inherited method

I can't seem to figure out what is going on with a particular templated method.

A similar templated method has been in my codebase for a while now and has been used in an identical manner as Bar::Bar(IFoo&), the only difference being that the function being passed in is inherited.

I have an interface IFoo which defines the templated function in question.

struct IFoo {
    template<class T>
    void doSomething(bool (T::*method)(int), T *instance) {
        std::cout << (instance->*method)(5) << "\n";
    }
};

I have a class Bar which is a child of another class

struct Parent {
    virtual bool setValue(int a) { return true; }
};
struct Bar : Parent { };

When I try to use IFoo::doSomething the compiler just doesn't see the matching function

int main() {
    Bar b;
    IFoo foo;
    foo.doSomething(&Bar::setValue, &b);
}

I get the following compiler message
error: no matching function for call to 'IFoo::doSomething(bool (Parent::*)(int), Bar*)'

What I'm really surprised about is that I don't get a candidate suggestion that for the templated IFoo::doSomething function.

C++98 solutions only please.

Upvotes: 2

Views: 59

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122228

As the error says, the type of Bar::setValue is actually bool (Parent::*)(int). This interferes with the template parameter deduction for doSomething because it has two Ts that need to be the same. You can help the compiler with the deduction by casting this:

int main() {
    Bar b;
    IFoo foo;
    foo.doSomething(&Bar::setValue, static_cast<Parent*>(&b));
}

Live Demo

Thanks to JVApen for pointing out that alternatively you can make doSomething more generic by allowing two different types and let Callback do the conversion:

template<class T, class U>
void doSomething(bool (T::*method)(int), U *instance);

Upvotes: 2

Related Questions