上篇文章介绍了内存分配器allocator的设计,此篇介绍内存分配器的属性。
__alloc_traits类
1,__alloc_traits类提供了一个顶层内存分配器的萃取器,可以使用_Alloc的allocate, dellocate, construct, destory等函数来完成内存分配、释放,对象构造、析构等任务。
2,其中特例化版本为allocator,是STL容器默认的内存分配器。
3,如果想将自定义的内存分配器融入到STL体系中,需要像allocator一样完成相应的接口设计,以及rebind函数,容器可通过模板赋值使用自定义的内存分配器。
__alloc_traits定义内存分配器中allocator_type,_Base_type,value_type,pointer,const_pointer,const_pointer,size_type,difference_type,reference,const_reference等类型定义,以及rebind<_Tp>重绑定模板类,construct, destory内存分配、释放模板函数,allocate, dellocate对象构造、析构函数,以及max_size函数。
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
template<typename _Alloc, typename = typename _Alloc::value_type>
struct __alloc_traits //模板类 __alloc_traits
: std::allocator_traits<_Alloc> //继承自allocator_traits,下面介绍
{ //类型定义
typedef _Alloc allocator_type; //内存分配器
typedef std::allocator_traits<_Alloc> _Base_type; //继承基类
typedef typename _Base_type::value_type value_type; //元素类型
typedef typename _Base_type::pointer pointer; //指针类型
typedef typename _Base_type::const_pointer const_pointer;
typedef typename _Base_type::size_type size_type;
typedef typename _Base_type::difference_type difference_type; //元素之间的距离
typedef value_type& reference; //左值引用类型
typedef const value_type& const_reference;
using _Base_type::allocate; //基类所有allocate重载函数在声明点处可见
using _Base_type::deallocate; //基类deallocate重载函数在声明点处可见
using _Base_type::construct; //基类construct重载函数在声明点处可见
using _Base_type::destroy; //基类destroy重载函数在声明点处可见
using _Base_type::max_size; //基类max_size重载函数在声明点处可见
private: //_Ptr与pointer类型相同,且不是标准类型指针时,__is_custom_pointer为true
template<typename _Ptr> //_Ptr是指向元素的自定义指针时为true
using __is_custom_pointer
= std::__and_<std::is_same<pointer, _Ptr>, //指针类型是否相同
std::__not_<std::is_pointer<_Ptr>>>; //是否为标准类型指针
public: //重载非标准类型指针的构造函数,标准指针会直接调用_Base_type的构造函数和析构函数
template<typename _Ptr, typename... _Args> //构造函数模板,模板参数为指针和构造类型所需参数
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type //返回为_Ptr或pointer
construct(_Alloc& __a, _Ptr __p, _Args&&... __args)
{ //调用基类构造函数construct
_Base_type::construct(__a, std::__to_address(__p),
std::forward<_Args>(__args)...);
}
template<typename _Ptr> //重载非标准类型指针的析构函数
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
destroy(_Alloc& __a, _Ptr __p)
{ _Base_type::destroy(__a, std::__to_address(__p)); }
//判断内存分配器是否包含拷贝、移动构造函数,交换及比较相等操作
//内存分配器中如果有相应成员函数则定义相应成员为true_type或false_type
//true_type::value为true,false_type::value为false
static constexpr bool _S_propagate_on_copy_assign()
{ return _Base_type::propagate_on_container_copy_assignment::value; }
static constexpr bool _S_propagate_on_move_assign()
{ return _Base_type::propagate_on_container_move_assignment::value; }
static constexpr bool _S_propagate_on_swap()
{ return _Base_type::propagate_on_container_swap::value; }
static constexpr bool _S_always_equal()
{ return _Base_type::is_always_equal::value; }
static constexpr bool _S_nothrow_move()
{ return _S_propagate_on_move_assign() || _S_always_equal(); }
template<typename _Tp>
struct rebind //基类rebind_alloc<_Tp>等于_Alloc<_Tp>,封装基类rebind定义_Alloc<_Tp>别名为other
{ typedef typename _Base_type::template rebind_alloc<_Tp> other; };
};
} // namespace __gnu_cxx
模板类allocator_traits类和__allocator_traits_base,获取内存分配器Alloc的属性,内存分配器不一定是std::allocator,可以是自定义的。
以及内存分配器std::allocator的属性萃取
namespace std _GLIBCXX_VISIBILITY(default)
{
struct __allocator_traits_base
{ //_Tp没有rebind成员函数时,调用此版本__rebind,成员type类型为_Tp<_Up>
template<typename _Tp, typename _Up, typename = void> //类模板,继承自__replace_first_arg
struct __rebind : __replace_first_arg<_Tp, _Up> { }; //__replace_first_arg中type成员类型为_Tp<_Up>
template<typename _Tp, typename _Up> //模板类特例化版本,_Tp有rebind成员函数时,调用此版本
struct __rebind<_Tp, _Up,
__void_t<typename _Tp::template rebind<_Up>::other>>
{ using type = typename _Tp::template rebind<_Up>::other; }; //声明成员type类型为_Tp<_Up>的别名
protected: //类型别名,_Tp为内存分配器
template<typename _Tp>
using __pointer = typename _Tp::pointer; //指针类型
template<typename _Tp>
using __c_pointer = typename _Tp::const_pointer;
template<typename _Tp>
using __v_pointer = typename _Tp::void_pointer;
template<typename _Tp>
using __cv_pointer = typename _Tp::const_void_pointer;
template<typename _Tp> //以下在_Tp中如果有相应成员函数则定义相应成员为true_type或false_type
using __pocca = typename _Tp::propagate_on_container_copy_assignment; //_Tp下成员
template<typename _Tp>
using __pocma = typename _Tp::propagate_on_container_move_assignment; //_Tp下成员
template<typename _Tp>
using __pocs = typename _Tp::propagate_on_container_swap; //_Tp下成员
template<typename _Tp>
using __equal = typename _Tp::is_always_equal; //_Tp下成员
}; //__allocator_traits_base
template<typename _Alloc, typename _Up> //声明__alloc_rebind为模板类__rebind中成员type的别名
using __alloc_rebind //模板类__allocator_traits_base下成员type在该声明点处可见
= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
//类allocator_traits,继承__allocator_traits_base,获取内存分配器的属性
template<typename _Alloc>
struct allocator_traits : __allocator_traits_base
{
typedef _Alloc allocator_type; //内存分配器
typedef typename _Alloc::value_type value_type; //内存分配的类型
//__detected_or_t<>等于__pointer<_Alloc>即_Alloc::pointer
//内存分配器_Alloc下无__pointer定义时,使用value_type*作为指针类型pointer
using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
private: //模板类,声明_Ptr成员type类型
//当pointer为标准指针类型时,pointer_traits<pointer>::rebind<_Tp>等于_Tp*
//当不为标准指针类型时,pointer_traits<pointer>::rebind<_Tp>等于__rebind<pointer,_Tp>::type
//在__allocator_traits_base中__rebind<pointer,_Tp>的成员type为pointer<_Tp>
//pointer<_Tp>即__detected_or_t<value_type*, __pointer, _Tp>
template<template<typename> class _Func, typename _Tp, typename = void>
struct _Ptr
{ using type = typename pointer_traits<pointer>::template rebind<_Tp>; }; //type为指针类型
template<template<typename> class _Func, typename _Tp> //模板类特例化版本
struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> //_Func为模板类,可接受内存分配器作为模板实参
{ using type = _Func<_Alloc>; }; //_Func<_Alloc>获取type类型
//模板类,声明_Diff下type为_A2::difference_type或pointer_traits<_Ptr>::difference_type
template<typename _A2, typename _PtrT, typename = void>
struct _Diff
{ using type = typename pointer_traits<_PtrT>::difference_type; };
template<typename _A2, typename _PtrT>
struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
{ using type = typename _A2::difference_type; };
//声明_Size下type为_A2::size_type or make_unsigned<_DiffT>::type
template<typename _A2, typename _DiffT, typename = void>
struct _Size : make_unsigned<_DiffT> { };
template<typename _A2, typename _DiffT>
struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
{ using type = typename _A2::size_type; };
public: //类型别名
using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; //_Ptr下成员type
using void_pointer = typename _Ptr<__v_pointer, void>::type;
using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
using difference_type = typename _Diff<_Alloc, pointer>::type; //_Diff下成员type
using size_type = typename _Size<_Alloc, difference_type>::type; //_Size下成员type
//__detected_or_t返回__pocca<_Alloc>的定义,若_Alloc下无__pocca定义则返回false_type
//__pocca<_Alloc>为_Alloc::propagate_on_container_copy_assignment
using propagate_on_container_copy_assignment
= __detected_or_t<false_type, __pocca, _Alloc>;
using propagate_on_container_move_assignment
= __detected_or_t<false_type, __pocma, _Alloc>;
using propagate_on_container_swap
= __detected_or_t<false_type, __pocs, _Alloc>;
using is_always_equal
= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
template<typename _Tp> //重新封装__alloc_rebind,rebind_alloc<_Tp>为_Alloc<_Tp>
using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
template<typename _Tp> //重新封装allocator_traits,萃取_Alloc<_Tp>的属性
using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
//以下省略allocate、deallocate、construct、destroy、max_size
}; //allocator_traits
//_Alloc为allocator的特例化版本
template<typename _Tp>
struct allocator_traits<allocator<_Tp>>
{
using allocator_type = allocator<_Tp>;
using value_type = _Tp;
using pointer = _Tp*;
using const_pointer = const _Tp*;
using void_pointer = void*;
using const_void_pointer = const void*;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using propagate_on_container_copy_assignment = false_type;
using propagate_on_container_move_assignment = true_type;
using propagate_on_container_swap = false_type;
using is_always_equal = true_type;
template<typename _Up> //_Up的内存分配器allocator<_Up>
using rebind_alloc = allocator<_Up>;
template<typename _Up>//allocator<_Up>的属性萃取allocator_traits<_Up>
using rebind_traits = allocator_traits<allocator<_Up>>;
//以下封装allocator<_Tp>的成员函数
static pointer
allocate(allocator_type& __a, size_type __n)
{ return __a.allocate(__n); }
static pointer
allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
{ return __a.allocate(__n, __hint); }
static void
deallocate(allocator_type& __a, pointer __p, size_type __n)
{ __a.deallocate(__p, __n); }
template<typename _Up, typename... _Args>
static void
construct(allocator_type& __a, _Up* __p, _Args&&... __args)
{ __a.construct(__p, std::forward<_Args>(__args)...); }
template<typename _Up>
static void
destroy(allocator_type& __a, _Up* __p)
{ __a.destroy(__p); }
static size_type
max_size(const allocator_type& __a) noexcept
{ return __a.max_size(); }
static allocator_type
select_on_container_copy_construction(const allocator_type& __rhs)
{ return __rhs; }
}; //allocator_traits<allocator<_Tp>>
} // namespace std