使用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);
}
由于&#34;推断出参数'T'('B'和'D')&#34;的冲突类型,失败。为什么不推断为D,是完全匹配?
答案 0 :(得分:13)
&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, "");
这背后的基本原理是,即使&D::f
是void ( B::* )(void)
,您仍然无法将f
的值分配给B
类型的变量,而无法进行投射&D::f == &B::f
成员或比较foo(static_cast<void (D::*)(void)>(&D::f), &D::g);
。
作为一种解决方法,您可以执行static_cast:
<ngx-slider
[(ngModel)]="globalYearSelection"
[step]="1"
[filled]="false"
[min]="1990"
[max]="2015"
(change)="onChangeYear($event.value)">
</ngx-slider>
答案 1 :(得分:12)
除VTT's excellent demonstration之外。我相信标准文本是[expr.unary.op]/3,强调我的:
一元&amp;的结果operator是指向其操作数的指针。该 操作数应为左值或限定ID。 如果操作数是 qualified-id命名某个C类的非静态或变体成员 对于类型T,结果具有类型“指向类C的成员的指针 T“并且是指定C :: m 的prvalue。
您使用的限定ID是D::f
,但它命名为B
的成员函数(如果需要,我可以调出查找规则)。因此,上一段中的类类型C
为B
。因此,该类型解析为void ( B::* )(void)
。