“类型萃取器”__type_traits

iterator_traits负责萃取迭代器的五种特性,__type_traits则负责萃取类型特性,即某种类型是否具有琐碎无意义(trivial)的构造函数或复制控制,即POD类型。

__type_traits定义于中:
struct __true_type {
};
 
struct __false_type {
};

template 
struct __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;
};


默认情况下,认为所有类型都为non-trivial,下面再给出内置类型的特化版本,如:
__STL_TEMPLATE_NULL struct __type_traits {
   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;
};


这里,就认为char类型具有trivial的构造和复制控制。注意,这些嵌套类型要么返回 __true_type类型,要么返回__false_type类型,根据类型不同而编译时期确定该调用哪个版本的函数。

下面来看看__type_traits的应用。
template 
inline ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n,
                                            const T& x) {
  return __uninitialized_fill_n(first, n, x, value_type(first));
}

此全局函数从迭代器first开始,在未初始化的空间内填充n个元素,值为x。

首先来分析函数value_type:
template 
inline typename iterator_traits::value_type*
value_type(const Iterator&) { // 决定迭代器value_type
  return static_cast::value_type*>(0);
}


它首先利用iterator_traits获得迭代器所指类型的value_type,然后返回这个value_type的指针。

template 
inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n,
                                              const T& x, T1*) {
  typedef typename __type_traits::is_POD_type is_POD;
  return __uninitialized_fill_n_aux(first, n, x, is_POD());
                                     
}


函数__uninitialized_fill_n接受到这个指针后,利用__type_traits机制来判断T1是否是POD类型。

如果是POD类型,is_POD()应该生成一个临时对象——__true_type,然后调用对应的重载函数:
template 
inline ForwardIterator
__uninitialized_fill_n_aux(ForwardIterator first, Size n,
                           const T& x, __true_type) {
  return fill_n(first, n, x);
}


STL算法fill_n直接对first指向的内存逐一赋值,因为是POD类型。

如果不是POD类型,is_POD()应该生成一个临时对象——__false_type,然后调用对应的重载函数:
template 
ForwardIterator
__uninitialized_fill_n_aux(ForwardIterator first, Size n,
                           const T& x, __false_type) {
  ForwardIterator cur = first;
  __STL_TRY {
    for ( ; n > 0; --n, ++cur)
      construct(&*cur, x);
    return cur;
  }
  __STL_UNWIND(destroy(first, cur));
}


调用全局函数construct(),对每个位置使用构造函数来进行初始化。

从上面的例子可以看出,__type_traits的目的就是要提取出某种类型的特性:has_trivial_default_constructor?
has_trivial_copy_constructor?
...
然后再根据这些特性选择效率最高的函数进行调用,是性能达到最大优化。

参考:
《STL源码剖析》 P103.

你可能感兴趣的:(C++)