我正在看[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&amp;或_Ty&amp;是一回事吗?
我确实理解他们为什么在这里做到了:
unique_ptr(pointer _Ptr, typename tr1::remove_reference<_Dx>::type&& _Dt)
: _Mybase(_Ptr, _STD move(_Dt))
{ // construct by moving deleter
}
答案 0 :(得分:14)
get_deleter
从返回类型中删除任何引用,然后添加引用。在符合C ++ 11的情况下,向现有&
(或&
)添加&&
会产生&
。然而,在C ++ 03中,这将形成对引用类型的引用,这是非法的。可能MSVC正在使用旧规则,或者代码是在它执行时编写的,因为它是无害的。
在这里,他们删除引用,添加const
,然后添加引用,以便通过const
引用。这是因为直接向引用类型添加const
nothing ! (§8.3.2/ 1)在C ++ 11或C ++ 03中,参数声明有效,但如果未删除和替换引用,则不会添加const
。
operator*
这与get_deleter
基本相同,但它们以不同的方式进行,_Ty
不能作为参考类型开始。在我看来,_Ty&
就足够了,但这是他们的特权。
答案 1 :(得分:3)
这是一个示例,可能是原型,为什么我们需要remove_reference
,在std::move
的实现中:目标是返回一个基于推导的rvalue-reference类型函数参数的类型。
示例: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&&
),则可以使用此模型。
答案 2 :(得分:1)
template class add_reference
专门针对void
,const void
和const volatile void
,因为不允许引用void type (void&)
。如果使用_Ty&
,则会在_Ty = void
时生成编译错误。