假设有一个接收universal references的模板函数foo,定义如下:

template<typename T>void foo(T&& t)
{
    cout << "foo(T&& t)" << endl;
}

 如果想对某些类型做特殊处理,写一个重载版本的foo,比如想对float类型做特殊处理,就写一个接收float类型的foo:

void foo(float n)
{
    cout << "foo(float n)" << endl;
}

这样,如果我们写下 foo(1.0) 时,理论上应该输出"foo(float n)",而实际上输出结果为"foo(T&& t)"。为什么呢?因为“Functions taking universal reference are the greediest functions in C++”,也就是说universal reference的函数能准确匹配几乎所有的类型。当我们调用foo(1.0)时,1.0被推导为double类型,如果调用foo(float n),就需要做narrow conversion,所以编译器会认为foo(T&& t)为更准确的匹配,除非我们写下foo(1.f)时,才会调用foo(float)。只有在类型完全准确匹配时,才会调用重载版本,否则编译器会始终认为universal reference版本为准确匹配。

这个问题在类继承中会更为隐晦,假设有一个名为Base的class,Base有一个接收universal reference的模板构造函数,定义如下:

网友评论