前言
继续看stl中常用东西的源码,打算把智能指针的坑给填了,这次先写点unique_prt,下次写shared_ptr。unique_prt的代码总体而言比较简单,唯一稍微复杂的地方就是对自定义析构函数的萃取。
STL版本
本文所使用的stl版本为libc++ 13.0,属于LLVM项目。
如果遇到不熟悉的宏定义可以参考文档Symbol Visibility Macros
Unique_ptr
依照惯例,来看一下定义的模板参数和一些typedef。
template <class _Tp, class _Dp = default_delete<_Tp> >
class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
public:
typedef _Tp element_type;
typedef _Dp deleter_type;
typedef _LIBCPP_NODEBUG_TYPE typename __pointer<_Tp, deleter_type>::type pointer; //萃取是否有自定义的指针类型
static_assert(!is_rvalue_reference<deleter_type>::value,
"the specified deleter type cannot be an rvalue reference");
private:
__compressed_pair<pointer, deleter_type> __ptr_;
第一个模板参数_Tp是我们要定义智能指针存储对象的类型,第二个模板参数_Dp则是析构函数的类型。默认的default_delete<_Tp>使用的是直接delete指针的方式。
__compressed_pair则是存储原始指针和析构函数的地方,具体我们稍后再说,先把大体看一遍,
__point是一个类型萃取,源码如下,简单来说就是pointer则是对_Dp进行类型萃取,判断_Dp是否自己定义了自己的point,如_Dp中定义了typedef point xxx,会萃取这个xxx。如果没有就会为_Tp*。
#define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(NAME, PROPERTY) \
template <class _Tp, class = void> struct NAME : false_type {
}; \
template <class _Tp> struct NAME<_Tp, typename __void_t<typename _Tp:: PROPERTY >::type> : true_type {
}
// __pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer);
template <class _Tp, class _Alloc,
class _RawAlloc = typename remove_reference<_Alloc>::type,
bool = __has_pointer<_RawAlloc>::value>
struct __pointer {
using type _LIBCPP_NODEBUG_TYPE = typename _RawAlloc::pointer;
};
template <class _Tp, class _Alloc, class _RawAlloc>
struct __pointer<_Tp, _Alloc, _RawAlloc, false> {
using type _LIBCPP_NODEBUG_TYPE = _Tp*;
};
不难看出,__pointer根据第四个模板参数进行选择性的特化,第四个模板参数__has_pointer是利用sfinae进行判断是否存