STL迭代器之一:偏特化

时间:2021-03-01 19:27:16

在stl的算法中运用容器的迭代器时,很可能经常会用到迭代器相应型别(例如迭代器所指物的型别),假设算法中有必要声明一个变量,以“迭代器所指对象的型别”为类型,如何是好,例如我们写一个功能,打印迭代器元素的值:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; template <class T>
typename T::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d", func(ite));
return ;
}

但是我们无法支持原生指针,比如

int a = 10;

int b = func(&a);

这里偏特化可以帮我们实现,"所谓partial specialization"的意思就是提供另一份template的定义式,而其本身仍为templatized”。

“针对(任何)template 参数更进一步的条件限制所设计出来的一个特化版本”——《泛型思维》

第一步定义iterator_traits中间层:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d", func(ite)); return ;
}

输出:8

第二步,针对原生指针设计一个特化版本:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; //针对原生指针
template <class I>
struct iterator_traits<I*>
{
typedef I value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d\n", func(ite));
int a = 1;
printf("%d\n", func(&a));
return ;
}

但是假设我在func里面希望做如下操作:

template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
  typename iterator_traits<T>::value_type a;
  a++;   //这里将报错,const 常量无法修改
  return *iter;
}

我们希望的效果是:只想定义一个T类型的数据类型,如果需要const修饰,我们自己在类型前面加个const即可。

于是我们还要对const T*设计一个特化版本:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; //针对原生指针
template <class I>
struct iterator_traits<I*>
{
typedef I value_type;
};
//针对const原生指针
template <class I>
struct iterator_traits<const I*>
{
typedef I value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
typename iterator_traits<T>::value_type a;
a++;
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d\n", func(ite));
int a = ;
const int* pa = &a;
func(pa); return ;
}