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

时间:2017-11-09 12:03:00

标签: c++ templates argument-deduction

使用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,是完全匹配?

2 个答案:

答案 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::fvoid ( 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的成员函数(如果需要,我可以调出查找规则)。因此,上一段中的类类型CB。因此,该类型解析为void ( B::* )(void)