[英]Cannot convert overloaded function pointer to member function pointer?
我有以下代码
class A
{
public:
int Key() const;
};
class B : public A
{};
template<class T, int (T::*MemFunction)() const>
class TT
{
public:
int Get() const {return (m_t.*MemFunction)();}
private:
T m_t;
};
TT<B, &B::Key> t; // Wrong, cannot convert overloaded function
// to int (T::*MemFunction)() (VS2010)
为什么以及如何以类似的方式起作用? 谢谢
答案已经由Billz提供,但是我将尝试给出一个解释。
在C ++中,当获得指向成员的指针时,表达式的结果不是指向表达式中存在的类型的成员的指针,而是指向定义该成员的类型的成员的指针。 也就是说,表达式&B::Key
产生&A::Key
,因为成员函数Key
是在A
定义的,而不是在B
定义的。 这在第5.3.1 / 3节中定义,虽然很难阅读,但附带一个示例:
一元&运算符的结果是指向其操作数的指针。 操作数应为左值或限定ID。 如果操作数是一个合格的ID,它用类型T命名某个类C的非静态成员m,则结果的类型为“指向类型T的类C的成员的指针”,并且是一个表示C :: m的前值。 否则,如果表达式的类型为T,则结果的类型为“指向T的指针”,并且是prvalue,它是指定对象(1.7)的地址或指向指定函数的指针。 [注意:特别是,类型为“ cv T”的对象的地址是“ cv T的指针”,具有相同的cv限定。 —尾注] [示例:
struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*
—结束示例]
这意味着您的模板实例化等效于:
TT<B, &A::Key>
虽然指向基础成员的成员的指针可以转换为派生类型的成员的指针,但对于非类型非模板模板参数的特定情况,不允许进行转换。 非类型非模板模板参数的转换在§14.3.2/ 5中定义,对于这种特殊情况,该状态指出:
对于成员函数类型指针的非类型模板参数,如果模板参数的类型为std :: nullptr_t,则应用空成员指针转换(4.11);否则,将转换为空成员指针。 否则,将不应用任何转换。
由于&A::Key
无法收敛为int (B::*)() const
,因此模板实例化格式不正确。 通过在模板实例化中添加强制类型转换,您将强制转换在实例化模板之前进行,并且该实例化变得有效,因为无需进行转换。
强制转换应使其起作用:
typedef int (B::*Key)() const;
TT<Key(&B::Key)> t;
t.Get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.