STL源码剖析(二)__alloc_traits特性

上篇文章介绍了内存分配器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
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值