涉及通用参考的过载分辨率

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 ++报告模糊调用.哪一个采取了正确的行动?

Ali*_*Ali 6

gcc 4.9.0 20140302和clang 3.5(trunk 202594)都正确选择了第一个版本.正如hvd友好地给了我评论中的参考:

如果,对于给定类型,扣除成功在两个方向上(即,类型是上述变换后相同的)和二者PA分别引用类型(与上面提到的类型被替换之前):
-如果从参数模板的类型是一个左值引用,参数模板中的类型不是,参数类型被认为比另一个更专业; 否则,
- 如果参数模板中的类型比参数模板中的类型更具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);.