- 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,即上述内容