简体   繁体   English

为什么模板参数推导失败指针到成员函数?

[英]Why is template argument deduction failing for pointer-to-member-function?

With g++ 5.4, this 用g ++ 5.4,这个

struct B {
    void f() {}
}; 

struct D : public B {
    void g() {}
};

template <class T>
void foo(void (T::*)(), void (T::*)())
{}

int main()
{
    foo(&D::f, &D::g);
}

fails due to "deduced conflicting types for parameter 'T' ('B' and 'D')". 由于“推断出参数'T'('B'和'D')的冲突类型而失败”。 Why isn't T deduced as D, being an exact match? 为什么不将T推导为D,完全匹配?

The type of &D::f would be void ( B::* )(void) &D::f的类型将为void ( B::* )(void)

static_assert(::std::is_same<void ( B::* )(void), decltype(&D::f)>::value, "");
static_assert(::std::is_same<void ( D::* )(void), decltype(&D::f)>::value, ""); // error
static_assert(::std::is_same<void ( D::* )(void), decltype(&D::g)>::value, "");

The rationale behind this is that otherwise you won't be able to assign a value of &D::f to a variable of void ( B::* )(void) type without a cast even though f is a member of B or compare &D::f == &B::f . 这背后的基本原理是,即使fB的成员或比较,否则你将无法在没有强制转换的情况下将&D::f的值赋给void ( B::* )(void)类型的变量。 &D::f == &B::f

As a workaround you can perform a static_cast: 作为解决方法,您可以执行static_cast:

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

In addition to VTT 's excellent demonstration . 除了VTT的出色演示 The standard text in question, I believe, is at [expr.unary.op]/3 , emphasis mine: 我相信,有问题的标准文本是在[expr.unary.op] / 3 ,强调我的:

The result of the unary & operator is a pointer to its operand. 一元&运算符的结果是指向其操作数的指针。 The operand shall be an lvalue or a qualified-id. 操作数应为左值或限定ID。 If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m . 如果操作数是一个qualified-id,命名一个类型为T的某个类C的非静态或变体成员m,则结果类型为“指向类型为C的C类成员的指针”,并且是一个指定C ::的prvalue米

The qualified id you used is D::f , but it names a member function of B (I can bring up the lookup rules if you want). 您使用的限定ID是D::f ,但它命名为B的成员函数(如果需要,我可以调出查找规则)。 So the class type C in the above paragraph, is B . 所以上段中的类CB The type therefore resolves to void ( B::* )(void) . 因此该类型解析为void ( B::* )(void)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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