这个成员转换指针有什么问题?

时间:2013-12-04 13:55:11

标签: c++ c++11

这段代码有什么问题?由于这个答案,我以为我可以转换:

Is it safe to "upcast" a method pointer and use it with base class pointer?

struct B
{
  void f(){}
};

struct D : B
{
  virtual ~D(){}
};

template <typename FP, FP fp>
void g()
{
}

int main()
{
  g<void (D::*)(), &B::f>();
  return 0;
}

错误:

t.cpp:18:27: error: could not convert template argument '&B::f' to 'void (D::*)()'
   g<void (D::*)(), &B::f>();

这也不起作用:

g<void (D::*)(), static_cast<void (D::*)()>(&B::f)>();

1 个答案:

答案 0 :(得分:4)

标准不允许这样做(C ++ 11,[temp.arg.nontype]§5):

  

对用作非类型模板参数的每个表达式执行以下转换。如果非类型 template-argument 无法转换为类型相应的模板参数然后程序格式不正确。

     

...

     
      
  • 对于指向成员函数的类型指针的非类型 template-parameter ,如果 template-argument 的类型为std::nullptr_t,则为null成员指针转换(4.11)适用; 否则,不适用转化。如果template-argument表示一组重载的成员函数,则从集合中选择匹配的成员函数(13.4)。
  •   

(强调我的)

由于[temp.arg.nontype]§1:

也不允许强制转换

  

非类型非模板模板参数 template-argument 应为以下之一:

     

...

     
      
  • 指向成员的指针,如5.3.1所述。
  •   

5.3.1§4的内容为:

  

只有在使用显式&并且其操作数是 qualified-id 未括在括号中时,才会形成指向成员的指针。

这结合起来说不允许使用强制转换作为非类型模板参数。

因此,尽管在运行时可以进行此类转换,但似乎无法将它们用作模板参数。