有人可以帮助我理解为什么以下代码输出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 );
}
答案 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 -
S2
和S1
是引用绑定(8.5.3),引用所引用的类型是相同的类型除了顶级 cv-qualifiers,以及S2
初始化引用的类型 refer比参考的类型更符合cv 由S2
初始化引用。
如果修改示例,非模板重载具有与模板扣除的相同的顶级cv限定符(例如,通过从非模板中删除S1
cv限定符函数),它将导致先前由重载分辨率选择,。
const