STL源码剖析 __type_traits

  • traits编程 弥补了C++本身的不足
  • STL只对迭代器进行规范制定出了iterator_traits,SGI在此基础上进一步扩展,产生了__type_traits
  • 双下划线的含义是这个是SGI内部使用的东西,不属于STL标准
  • iterator_traits 负责萃取迭代器的特性
  • __type_traits负责萃取型别特性。比如是否具备non-trivial default ctor? non-trivial copy ctor?non-trivial assignment operator?non-trivial dtor? 如果答案是否定的,就可以对这个型别进行构造、析构、拷贝、赋值等操作时,采取最有效率的措施.
  • 比如 根本不调用身居高位的constructor、destructor,直接进行内存层面上的操作,比如malloc()、memcpy()等等,进一步提高效率
  • __type_traits 允许针对不同的型别属性在编译时期完成函数的派送指定。这对于撰写模板很有帮助,比如对一个元素型别未知的数组进行copy操作的时候,如果事先知道元素的型别是否有一个trivial copy constructor,就可以帮助函数确定是否可以使用memcpy() 或者 memmove()
  • 根据iterator_traits的经验,程序应该采用如下的方式使用__type_traits  其中T代表任意的型别
__type_traits<T>::has_trivial_default_constructor
__type_traits<T>::has_trivial_copy_constructor
__type_traits<T>::has_trivial_assignment_operator
__type_traits<T>::has_trivial_destructor
__type_traits<T>::is_POD_type
  • 上述的公式 响应真或者假,从而函数决定采用什么样的处理策略。但是不仅仅是一个bool数值,而应该是一个具备真假性质的对象。因为需要利用它的响应结果来进行参数的推导,而编译器只会对具备class object形式的参数才会进行类型的推导
  • 因此,上述公式应该返回的是 如下的形式,这两个空白的classes没有任何的成员,不会带来额外的负担,但是能表明真假,满足需求
struct __true_type{};
struct __false_type{};
  • 为了满足上述的式子,__type_traits必须定义一些typedef ,其类型不是__true_type,就是__false_type
  • 下面是SGI的做法
struct __true_type{};
struct __false_type{};

template <class type>
struct __type_traits{
    /*
     * 不要移除这个成员,他通知"有能力自动将__type_traits特化"的编译器说,现在的
     * 这个__type_traits是特殊的,确保万一编译器也使用一个__type_traits而其实
     * 与此处定义并没有任何关联的模板的时候,不出现错误
     */
    typedef __true_type this_dummy_member_must_be_first;
    
    /*
     * 遵守以下的约定,因为编译器有可能自动为各个型别产生专属的__type_traits
     * 特化版本
     *    1,可以重新排列以下成员的次序
     *    2,不可以删除以下成员
     *    3,绝对不可以将以下成员重新命名,但是没有改变编译器中对应的名称
     *    4,新加入的成员视为一般成员,除非你在编译器中加上适当的支持
     */
    typedef __false_type has_trivial_default_constructor;
    typedef __false_type has_trivial_copy_constructor;
    typedef __false_type has_trivial_assignment_operator;
    typedef __false_type has_trivial_destructor;
    typedef __false_type is_POD_type;
};
  • 将所有的内嵌型别都定义为__false_type,默认是最为保守的数值。
  • 随后可以根据每一个标量类型设计适当的__type_traits的特化版本

特化版本

  • 以下针对C++基本型别char \ signed char \ unsigned char \ short \ unsigned short \ int  \ unsigned int \ long  \ unsigned long \ float \ double \ long double 提供了特化版本,每一个的成员数值都是true_type,即这些型别都可以采用最快速的方式(例如 memcpy) 进行拷贝 或者 赋值操作
  • SGI STL<stl_config.h> 将以下出现的__STL_TEMPLATE_NULL d定义为template<> ,是所谓的class template explicit specialization
template<>
struct __type_traits<char>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<signed char>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<unsigned char>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<short>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<unsigned short>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<int>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<unsigned int>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<long>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<unsigned long>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<float>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<double>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<>
struct __type_traits<long double>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};

template<class T>
struct __type_traits<T*>{
    typedef __true_type has_trivial_default_constructor;
    typedef __true_type has_trivial_copy_constructor;
    typedef __true_type has_trivial_assignment_operator;
    typedef __true_type has_trivial_destructor;
    typedef __true_type is_POD_type;
};
  • 以上内容均将__STL_TEMPLATE_NULL 替换为 template <> 

  • type_traits在SGI STL中使用很广泛 例如:uninitialized_fill_n()全局函数、destroy()函数、copy()函数 (STL源码剖析110页),他们的思想都是一样的,分为泛型和偏特化两种模式,进行切换
  • 一个class什么时候应该有自己的 non-trivial default ctor? non-trivial copy ctor?non-trivial assignment operator?non-trivial dtor?简单的判断准则是,如果这个类内含指针成员,并且对它进行内存动态配置,那么这个类就需要自己实现 non trivial XXX,即上述内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值