转发引用的绑定优先级

时间:2017-10-29 05:37:14

标签: c++ templates c++14 forwarding-reference

有人可以帮助我理解为什么以下代码输出T&&而不是const A&

class A{};

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


void foo( const A& )
{
   std::cout << "const A&" << std::endl;
}


int main()
{
  A a;
  foo( a );
}

1 个答案:

答案 0 :(得分:2)

[temp.deduct.call]/1 & 3 [强调我的]:

  

<强> / 1

     

通过比较每个函数来完成模板参数推导   包含的模板参数类型(称为P)   参与模板参数推导的模板参数   与调用的相应参数的类型(称为A)   如下所述。 ...

     

<强> / 3

     

...转发引用是对cv-nonqualified的右值引用   模板参数,不代表a的模板参数   类模板(在类模板参数推导期间   ([over.match.class.deduct]))。 如果P是转发参考而且   参数是左值,使用类型“A的左值引用”   A的类型扣除地点

     

[示例:

...
template <class T> int f(T&& heisenreference);
int i;
int n1 = f(i);                  // calls f<int&>(int&)
...
     

- 结束示例]

应用于您的示例,foo(a)调用将针对模板参数扣除,解析为void foo<A&>(A&),这与cv-nonqualified左值a完全匹配。非模板函数void foo(const A&)[over.ics.rank]/3.2.6(感谢@MM更正消除这两个歧义的排名规则),提供比模板扣除的更差的转换序列,{{1}将在重载决策中具有优先权。

  

<强> /3.2

     

标准转换序列void foo<A&>(A&)是一个比转换序列更好的转换序列   标准转换序列S1 if

     
      
  • ...

  •   
  • /3.2.6 - S2S1是引用绑定(8.5.3),引用所引用的类型是相同的类型除了顶级   cv-qualifiers,以及S2初始化引用的类型   refer比参考的类型更符合cv   由S2初始化引用。

  •   

如果修改示例,非模板重载具有与模板扣除的相同的顶级cv限定符(例如,通过从非模板中删除S1 cv限定符函数),它将导致先前由重载分辨率选择,。

const