C++STL迭代器识别相应对象的类型

一、问题

在算法中运用迭代器时,经常会用到其相应类型(associative type),即迭代器所指向对象的类别。但C++只支持sizeof(),并不存在typeof()之说(即使运用RTTI性质中的typeid(),获得的也只是类型名称,不能用来做变量声明之用)。
为解决此问题,这里总结下迭代器相应型别的获取方法。

二、方案

1、可以利用函数模板(function template)的参数推导(argument deduction)机制:

template <class I, class T>
void fun_impl(I iter, T t){     // 此处该函数利用模板参数推导得知T为*iter类型
    T tmp;                      // 可以声明变量
    //...
};

template <class I>
inline void func(I iter){
    fun_impl(iter, *iter); //此处把*iter作为第二个参数传递给fun_impl()
}
int main(int argc, char *argv[])
{
    int i=9;
    func(&i);
    return 0;
}

 然而这种template参数推导机制方法并不适用于任何的情况,比如函数的返回值就无法利用这种方法,因为template参数推导只适合于参数,不适合于函数返回值。所以我们需要更加全面的方法。

 2、声明内嵌型别

#include<iostream>
using namespace std;
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 iter){//关键代码
	return *iter;
}
int main(){
	
	MyIter<int>iter(new int(8));
	cout<<func(iter);//输出8 
	
}

中func的返回值必须加上关键字typename,因为T是一个template参数,在它编译具现化之前,编译器对T一无所知,编译器此时并不知道MyIter<T>::value_type代表的是一个型别或者是一个member function或是一个data member。typename的用意是告诉编译器这是一个型别,才能通过编译。但是这种方法只适用于迭代器是一个class或者struct,因为只有class和struct才能使用内嵌型别即typedef T value_type;而对于像指针这种类型,这种方法不使用。怎么办呢,这时候模板偏特化就派上用场了。
 

3.模板偏特化

有了偏特化之后,就可以解决上面的原生指针不是class type的类型。我们可以针对“迭代器的template参数为指针”者,设计特化版本的迭代器。

#include<iostream>
using namespace std;
template <class T>
struct MyIter{
	typedef T value_type;
	T* ptr;
	MyIter(T* p=0):ptr(p){}
	T& operator*() const{
		return *ptr;
	}
};
//偏特化 
template <class T>
struct MyIter<T*>{
	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 iter){//关键代码,
	return *iter;
}
 
int main(){
	MyIter<int>iter1(new int(8));
	MyIter<int*>iter2(new int(8));//注释掉偏特化版本将出错 
	cout<<func(iter1)<<endl<<func(iter2); 
}

STL中常见的5中相应型别如下:

template<class T>
struct my_iterator_traits{
	typedef typename T::iterator_category iterator_category;//迭代器分类 
	typedef typename T::value_type value_type;//相应型别 
	typedef typename T::difference_type difference_type;//两个迭代器之间的距离 
	typedef typename T::pointer pointer;//指针 
	typedef typename T::reference reference;//引用 
}; 

参考:

https://www.cnblogs.com/visayafan/archive/2011/11/27/2265400.html

https://blog.csdn.net/gettogetto/article/details/51579522

https://blog.csdn.net/LG1259156776/article/details/77992822

猜你喜欢

转载自blog.csdn.net/sinat_31608641/article/details/107419632