[英]When should I use remove_reference and add_reference?
我正在看[VC10的] unique_ptr,他們做了一些我不明白的事情:
typedef typename tr1::remove_reference<_Dx>::type _Dx_noref;
_Dx_noref& get_deleter()
{ // return reference to deleter
return (_Mydel);
}
unique_ptr(pointer _Ptr,
typename _If<tr1::is_reference<_Dx>::value, _Dx,
const typename tr1::remove_reference<_Dx>::type&>::_Type _Dt)
: _Mybase(_Ptr, _Dt)
{ // construct with pointer and (maybe const) deleter&
}
typename tr1::add_reference<_Ty>::type operator*() const
{ // return reference to object
return (*this->_Myptr);
}
不只是寫_Dx&或_Ty&是同一回事?
我實際上明白他們為什么在這里做到了:
unique_ptr(pointer _Ptr, typename tr1::remove_reference<_Dx>::type&& _Dt)
: _Mybase(_Ptr, _STD move(_Dt))
{ // construct by moving deleter
}
get_deleter
從返回類型中刪除任何引用,然后添加引用。 在符合C ++ 11的情況下,將&
添加到現有的&
(或&&
)會產生&
。 然而,在C ++ 03中,這將形成對引用類型的引用,這是非法的。 可能MSVC正在使用舊規則,或者代碼是在它執行時編寫的,因為它是無害的。
在這里,他們刪除引用,添加const
,然后添加引用,以便通過const
引用傳遞。 這是因為直接向引用類型添加const
什么都不做 ! (§8.3.2/ 1)在C ++ 11或C ++ 03中,參數聲明有效,但如果未刪除和替換引用,則不會添加const
。
operator*
這與get_deleter
基本相同,但它們以不同的方式進行,並且_Ty
不能作為開頭的引用類型。 它看起來像_Ty&
就足夠了,但這是他們的特權。
這里有一個例子,可能是原型,為什么我們需要remove_reference
,在std::move
的實現中:目標是根據推導出的函數參數類型返回一個rvalue-reference類型。
示例: Foo x; move(x);
Foo x; move(x);
這里move(x)
應該返回一個類型Foo&&
。 但是move
的論點是Foo&
類型的表達。 那么move
功能如何推導出正確的類型呢?
第一次嘗試是使用普通模板參數推導並使用強制轉換:
template <typename T> T && move(??? x) { return static_cast<T&&>(x); }
但應該怎么做???
? 如果我們說T x
,那么T
將被推斷為Foo&
; 如果我們說T & x
,那么T = Foo
,如果我們說T && x
,它將完全不匹配。 第二個版本T & x
似乎很有用。
但是這個函數在rvalues上不起作用(例如move(Foo(...))
。在這種情況下,我們想要T && x
使得T = Foo
和T&& = Foo&&
根據需要。我們可以有兩個重載,但有多個重載是不可取的,因為它不必要地增加了復雜性。最后,如果有人明確指定模板參數move<Foo&>(x)
,該函數將永遠不會工作,因為當T = Foo&
,則T&& = Foo&
以及。
所以來自remove_reference
:
template <typename T>
typename std::remove_reference<T>::type && move(T && x)
{
return static_cast<typename std::remove_reference<T>::type &&>(x);
}
首先,新的參考折疊規則意味着在兩種情況下T
被推斷為Foo&
或Foo&&
。 然后, remove_reference
剝離引用並在任何情況下給出類型Foo
,並添加&&
使得所需的Foo&&
返回類型。
在一個過於簡化的摘要中:我們需要remove_reference
因為(Foo&)&&
是Foo&
而不是Foo&&
。 如果您編寫的模板代碼需要模板參數的基本類型(可以推導為U&
或U&&
,則可以使用此模型。
template class add_reference
具有void
, const void
和const volatile void
因為不允許引用void type (void&)
。 如果使用_Ty&
,則在_Ty = void
時會產生編譯錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.