主要讨论如何获取迭代器相应型别。使用迭代器时,极可能用到其型别,若须要声明某个迭代器所指对象的型别的变量,该如何解决。方法以下:编程
例如:函数
template<typename I, typename T> void func_impl(I iter, T t) { //T为迭代器所指对象的型别 T tmp; //..... } template<typename I> inline void func(I iter) { //func工做交给func_impl完成 func_impl(iter, *iter); } int main() { int i; func(&i); return 0; }
func_impl()是一个 function template,一旦被调用,编译器会自动进行template参数推导,从而导出型别T,无需本身指出型别,解决问题。迭代器相应型别不仅是迭代器所指对象的型别一种而已,最经常使用的相应型别有五种,但并不是任何状况均可利用上述template参数推导机制来取得。这就须要其余方法。设计
迭代器所指对象的型别,成为该迭代器的value type,上述模板参数推导并不是全面可用,在须要value type做为函数返回值时,就不能解决了。template参数推导的只是参数而已。所以,声明内嵌型别就出现了。指针
例如:code
template<typename T> struct MyIter { typedef T value_type; //内嵌型别声明 T* ptr; MyIter(T* p = nullptr):ptr(p) { } T& operator*() const { return *ptr;} //... }; template<typename I> typename I::value_type //函数func()的返回类型,为I类型迭代器中的value_type func(I ite) { return *ite; } int main() { MyIter<int> ite(new int(8)); cout<<func(ite); //输出8 return 0; }
func()函数的返回值必须加上关键字typename,用来告诉编译器这时一个模板类型。但并非全部迭代器都为class type,原生指针就不是,它就不能定义内嵌型别。这时模板偏特化(template partial specialization)就能解决这个问题。对象
若是class template拥有一个以上的template参数,咱们能够针对其中某个(或数个,但并不是所有)template参数进行特化工做。也就是将泛化版本中的某些template参数给予明确的指定。ci
如:编译器
template<typename U, typename V, typename T> class C { }
偏特化不是template参数U、V或T指定某个参数值,而是针对(任何)template参数更进一步的条件限制所设计出来的一个特化版本。看这个例子:it
//泛化版本 template<typename T> class C { } //偏特化版本 template<typename T> class C<T*> { } //解决原生指针的问题
如此便能解决前面的内嵌型别的问题。下面这个class template专门用来萃取迭代器的特性之一 :value_typeio
template<typename I> struct Iterator_traits //traits指的是特性 { typedef typename I::value_type value_type; }