将超类函数作为非类型名模板参数传递

Fab*_*era 8 c++ templates

假设你有

  struct A{
  void f(){}
};


struct B:public A{
};


template<typename C,void (C::*f)()>
struct Call{

  void operator()(C* c){
    (c->*f)();
  }
};
Run Code Online (Sandbox Code Playgroud)

为什么

int main(){
  void (B::*f)()=&B::f;    
}
Run Code Online (Sandbox Code Playgroud)

工作但是

 Call<B,&B::f> a;
Run Code Online (Sandbox Code Playgroud)

没有,抱怨

could not convert template argument ‘&A::f’ to ‘void (B::*)()
Run Code Online (Sandbox Code Playgroud)

(Call<A,&A::f>显然有效)

以类似的方式

const void (B::*f)()=&B::f;
Run Code Online (Sandbox Code Playgroud)

cannot convert ‘void (A::*)()’ to ‘const void (B::*)()’ in initialization
Run Code Online (Sandbox Code Playgroud)

use*_*672 4

void (B::*f)()=&B::f;   \n
Run Code Online (Sandbox Code Playgroud)\n\n

之所以有效,是因为隐式转换来自

\n\n
void (A::*f)() \n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
void (B::*f)()\n
Run Code Online (Sandbox Code Playgroud)\n\n

被申请;被应用。

\n\n

\n4.11 (2)

\n\n

\xe2\x80\x9c 类型的纯右值,指向 cv T\xe2\x80\x9d 类型的 B 成员,其中 B 是类类型,可以转换为 \n\n\xe2\x80\x9c 类型的纯右值,指向 cv T\xe2\x80\x9d 类型的成员D 类型为 cv T\xe2\x80\x9d,其中 D 是 B 的派生类(第 10 条)。\n

\n\n

但是,该标准不允许对模板参数中的成员函数指针进行任何转换,除了 nullptr_t 转换:

\n\n

\n14.3.2

\n\n

对于指向成员函数的指针类型的非类型模板参数,如果模板参数的类型为 std::nullptr_t,则应用空成员指针转换 (4.11);否则,不进行任何转换\n。如果模板参数表示一组重载成员函数,则从该组\n中选择匹配的成员函数(13.4)。\n

\n