With g++ 5.4, this
struct B {
void f() {}
};
struct D : public B {
void g() {}
};
template <class T>
void foo(void (T::*)(), void (T::*)())
{}
int main()
{
foo(&D::f, &D::g);
}
fails due to "deduced conflicting types for parameter ‘T’ (‘B’ and ‘D’)". Why isn't T deduced as D, being an exact match?
In addition to VTT's excellent demonstration. The standard text in question, I believe, is at [expr.unary.op]/3, emphasis mine:
The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C::m.
The qualified id you used is D::f
, but it names a member function of B
(I can bring up the lookup rules if you want). So the class type C
in the above paragraph, is B
. The type therefore resolves to void ( B::* )(void)
.