STL源代码剖析-08 迭代器,type-traits (1)

2115阅读 0评论2012-04-22 _Rayx
分类:C/C++

迭代器就是一个类似于指针的玩意,在STL里面大量应用了迭代器,同时为了更好的提升效率,里面也提供了多种迭代器供选择。
stl_construct.h中我们说了使用type traits技术来构造与析构对象,以达到最好的效率。现在为了使迭代器通用,我们必需知道迭代器指向的对象的类型,同时这个类型可能是作为变量声明,返回值等来使用。对于用作变量声明,使用模板参数推导可以很好的解决。可以看如下代码:

  1. template<class Type, class Value>
  2. void Test(Type ty, Value val) {
  3.     Value c = val; //迭代器的指向的类型就是Value
  4.     //...
  5. }

  6. template<class Type>
  7. void TestInterface(Type b) {
  8.     //...
  9.     Test(b, *b); //*b代表的就是迭代器指向的类型的值
  10. }

  11. int main(int argc, char **argv) {
  12.     Iterator a = ...;// a是一个迭代器
  13.     TestInterface(a);
  14.     //...
  15.     return 0;
  16. }
上面代码就将一个迭代器a所指向的类型提取出来了,就是Value。当然直接Test(a, *a)也行。你需要做的就是保证迭代器与它所指的内型都让模板能推导正确就行了。然而上面存在的一个问题就是函数并不推导返回值类型,有时候我们需要一个类型作为返回值,这样就可能存在问题了,这个类型是什么呢,我们不知道,一种想法是自己指定,而参数类型由模板去推导:

  1. template<class RT, class Type, class Value>
  2. RT Test(Type ty, Value val) {
  3.     Value c = val; //迭代器的指向的类型就是Value
  4.     printf("%d\n", c);
  5.     return c;
  6. }

  7. int main() {
  8.     int a = 5;
  9.     Test<int>(&a, a); //调用的时候我们自己指定返回类型,参数类型由模板推导
  10.     return 0;
  11. }
啊哈,我们指定RT为int类型,这样返回值类型我们就知道了。然而STL里面却是使用的声明内嵌类型,即在迭代器里typedef一个类型,这个类型是做为返回值用的。

  1. template <class T>
  2. struct MyIter {
  3.     typedef T value_type;
  4.     T* ptr;
  5.     //....
  6. };

  7. template<class I>
  8. typename I::value_type
  9. func(I itr) {
  10.     return *itr;
  11. }
可以看到 func中指明了返回类型是I::value_type,如果迭代器传的就是MyIter,那么T就是返回类型。即传一个MyIter返回类型就是double。
返回类型还存在的一个问题就是对于指针类型的处理,因为typedef指针可能会出现问题!


  1. typedef int * intPtr;

  2. int main() {
  3.     int a = 5;
  4.     const intPtr ptr= &a;
  5.     printf("%d\n", *ptr);
  6.     *ptr = 6;
  7.     printf("%d\n", *ptr);
  8.     //int b = 7;
  9.     //ptr = &b; //错误
  10.     //printf("%d\n", *ptr);
  11.     return 0;
  12. }
可以看到注释的部分有问题了,因为const intPtr等价于intPtr const,即intPtr是一个整体。可能我们的本意是一个指向a的不可改变a的内容的指针(const int *),现在却变成了一个指向a可改变a的值但不能指向其它对象的指针(int * const),typedef之后我们发现我们不能定义出类似于const int *这样的变量了!
这个问题的解决办法就是使用模板的偏特化来特殊处理指针类型,下次再说吧。



上一篇:STL源代码剖析-07 memory 智能指针auto_ptr
下一篇:STL源代码剖析-09 迭代器,type-traits (2)