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
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With