2017-02-09 71 views
2

請考慮下面的代碼:類型不推導爲r值參考:爲什麼不呢?

class CMyClass {}; 

template<class T> 
void func(T&& param) { 
     if (std::is_same<CMyClass, std::decay<T>::type>::value) 
      std::cout << "param is a CMyClass\n"; 
     if (std::is_same<T, CMyClass&>::value) 
      std::cout << "param is a CMyClass reference\n"; 
     else if (std::is_same<T, CMyClass&&>::value) 
      std::cout << "param is a CMyClass r-value reference\n"; 
     else if (std::is_same<T, const CMyClass&>::value) 
      std::cout << "param is a const CMyClass reference\n"; 
     else if (std::is_same<T, const CMyClass&&>::value) 
      std::cout << "param is a const CMyClass r-value reference\n"; 
     else if (std::is_same<T, const CMyClass>::value) 
      std::cout << "param is a constant CMyClass\n"; 
     else if (std::is_same<T, CMyClass>::value) 
      std::cout << "param is a CMyClass\n"; 
     else 
      std::cout << "param is not a CMyClass\n"; 
} 


CMyClass mc3; 
func(std::move(mc3)); 

從這個小程序的輸出

param is a CMyClass 
param is a CMyClass 

爲什麼MC3的類型不被推斷爲R值的參考嗎?

+1

related/dupe:http://stackoverflow.com/questions/16373881/why-forwarding-reference-does-not-deduce-to-rvalue-reference-in-case-of-rvalue – NathanOliver

+0

_「爲什麼有請問mc3的類型是否被推斷爲r值參考?「_因爲它不是一個? –

+1

你的代碼檢查'T'的類型,但是然後打印出一個關於'param'類型的謊言。 'param'的類型是'T &&'不''T,所以你的程序在於。現在,你需要用什麼類型來代替'T'來使'T &&'等於'CMyClass &&'?那麼什麼是'T'? –

回答

6

我不能找到一個很好的欺騙,即使一個必須存在的地方,對不起。

扣除規則:

template <class T> 
void foo(T&&) 
在呼叫 foo(expr)的上下文

是:

  • 如果exprU類型的左值,然後T推導爲U&T&&類型由於引用崩潰,所以是U&
  • 如果exprU類型的右值,然後T推導作爲U類型T&&U&&,由於引用塌陷。

在您的示例中,std::move(mc3)是類型CMyClass的右值(具體爲xvalue)。因此,T被推斷爲CMyClass。此檢查:

else if (std::is_same<T, CMyClass&&>::value) 
    std::cout << "param is a CMyClass r-value reference\n"; 

T絕不會演繹出作爲右值引用類型幾乎從來不會是真實的。它可以具體提供如下:

func<CMyClass&&>(std::move(mc3)); 

但這是不太可能的用法。你可以做什麼,而不是檢查:

else if (std::is_same<T&&, CMyClass&&>::value) 
//     ~~~~ 

這將處理的所有情況下,參數是一個右值。事實上,如果你只是總是檢查T&&,那將正確處理你的所有情況。

+0

)在第二個項目符號中,你也以「由於引用崩潰」而結束......但是,沒有任何崩潰(只涉及一個'&&'應用程序)? –

3

爲什麼mc3的類型未被推斷爲r值參考?

如果param右值T非參考內部func,和T&&右值參考。下面是根據經驗示出了什麼T指在函數體,需要一個轉發參考一個例子:

template <typename T> 
void func(T&& x) 
{ 
    std::is_same<T, something>{}; // (0) 
    std::is_same<T&&, something>{}; // (1) 
} 

(0)的情況下:

  • TT右值傳遞給func(*)
  • TT&左值被傳遞到func爲。

(1)的情況下:

  • T&&T&&右值被傳遞給func
  • T&&T&左值被傳遞給func

如果使用std::is_same<T&&, CMyClass>::value,您應該得到一個T&T&&


(*):注意,術語 「是」 是不正確的 - 的Tfunc不同含義取決於template argument deductionreference collapsing

簡而言之:

  • T推導爲:

    • T&如果x左值

    • T否則。

  • 由於參考塌陷T&&是:

    • T&如果x左值T& && - >T&

    • T&&否則。 T&& && - >T&&

+0

@EdgarRokyan對於* prvalues *來說是正確的,但我認爲它被推導爲'T &&'* xvalues *。儘管如此,我會修改我的答案,提到*引用崩潰*正在發生。 –

+2

「T」是什麼意思在「()'的背景下推導出來的?這條線沒有扣除。 – Barry

+0

@Barry:將'something'改爲'std :: is_same'。我想說的是,'func'主體內的'T'和'T &&'的「含義」會根據推導出的T以及引用崩潰的效果而改變。顯然在術語方面有問題 –