关于iterator traits和type traits的使用,我们什么时候会使用这两个类?我们怎么使用?
//问题:将[first1,last1)区间内的元素复制一遍。 //我们需要知道first1迭代器的类型。。 template<class _Iter> _Iter copy(_Iter first1,_Iter last1) { //首先需要分配足够的空间,即迭代器所指元素的大小乘以个数 typedef typename iterator_traits<_Iter>::value_type _T; _T* __result=new _T[last1-first1]; //然后我们需要进行复制 _T* __p=__result; for(;first1!=last1;++first1,++__p){ //这里的复制,我们需要知道_T是否是具有快速的复制构造函数 typedef typename __type_traits<_T>::has_trivial_copy_constructor _Copy_traits; //如果_Copy_traits是__true_type那么就使用快速的copy,如果是__false_type那么就使用慢的copy,这里怎么判断两者相等 //是个问题。。。 //方法一: _Copy_traits __ct;__true_type __tt; if(typeid(__ct)==typeid(__tt)){__quick_copy(__p,__first);} else __normal_copy(__p,__first); //方法二: //mfc中的策略 //方法三:利用函数的重载机制和模板推断机制 __copy(_Iter(__p),__first,_Copy_traits()); } return _Iter(__result); } template<class _Iter> void __copy(_Iter __dest,_Iter __source,__true_type) { __quick_copy(__dest,__source); } template<class _Iter> void __copy(_Iter __dest,_Iter __source,__false_type) { __normal_copy(__dest,__source); }
这就是traits使用的大体情况,这里stl中使用的统一技术就是函数重载与模板推断机制
举两个stl中的例子:他们遵循的模式都是:定义接口--利用模板推断和重载将任务分配或者说是路由-----特化特定的类型提高速度
//两个例子: template <class _Tp> inline void destroy(_Tp* __pointer) { __pointer->~_Tp(); } //补充__VALUE_TYPE template <class _Iter> inline typename iterator_traits<_Iter>::value_type* __value_type(const _Iter&) { return static_cast<typename iterator_traits<_Iter>::value_type*>(0);//返回的是指针,这里的技术需要注意 } template <class _Iter> inline typename iterator_traits<_Iter>::value_type* value_type(const _Iter& __i) { return __value_type(__i); } #define __VALUE_TYPE(__i) value_type(__i) //销毁对象,下面使用的策略是、其实完全不必要,只是为了在stl中使用一致的策略 template <class _ForwardIterator> inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) { __destroy(__first, __last, __VALUE_TYPE(__first));//根据迭代器萃取类型信息 } template <class _ForwardIterator, class _Tp> inline void __destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)//我们需要类型信息 { typedef typename __type_traits<_Tp>::has_trivial_destructor _Trivial_destructor; __destroy_aux(__first, __last, _Trivial_destructor()); } template <class _ForwardIterator> void __destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type) { for ( ; __first != __last; ++__first) destroy(&*__first);//传递给destroy的是指针,此处主要是迭代器与指针的不兼容性 } template <class _ForwardIterator> inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {} //特化 inline void _Destroy(char*, char*) {} inline void _Destroy(int*, int*) {} inline void _Destroy(long*, long*) {} inline void _Destroy(float*, float*) {} inline void _Destroy(double*, double*) {} //copy: template <class _InputIter, class _ForwardIter> inline _ForwardIter uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result) { return __uninitialized_copy(__first, __last, __result, __VALUE_TYPE(__result)); } template <class _InputIter, class _ForwardIter, class _Tp> inline _ForwardIter __uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result, _Tp*) { typedef typename __type_traits<_Tp>::is_POD_type _Is_POD; return __uninitialized_copy_aux(__first, __last, __result, _Is_POD()); } template <class _InputIter, class _ForwardIter> inline _ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last,_ForwardIter __result,__true_type) { return copy(__first, __last, __result); } template <class _InputIter, class _ForwardIter> _ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __false_type) { _ForwardIter __cur = __result; __STL_TRY { for ( ; __first != __last; ++__first, ++__cur) _Construct(&*__cur, *__first); return __cur; } __STL_UNWIND(_Destroy(__result, __cur)); } //对于char和wchar_t的特化版本 inline char* uninitialized_copy(const char* __first, const char* __last, char* __result) { memmove(__result, __first, __last - __first); return __result + (__last - __first); } inline wchar_t* uninitialized_copy(const wchar_t* __first, const wchar_t* __last, wchar_t* __result) { memmove(__result, __first, sizeof(wchar_t) * (__last - __first)); return __result + (__last - __first); }