繁体   English   中英

无法将重载的函数指针转换为成员函数指针?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM