STL源码笔记之型别提取技法(2)

1.iterator_category

    (1)Input Iterator:这种迭代器所指的对象,不允许外接改变,只读。    

    (2)Output Iterator:只写。

    (3)Forward Iterator:允许“写入型”算法在此迭代器所形成的区间上进行读写操作。

    (4)Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间,可使用Bidirectional Iterator。

    (5)Random Access Iterator:前四种迭代器只提供一部分指针的能力(前三种只支持operator++,operator--),第五种涵盖所有指针算术能力。包括p+n、p-n、p[n]、p1-p2,p1<p2。

      为了能够提供编译迭代器动态选择,STL定义了五种标记用的型别,这样我们在调用涉及到迭代器的函数时,就能选择符合相应迭代器特性的函数。五个迭代器分别为:

                  struct input_iterator_tag{};

                  struct output_iterator_tag{};

                  struct forward_iterator_tag: public input_iterator_tag{};

                  struct bidirection_iterator_tag: public forward_iterator_tag{};

                  struct random_access_iterator_tag: public bidirection_iterator_tag{};

这些class只作标记使用,不占用任何空间。

//advance()为例
//最后一个参数只是用来重载,不需要任何成员
template<class InputIterator,class Distance>
inline void__advance(InputIterator& i,Distance n,input_iterator_tag)
{while(n--)++i;}

template<class ForwardIterator,class Distance>
inline void__advance(ForwardIterator& i,Distance n,forward_iterator_tag)
{
     __advance(i,n,input_iterator_tag);
}

template<class BidirectionalIterator,class Distance>
inline void__advance(BidirectionalIterator& i,Distance n,bidirectional_iterator_tag)
{
     if(n>=0)while(n--)++i;
     else while(n++)--i;
}

template<class RandomAccessIterator,class Distance>
inline void__advance(RandomAccessIterator& i,Distance n,random_access_iterator_tag)
{
    i+=n;
}

//调用的时候,InputIterator可以是所有上面的五种迭代器之一
template<class InputIterator,class Distance>
inline void advance(InputIterator& i,Distance n)
{
    //自动选择上面的四个函数
    //萃取iterator_category必须在每个iterator_traits里面
    __advance( i,n,iterator_traits<InputIterator>::iterator_category());
}


2.std::iterator的保证

      为了符合规范,任何迭代器都必须要相应的型别,以利于traits萃取,否则便是自别于整个STL架构,可能无法与STL组件顺利搭配。STL定义了一个标准的iterator class,每个迭代器都继承自它,这样就保证了统一行。

template<
     class Category,
     class T,
     class Distance = ptrdiff_t,
     class Pointer = T*,
     class Reference = T&              
>
struct iterator{
     typedef  Category     iterator_category;
     typedef  T                 value_type;
     typedef  Distance     difference_type;
     typedef  Pointer        pointer;
     typedef  Reference   reference  ;
};

      iterator class不含任何成员,纯粹型别定义,所以继承不会招致任何负担,由于后三个参数皆有默认值。故心得迭代器只需要提供两个参数即可。

template<class T>

struct ListIter:public std: iterator<std::forward_iterator_tag,Item>

{...........}

3.__type_traits

      类型粗略的讲有两种,一种是用class封转,并且它的复制拷贝很费时,比如需要深度复制,需要safe copying——即需要调用构造函数完成复制;另一种是所谓的POD(plain old data),一般是build-in类型或是c式的struct类型,这种类型复制和拷贝时只需直接复制内存块就可以了,于是有了bitwise copying或是trival construct/deconstruct/copy/assignment的概念。

      SGI STL中使用__type_traits就可以在编译期间就确定复制一个对象是调用赋值构造函数还是直接调用memcpy,从而提高效率。看SGI STL的源代码:

  1. struct __true_type {};  
  2. struct __false_type {};  
  3.   
  4. template <class type>   //primariy template  
  5. struct __type_traits {   
  6.      typedef __true_type     this_dummy_member_must_be_first;  
  7.       
  8.     typedef __false_type    has_trivial_default_constructor;  
  9.     typedef __false_type    has_trivial_copy_constructor;  
  10.     typedef __false_type    has_trivial_assignment_operator;  
  11.     typedef __false_type    has_trivial_destructor;  
  12.     typedef __false_type    is_POD_type;  
  13. };  
  14. __STL_TEMPLATE_NULL struct __type_traits<char> { //full specialization  
  15.     typedef __true_type    has_trivial_default_constructor;  
  16.     typedef __true_type    has_trivial_copy_constructor;  
  17.      typedef __true_type    has_trivial_assignment_operator;  
  18.     typedef __true_type    has_trivial_destructor;  
  19.     typedef __true_type    is_POD_type;  
  20. };  
  21. __STL_TEMPLATE_NULL struct __type_traits<int> {  
  22.     typedef __true_type    has_trivial_default_constructor;  
  23.     typedef __true_type    has_trivial_copy_constructor;  
  24.     typedef __true_type    has_trivial_assignment_operator;  
  25.     typedef __true_type    has_trivial_destructor;  
  26.     typedef __true_type    is_POD_type;  
  27. };  
接下来,看看怎样使用__type_trairt:
[cpp]  view plain copy
  1. template <class InputIterator, class ForwardIterator, class T>  
  2. inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last,  
  3.                      ForwardIterator result, T*) {  
  4.         typedef typename __type_traits<T>::is_POD_type is_POD;  
  5.         return __uninitialized_copy_aux(first, last, result, is_POD());  
  6. }  
  7. template <class InputIterator, class ForwardIterator> inline ForwardIterator   
  8. __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  9.                          ForwardIterator result, __true_type) {  
  10.         return copy(first, last, result); //STL 算法copy里面大有乾坤,针对POD类型,调用memmove,还含有iterator_trait的使用  
  11. }  
  12. template <class InputIterator, class ForwardIterator>  
  13. ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  14.                          ForwardIterator result, __false_type) {  
  15.         ForwardIterator cur = result;  
  16.         for ( ; first != last; ++first, ++cur)  
  17.                construct(&*cur, *first);  
  18.         return cur;  
  19.   }  
  20. }  

你可能感兴趣的:(STL源码笔记之型别提取技法(2))