2015-03-13 19 views
1

看着斯科特·邁耶的有效的現代C++頁200-201的std::forward建議簡化的實現可以是(沒有看到其他地方的正確實施):在std :: forward中它如何接受右值?

template <typename T> 
T&& forward(std::remove_reference_t<T>& param) 
{ return static_cast<T&&>(param); } 

而接受右值的Widget時,就變成了:

Widget&& forward(Widget& param) 
{ return static_cast<Widget&&>(param); } 

現在,如果你採取取代代碼,然後執行:

struct Widget { }; 

Widget&& forward(Widget& param) 
{ return static_cast<Widget&&>(param); } 

template <typename T> 
void G(T&& uref) 
{ } 

template <typename T> 
void F(T&& uref) 
{ G(forward(uref)); } 

int main() 
{ 
    Widget x; 
    F(std::move(x)); 
} 

什麼我不能包裹我的頭,並沒有看到SO的直接答案是:in forward參數Widget& param如何設法從F()接受Widget&&通常GCC-5.0會抱怨像這樣與非模板代碼:

error: invalid initialization of non-const reference of type ‘Widget&’ from an rvalue of type ‘std::remove_reference::type {aka Widget}’

Question #27501400幾乎接觸的話題,但不太它顯示標準爲同時具有左值&和右值& &版本。)

+5

命名的右值引用是左值;真正的價值被一個單獨的過載所接受。 – 2015-03-13 20:30:29

+0

@ T.C。這正是我所忽略的一面,謝謝。 – JasonM 2015-03-13 20:40:38

+1

如果它有一個名字,那是一個左值。所以'uref'是一個左值。 – 2015-03-13 21:13:04

回答

0

"Named rvalue references are lvalues",

所以示例工作正常,如註釋中所述。

儘管如此您的代碼可被修改以

template <typename T> 
void F(T && uref) 
{ 
    G(forward(move(uref))); 
} 

由另一超負荷接受(比較):

template<typename T> 
T && forward(typename std::remove_reference<T>::type & t) 
{ 
    return static_cast<T &&>(t); 
} 


template<typename T> 
T && forward(typename std::remove_reference<T>::type && t) 
{ 
    static_assert(!std::is_lvalue_reference<T>::value, "T is an lvalue reference"); 
    return static_cast<T &&>(t); 
} 

第二過載將用於右值。它適用於TWidgetWidget &&,並且斷言失敗Widget &

+0

爲什麼要傳遞一個右值到'std :: forward'? – 0x499602D2 2015-06-06 03:18:36

+0

@ 0x499602D2可能是意外。如果你這樣做,你會得到一個static_assert錯誤。 – 2015-09-29 13:06:45

相關問題