本文原创
traits 是用于在编译期进行特性提取的技术,type_traits 在 STL 中用于判定模板形参类型,以此针对不同类型执行不同的实现。
type_traits.h 文件注释中就提供了一个例子说明其用途:
// Copy an array of elements which have non-trivial copy constructors template <class T> void copy(T* source, T* destination, int n, __false_type); // Copy an array of elements which have trivial copy constructors. Use memcpy. template <class T> void copy(T* source, T* destination, int n, __true_type); // Copy an array of any type by using the most efficient copy mechanism template <class T> inline void copy(T* source, T* destination, int n) { copy(source, destination, n, typename __type_traits<T>::has_trivial_copy_constructor()); }
最下面一个 copy 是对外被调用的,利用 __type_traits 判定类型 T 是否有默认的拷贝构造函数,根据判定结果选择调用上面两个 copy 中的一个,以此针对某些类型提供高效的特殊实现。
__true_type 和 __false_type 都是一个空的结构体,先来看看 __type_traits 的一般模板:
struct __true_type { }; struct __false_type { }; template <class _Tp> struct __type_traits { typedef __true_type this_dummy_member_must_be_first; /* Do not remove this member. It informs a compiler which automatically specializes __type_traits that this __type_traits template is special. It just makes sure that things work if an implementation is using a template called __type_traits for something unrelated. */ /* The following restrictions should be observed for the sake of compilers which automatically produce type specific specializations of this class: - You may reorder the members below if you wish - You may remove any of the members below if you wish - You must not rename members without making the corresponding name change in the compiler - Members you add will be treated like regular members unless you add the appropriate support in the compiler. */ 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; };
关于 POD 类型,解释如下:
A type that consists of nothing but Plain Old Data. A POD type is a C++ type that has an equivalent in C, and that uses the same rules as C uses for initialization, copying, layout, and addressing.
“An aggregate is an array or class with no user-declared constructors, no private or protected non-static data members, no base classes and no virtual functions.”
“A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-define copy operator and no user-defined destructor.”
一般模板默认类型无 trivial constructor 和 trivial destructor 等,也不是 POD 类型。这里的 trivial constructor 表示无用户自定义的构造函数,由编译器生成默认的构造函数,而且该类无虚基类,类中无虚函数。
随后,针对各种内置类型对模板做了全局特化,包括 bool, char, unsigned char, short, unsigned short, int, unsigned int, wchar_t, long, unsigned long, long long, unsigned long long, float, double, long double,形式都一样:
template <> struct __type_traits<bool> { 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_CLASS_PARTIAL_SPECIALIZATION,则还对指针类型作了局部特化:
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION template <class _Tp> struct __type_traits<_Tp*> { 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; }; #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ ...... #endif
如果没声明该宏,则上述 …… 处对类型 char *, unsigned char *, const char *, const unsigned char * 做了和其他内置类型同样的全局特化。
type_traits.h 文件中还有一个判断类型是不是整型或可转换为整型的 _Is_integer 的模板,一般模板置否:
template <class _Tp> struct _Is_integer { typedef __false_type _Integral; };
对于可转换为整型的类型 bool, char, unsigned char, short, unsigned short, int, unsigned int, wchar_t, long, unsigned long, long long, unsigned long long,作类似以下的全局特化:
template <> struct _Is_integer<bool> { typedef __true_type _Integral; };