goo*_*era 9 c++ gcc clang language-lawyer c++11
对于以下代码:
class A {};
template <typename T> void f(T& a) {}
template <typename T> void f(T&& a) {}
int main() {
A a;
f(a);
}
Run Code Online (Sandbox Code Playgroud)
clang ++将调用绑定到第一个重载,而g ++报告模糊调用.哪一个采取了正确的行动?
gcc 4.9.0 20140302和clang 3.5(trunk 202594)都正确选择了第一个版本.正如hvd友好地给了我评论中的参考:
这是一个微妙的问题,有一个缺陷报告,
4.9之前的gcc实现实现了早期的缺陷,请参阅 模板重载解析T&&对于模式的不明确T&
标准中的相应部分是14.8.2.4 [temp.deduct.partial],第9段:
如果,对于给定类型,扣除成功在两个方向上(即,类型是上述变换后相同的)和二者
P并A分别引用类型(与上面提到的类型被替换之前):
-如果从参数模板的类型是一个左值引用,参数模板中的类型不是,参数类型被认为比另一个更专业; 否则,
- 如果参数模板中的类型比参数模板中的类型更具cv限定(如上所述),则认为参数类型比另一个更专业; 否则,
- 两种类型都不比另一种更专业.
顺便说一句,观看通用参考/重载碰撞难题视频为什么超载通用参考是一个坏主意.简而言之,请考虑以下示例:
#include <iostream>
#include <utility>
struct A { bool guts_stolen; };
void steal_guts(A&& a) {
a.guts_stolen = true;
}
template <typename T> void f(const T& a) {
// ^^^^^ note the const!
std::cout << "T&\n";
}
template <typename T> void f(T&& a) {
std::cout << "T&&\n";
steal_guts(std::move(a));
}
int main() {
A a{ false };
f(a);
std::cout << "Guts stolen? " << std::boolalpha << a.guts_stolen << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果您运行该程序,它将打印
T&&
Guts stolen? true
Run Code Online (Sandbox Code Playgroud)
这完全不是你期望的那样A a{ false }; f(a);.