STL源码剖析笔记(迭代器)

STL经常需要获取迭代器型别来进行一系列算法设计,简单总结一下书所对于型别推导提到的思想

迭代器获取其所指元素的型别

  1. 1.

一 利用 function template 的自变量推导( argument deducation)机制。

template <class I, class T>
void func_impl(I iter, T t)
{
 T tmp; // 这里解决了问题。 T就是迭代器所指之物的型别,ᴀ例为 int
// ... 这里做原ᴀ func() 应该做的全部工作
};
template <class I>
inline void func(I iter)
{
 func_impl(iter, *iter); // func 的工作全部移往 func_impl
}
int main()
{
 int i;
 func(&i);
}

使用func()来包装func_impl(),func函数对外。只要调用func()便可以通过func_impl推导出型别T。但是这中方法并不健全,当func的参数为函数返回值就行不通了。
-
2.

声明内嵌型别

template <class T>
struct MyIter
 typedef T value_type; 
 T* ptr;
 MyIter(T* p=0) : ptr(p) { }
 T& operator*() const { return *ptr; }
 // ...
};
template <class I>
typename I::value_type   func(I ite)
{ return *ite; }
// ...
MyIter<int> ite(new int(8));
cout << func(ite); //输出: 8

但是 实际上 要使迭代器有内嵌型别,迭代器本身就必须是一个struct或者class,但是像原生指针并不是class这种类型就无法定义内嵌型别,因此通过3
3.

偏特化

template<typename T>  //1
class C { ... };  

template<typename T>  //2
class C<T*> { ... };  

如上,2为1偏特化,可以通过2设计T指针的偏特化迭代器。解决了指针无法定义内嵌型别的问题。

关于traits ,这个地方比上面难理解一些 多写一点
首先需要明白traits 解决的问题,对于T
举个例子 如果我要实现一个模板类,在这个模板类实现一个函数sum()来计算两个成员变量的和,其中两个成员变量均为T类型。sum要求如下

1当T为float类型时候,要求sum()返回类型为int
2当T为其他类型的时候,要求sum( )返回类型为T

如果只是单纯实现2的话,很容易做到,但是1的话不属于2范围,这时候就需要用到偏特化。
实现如下

#include<iostream>
template <typename T>
struct  Traits{
    typedef T _type;

};
template<>
struct  Traits<float>{
    typedef int _type;
};

template <typename T>
class A
{
public:
  A(T a,T b):data_a(a),data_b(b){};
  typename Traits<T>::_type sum(){return data_a+data_b;}

private:
  T data_a,data_b;
};



int main()
{
    A<double>Obj_d(1.3,1.5);
    A<float>Obj_f(1.3,1.5);
    std::cout<<Obj_d.sum()<<"  "<<Obj_f.sum();  //输出为2.8   2
    return 0;
}

理解了traits的本意,那么我们可以对T* 进行偏特化,并通过trait取出value(T)类型来定义func2,同样也适用于const T*

#include<iostream>

using namespace std;
template <class T>
struct MyIter{
    typedef T Iter_type;
    T* ptr;
    MyIter(T* p=0):ptr(p){}
    T& operator*() const{
        return *ptr;
    }
};
template <class T>
struct MyIter<T*>{
    typedef T Iter_type;
    T* ptr;
    MyIter(T* p=0):ptr(p){}
    T& operator*() const{
        return *ptr;
    }
};

template<class T>
struct traits{
    typedef typename T::Iter_type traits_type;
};

template<class T>
struct traits<T*>{
    typedef  T traits_type;
};

//template<class T>
//struct traits<const T*>{
//    typedef T traits_type;
//};

template <class I>
typename traits<I>::traits_type func(I iter){
    return *iter;
}


int main(){
    MyIter<int>iter1(new int(8));
    MyIter<int*>iter2(new int(8));
    cout<<func(iter1)<<endl<<func(iter2);
}



迭代器

5个内嵌类型

  • value type 用来表示迭代器所指对象的型别;
  • difference type 用来表示两个迭代器之间的距离;
  • reference 为引用类型;
  • pointer 为指针类型;
  • iterator_category 表明迭代器的类型

迭代器的五种类型
1. Input Iterator:这种迭代器所指对象,不允许外界改变,只读(read only);
2. Output Iterator:唯写(write only);
3. Forward Iterator:允许「写入型」算法(例如 replace())在此种迭代器所形成的区间上做读写动作;
4. Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间(例如逆向拷贝某范围内的元素),就可以使用 Bidirectional Iterators;
5. Random Access Iterator:前四种迭代器都只供应一部份指标算术能力(前3
种支持 operator++ ,第4种再加上 operator–),第5种则涵盖所有指标算术能力,包括 p+n, p-n, p[n], p1-p2, p1

这里写图片描述
通过继承机制,

 struct input_iterator_tag { };
 struct output_iterator_tag { }; 
 struct forward_iterator_tag : public input_iterator_tag { }; 

 struct bidirectional_iterator_tag : public forward_iterator_tag { }; 

 struct random_access_iterator_tag : public bidirectional_iterator_tag { };

以上结构体仅作为标记存在,通过一个作为标记参数来重载函数
对外接口使用traits机制,在编译期确定调用的重载函数。




__type_traits

traits的其他用途,用于获取是否有如下内容,提高在程序运行期的效率。
has_trivial_default_constructor;
has_trivial_copy_constructor;
has_trivial_assignment_operator;
has_trivial_destructor;
is_POD_type;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值