![](/img/trans.png)
[英]What's the difference between an ordinary rvalue reference and one returned by std::forward?
[英]What is the purpose of std::forward()'s rvalue reference overload?
我正在試驗完美轉發,我發現std::forward()
需要兩個重載:
超載編號 1:
template <typename T>
inline T&& forward(typename
std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
重載 nr.2:
template <typename T>
inline T&& forward(typename
std::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value,
"Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
現在完美轉發的典型場景是這樣的
template <typename T>
void wrapper(T&& e)
{
wrapped(forward<T>(e));
}
當然你知道當wrapper()
被實例化時, T
取決於傳遞給它的參數是左值還是右值。 如果它是U
類型的左值,則T
被推導為U&
。 如果是右值,則將T
推導為U
。
在任何情況下 - 在wrapper()
的范圍內 - e
是一個左值,因此它總是使用std::forward()
的第一個重載。
現在我的問題:
使用(並且需要)第二次重載的有效場景是什么?
N2951中詳細討論了forward
的設計原理。
本文檔列出了 6 個用例:
A.應該將左值作為左值轉發。 所有實現都通過了這個測試。 但這不是經典的完美轉發模式。 此測試的目的是表明實現 2 未能實現其防止除完美轉發之外的所有用例的既定目標。
B.應該將右值作為右值轉發。 與用例 A 一樣,這是一個身份轉換,這提供了一個需要身份轉換的激勵示例。
C.不應該轉發右值作為左值。 此用例展示了意外創建懸空引用的危險情況。
D.應該將較少的 cv 限定表達式轉發到更多 cv 限定的表達式。 一個激勵用例,涉及在轉發期間添加 const。
E.應該將派生類型的表達式轉發到可訪問的、明確的基類型。 一個激勵用例,涉及將派生類型轉發到基類型。
F.不應該轉發任意類型轉換。 此用例演示了前向中的任意轉換如何導致懸空引用運行時錯誤。
第二個重載啟用情況 B 和 C。
該論文繼續提供每個用例的示例,這些示例太長,無法在此重復。
更新
我剛剛通過這 6 個用例運行了第一個重載的“解決方案”,這個練習表明第二個重載也啟用了用例 F:不應轉發任意類型轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.