2011-11-29 50 views
5

_Remove_reference存在,如你所知,轉換牛逼&到T或T & &到T.爲什麼std :: move()不能在沒有_Remove_reference的情況下工作?

我做了一個好玩的心情下面的代碼,這是行不通的,因爲我希望所有,但都沒有想法爲什麼。

template<class _Ty> 
struct _Remove_reference 
{ // remove reference 
    typedef _Ty _Type; 
    static void func(){ cout << "1" << endl; } 
}; 

// template<class _Ty> 
// struct _Remove_reference<_Ty&> 
// { // remove reference 
// typedef _Ty _Type; 
// static void func(){ cout << "2" << endl; } 
// }; 
// 
// template<class _Ty> 
// struct _Remove_reference<_Ty&&> 
// { // remove rvalue reference 
// typedef _Ty _Type; 
// static void func(){ cout << "3" << endl; } 
// }; 

template<class _Ty> inline 
    typename _Remove_reference<_Ty>::_Type&& 
    move(_Ty&& _Arg) 
{ // forward _Arg as movable 
    typename _Remove_reference<_Ty>::func(); 
    return ((typename _Remove_reference<_Ty>::_Type&&)_Arg); 
} 

int main(){ 
    int a1= 3; 
    int&& a2 = move(a1); // can't convert the a1 to int&& 
    return 0; 
} 

我想這是關於引用崩潰規則和模板參數的演繹,但我很困惑。我對此的好奇心已經被打破,讓我睡得很緊。

在此先感謝。

回答

8

鑑於

template<class _Ty> inline 
typename _Remove_reference<_Ty>::_Type&& 
move(_Ty&& _Arg) 

當你這樣做move(a1)_Ty推導爲int&_Ty&&將因此仍然int&由於參考崩潰規則,所以你需要刪除提及得到int之前,你可以把它的右值引用。

這是模板參數推導規則的特例。如果函數參數是T&&,其中T是模板參數,那麼如果將左值(即命名對象或左值引用)傳遞給該函數,則T被推導爲X&,其中X是左值對象的類型。如果你傳遞一個右值(臨時值或右值參考)給函數,那麼T就是推導爲X

例如move(a1)演繹_Tyint&,而move(42)演繹_Tyint

BTW:我想你從你的編譯器的標準庫把這個代碼---飾有一個前導下劃線和一個大寫字母_Like _this名是留給編譯器和標準庫的實現。

+0

謝謝。我很感激。但想知道爲什麼我需要取消註釋代碼?如果_remove_reference的目的是將它們轉換爲T,爲什麼我需要這些模板專門化版本? –

+1

專長是'_Remove_reference'如何工作。主模板匹配任何東西,並返回相同的類型,所以'_Remove_reference :: type'就是'int'。參考文獻的部分專業化進行參考刪除。 '_Remove_reference '匹配第一個部分特化,所以用來代替主模板。 **在這個專門化**中,'_Ty'只是'int'(所以'_Ty&'是'int&'),所以'_Remove_reference :: type'是一個int類型定義。 –

+1

關於引用崩潰,請參閱http://thbecker.net/articles/rvalue_references/section_08.html。實際上,從第1頁開始,整篇文章就是一個很好的解讀。從一開始就閱讀以獲取事物的上下文。 – wilhelmtell

相關問題