Passing a superclass function as non typename template parameter
c++, templates
Solution
void (B::*f)()=&B::f;
works because implicit conversion from
void (A::*f)()
to
void (B::*f)()
is applied.
4.11 (2)
A prvalue of type “pointer to member of B of type cv T”, where B is a class type, can be converted to a prvalue of type “pointer to member of D of type cv T”, where D is a derived class (Clause 10) of B.
However, the standard doesn't allow any conversions for pointer to member function in template arguments except of nullptr_t conversion:
14.3.2
For a non-type template-parameter of type pointer to member function, if the template-argument is of type std::nullptr_t, the null member pointer conversion (4.11) is applied; otherwise, no conversions apply. If the template-argument represents a set of overloaded member functions, the matching member function is selected from the set (13.4).
Problem
Suppose you have ``` struct A{ void f(){} }; struct B:public A{ }; template<typename C,void (C::*f)()> struct Call{ void operator()(C* c){ (c->*f)(); } }; ``` why does ``` int main(){ void (B::*f)()=&B::f; } ``` work but ``` Call<B,&B::f> a; ``` doesn't, complaining ``` could not convert template argument ‘&A::f’ to ‘void (B::*)() ``` ? (`Call<A,&A::f>` clearly works) In a similar way ``` const void (B::*f)()=&B::f; ``` gives ``` cannot convert ‘void (A::*)()’ to ‘const void (B::*)()’ in initialization ```