2014-03-07 74 views
9

對於以下的代碼:重載分辨率通用參考涉及

class A {}; 

template <typename T> void f(T& a) {} 
template <typename T> void f(T&& a) {} 

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

鐺++結合所述呼叫到所述第一過載,而克++報告曖昧呼叫。哪一個正在採取正確的行動?

回答

6

gcc 4.9.0 20140302和clang 3.5(trunk 202594)都正確選擇第一個版本。作爲hvd好心給我the references in comments

如果,對於給定類型,扣除成功在兩個方向上(即,類型是相同的上述轉換之後)並且兩個PA分別引用類型(與上面提到的類型被替換之前):
- 如果參數模板中的類型是左值引用,而參數模板中的類型不是,則參數類型被認爲比其他類型更專用;否則,
- 如果參數模板的類型比參數模板的類型更具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);只是期望。

+0

第一個版本,'T = A',第二個版本,'T = A&',都有一個'T&'類型的參數,所以你可以說什麼基礎是正確的第一個版本被選中? (我確實認爲你是對的,但你應該真的解釋你的答案。) – hvd

+0

@hvd是的,我想在bugzilla的標準/ gcc bugreport中找到相應的部分。 – Ali

+1

[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