一、SGI STL 的私房菜:__type_traits
__type_traits 负责萃取型别(type)的特性。此处所关注的型别特性是指:这个型别是否具备 non-trivial defalt ctor?是否具备 non-trivial copy ctor?是否具备 non-trivial assignment operator?是否具备 non-trivial dtor?如果答案是否定的,我们在对这个型别进行构造、析构、拷贝、赋值等操作时,就可以采用最有效率的措施,而采用内存直接处理操作,如malloc()、memcpy()等等,获得最高效率。
根据 iterator_traits 得来的经验,我们希望,程序之中可以这样运用 __type_traits<T>,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 值,应该是个有着真/假性质的“对象”,因为我们希望利用其响应结果来进行参数推导,而编译器只有面对 clas object 形式的参数才会做参数推导。为此,上述式子应该传回这样的东西:
struct __true_type { };
struct __false_type { };
为了达成上述五个式子,__type_traits 内必须定义一些 typedefs,其值不是 __true_type 就是 __false_type。下面是 SGI 的做法:
template <class type> struct __type_traits { typedef __true_type this_dummy_member_must_be_first; /* 不要移除这个成员。它通知"有能力自动将__type_traits特化" 的编译器说,我们现在所看到的这个__type_traits template 是特 殊的。这是为了确保万一编译器也使用一个名为__type_traits 而其 实与此处定义并无任何关联的template时,所有事情都仍将顺利运行 */ /* 以下条件应被遵守,因为编译器有可能自动为各型别产生专属的 __type_traits 特化版本: - 你可以重新排列以下的成员次序 - 你可以移除以下任何成员 - 绝对不可以将以下成员重新命名而却没有改变编译器中的对应名称 - 新加入的成员会被视为一般成员,除非你在编译器中加上适当支持 */ 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; };
上述 __type_traits 可以接受任何型别的参数,五个 typedefs 将经由一下管道获得实值:
1. 一般具现化,内含对所有型别都必定有效的保守值。
2. 经过声明的特化版本,例如<type_traits.h>内对所有 C++ 标量型别提供了对应的特化声明。
3. 某些编译器会自动为所有型别提供适当的特化版本。