2017-10-04 63 views
4

foo是函數:理解型扣除普遍引用

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

什麼類型將T推斷爲foo以下呼叫:

foo(0); // is T here int or int&& ? 

int a = 0; 
foo(a); // is T here int or int& ? 
+1

您可以通過使用不同類型的特徵,如HTTP嘗試:// EN。 cppreference.com/w/cpp/types/is_reference或std :: is_same ..並用std :: add_lvalue_reference之類的東西建立類型,然後看看這些特徵的值是什麼 – xaxxon

+0

下面是一個例子,所以你可以看到一種方式自己測試一下:https://wandbox.org/permlink/51APJ9Pr4fsweWrF – xaxxon

+2

這裏有一個調試類型的技巧:'template class TD;',然後在foo中使用:'TD ();'。由於'TD'沒有定義,編譯器會發出抱怨,並且在錯誤消息中,一個好的編譯器會顯示'T'的類型。 – geza

回答

5

的類型推演默認規則參考類型永遠不可能是扣除的結果。給定此代碼,

template <class T> 
void bar(T par); 

bar(0); 
int a; 
bar(a); 
int &b; 
bar(b); 

所有3個電話將呼叫foo<int>。也就是說,T推導爲intpar的類型爲int

轉發的引用通過簡單添加一個規則的工作:當用於一個轉發參考的類型扣(即,參數T&&的用於推導T)參數是X類型的左值,類型X &用於代替X進行扣除。

請注意,這意味着給定類型X,只有XX &可以是類型扣除的結果; X &&永遠不會。

讓我們來分析你的代碼(我將重新命名,他功能參數,使之清楚,我指):

template <class T> 
void foo(T &&par); 

foo(0); 

int a; 
foo(a); 

在第一種情況下foo(0),參數是int類型的右值因此使用類型int來進行類型推斷,這意味着T被推導爲int(被稱爲的函數是foo<int>)並且par的類型是int &&

在第二種情況foo(a)中,自變量是類型int。轉發參考規則將啓動並使用類型int &進行推導。 T因此推導爲int &(函數名爲foo<int&>),並且par的類型爲「int & &&」,其摺疊爲int &

1

foo(0); //是T這裏是int還是int & &?

int

int a = 0; (a); //是T這裏int還是int &?

一個int&

1

像您

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

什麼在推斷上下文表達T&&即T的基礎上,提供的參數推斷,是受 reference collapsing rules

總之;

  • 如果所提供的參數是一個左值type類型的T&& 將擴大到type& &&坍塌到type&

  • 如果所提供的參數是type類型的右值T&& 將展開至type &&,摺疊至type&&

注意,兩者都是引用,如果你需要觸發另一個函數的右值 超載,你需要做的std::forward<T>(a)