對於以下的代碼:重載分辨率通用參考涉及
class A {};
template <typename T> void f(T& a) {}
template <typename T> void f(T&& a) {}
int main() {
A a;
f(a);
}
鐺++結合所述呼叫到所述第一過載,而克++報告曖昧呼叫。哪一個正在採取正確的行動?
對於以下的代碼:重載分辨率通用參考涉及
class A {};
template <typename T> void f(T& a) {}
template <typename T> void f(T&& a) {}
int main() {
A a;
f(a);
}
鐺++結合所述呼叫到所述第一過載,而克++報告曖昧呼叫。哪一個正在採取正確的行動?
gcc 4.9.0 20140302和clang 3.5(trunk 202594)都正確選擇第一個版本。作爲hvd好心給我the references in comments:
這是一個微妙的問題,有a defect report,
gcc的實施之前4.9實施早期缺陷,見Template overload resolution ambiguous for T&&
versus T&
中的相應部分標準爲14.8.2.4 [temp.deduct.partial],第9段:
如果,對於給定類型,扣除成功在兩個方向上(即,類型是相同的上述轉換之後)並且兩個
P
和A
分別引用類型(與上面提到的類型被替換之前):
- 如果參數模板中的類型是左值引用,而參數模板中的類型不是,則參數類型被認爲比其他類型更專用;否則,
- 如果參數模板的類型比參數模板的類型更具cv限定(如上所述),則參數類型被認爲比另一個更專用;否則,
- 兩種類型都比另一種更專業。
順便說一句,看The Universal Reference/Overloading Collision Conundrum視頻爲什麼普遍引用超載是一個壞主意。總之,考慮下面的例子:
#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;
}
如果你運行該程序,將打印
T&&
Guts stolen? true
這是不是在所有你通過看A a{ false }; f(a);
只是期望。
第一個版本,'T = A',第二個版本,'T = A&',都有一個'T&'類型的參數,所以你可以說什麼基礎是正確的第一個版本被選中? (我確實認爲你是對的,但你應該真的解釋你的答案。) – hvd
@hvd是的,我想在bugzilla的標準/ gcc bugreport中找到相應的部分。 – Ali
[Here](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164)和[here](http://gcc.gnu.org/bugzilla/show_bug。 cgi?id = 57172):) – hvd