[英]Why is template argument deduction failing for pointer-to-member-function?
用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);
}
由于“推断出参数'T'('B'和'D')的冲突类型而失败”。 为什么不将T推导为D,完全匹配?
&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, "");
这背后的基本原理是,即使f
是B
的成员或比较,否则你将无法在没有强制转换的情况下将&D::f
的值赋给void ( B::* )(void)
类型的变量。 &D::f == &B::f
。
作为解决方法,您可以执行static_cast:
foo(static_cast<void (D::*)(void)>(&D::f), &D::g);
除了VTT的出色演示 。 我相信,有问题的标准文本是在[expr.unary.op] / 3 ,强调我的:
一元&运算符的结果是指向其操作数的指针。 操作数应为左值或限定ID。 如果操作数是一个qualified-id,命名一个类型为T的某个类C的非静态或变体成员m,则结果类型为“指向类型为C的C类成员的指针”,并且是一个指定C ::的prvalue米
您使用的限定ID是D::f
,但它命名为B
的成员函数(如果需要,我可以调出查找规则)。 所以上段中的类C
是B
因此该类型解析为void ( B::* )(void)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.