STL(七)之萃取技术 C++标准库(七)之traits技术

C++标准库(七)之traits技术

traits技术

原理:利用template的参数推导机制获取传入的参数型别。

template<typename T>
struct Iter { typedef T value_type; .... } template<typename T> typename T::value_type func(T* ite) {return *ite;}

这种程度,依旧会遇到一个问题:如果不是一个class type(比如指针,引用),就无法进行正确的参数推导。可以使用模板偏特化来处理这种情形:

template<typename T>
struct Iter<T*> { typename T value_type; };

我们需要处理的核心问题:通过traits技术如何获得iterator描述的型别?

template<typename T>
struct 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; };

同时,iterator_traits必须对传入的型别为pointer和pointer-to-const者设计特化版本。

template<typename T>
struct iterator_traits<T*> { ... typedef random_access_iterator_tag iterator_category; } template<typename T> struct iterator_traits<const T*> { ... typedef random_access_iretator_tag iterator_category; }

型别:

  • value type:描述iterator指向对象的型别。
  • difference type:描述两个iterator之间的距离,默认情况下使用C++内建的ptrdiff_t类型
  • reference type:描述iterator所指向对象的引用
  • pointer type:描述iterator所指向对象的指针
  • iterator_category:描述迭代器的相应性别
    • Input Iterator:只读迭代器
    • Output Iterator:只写迭代器
    • Forward Iterator:读写迭代器
    • Bidirectional Iterator:双向移动迭代器,可读写
    • Random Access Iterator:随机移动迭代器,可读写

利用重载机制,通过在编译期就为不同版本的迭代器选择不同版本的函数:

template<typename category,typename T,typename dis=ptrdiff_t,typename poin=T*,typename ref=T&> struct iterator { typedef category iterator_category; typedef T value_type; typedef dis difference_type; typedef poin pointer; typedef ref reference; }; 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 {}; template <typename InputIterator,typename Distance> inline void __advance(InputIterator& iter,Distance n,input_iterator_tag) { while(n--) ++iter; } template <typename ForwardIterator,typename Distance> inline void __advance(ForwardIterator& iter,Distance n,forward_iterator_tag) { __advance(i,n,input_iterator_tag()); } template <typename BidirectionalIterator,typename Distance> inline void __advance(BidirectionalIterator& iter,Distance n,bidirectional_iterator_tag) { if(n > 0) while(n--) ++iter; if(n < 0) while(n--) --iter; } template <typename RandomAccessIterator,typename Distance> inline void __advance(RandomAccessIterator& iter,Distance n,random_access_iterator_tag) { iter += n; }

根据traits机制,需要使用以下 的包装器:

template <typename InputIterator,typename Distance>
inline void __advance(InputIterator& iter,Distance n) { __advance(i,n,iteratir_traits<InputIterator>::iterator_category()); }

获取型别的函数:

template<typename Iterator>
inline typename iterator_traits<Iterator>::iterator_category iteratir_category(const Iterator&) { typedef typename iterator_traits<Iterator>::iterator_category category; return category(); } template<typename Iterator> inline typename iterator_traits<Iterator>::distance_type* distance_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::distance_type*>(0); } template<typename T> inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::value_type*>(0); } 

总结

设计适当的型别,是迭代器的责任。
设计适当的迭代器,是容器的责任。

__type_traits
traits技术弥补了C++语言本身的不足,但是traits技术不仅存在于Iterator之中,也存在于STL之中。iterator_traits负责萃取迭代器特性,__type_traits则负责萃取型别参数。此处的型别参数是指:这个型别是否具有non-trivial default ctor?是否具有non-trivial copy ctor?是否具有non-travial assignment operator?是否具有non-trravial dctor?如果没有的话,我们可以使用memcpy(),memmove()采取最有效的操作。否则的话,需要根据ctor,copy,dctor等进行复杂的操作。
可以使用如下类似与iterator_traits的方式:

__type_traits<T>::has_trivial_default_constructor
__type_traits<T>::has_trivial_copy_constructor
__type_traits<T>::has_trivial_assignment_operator
__type_traits<T>::has_trivial_destructor
__type_traits<T>::is_POD_type

struct __true_type {};
struct __false_type {}; template<typename T> struct __type_traits { typedef __false_type has_trivial_default_constructor; typedef __false_type has_trivial_copy_constructor; typedef __false_type has_trivial_assignment_operator typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; }

STL为所有的内嵌性别定义最保守的值,然后再为体统提供类型(char,long,int,double)等设计适当的特化版本。

__STL_TEMPLATE_NULL struct __type_traits<bool> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_NO_BOOL */ __STL_TEMPLATE_NULL struct __type_traits<char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<signed char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_HAS_WCHAR_T __STL_TEMPLATE_NULL struct __type_traits<wchar_t> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_HAS_WCHAR_T */ __STL_TEMPLATE_NULL struct __type_traits<short> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned short> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<int> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned int> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_LONG_LONG __STL_TEMPLATE_NULL struct __type_traits<long long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned long long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_LONG_LONG */ __STL_TEMPLATE_NULL struct __type_traits<float> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<double> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<long double> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION template <class _Tp> struct __type_traits<_Tp*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ __STL_TEMPLATE_NULL struct __type_traits<char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<signed char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const signed char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const unsigned char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; };

traits技术

原理:利用template的参数推导机制获取传入的参数型别。

template<typename T>
struct Iter { typedef T value_type; .... } template<typename T> typename T::value_type func(T* ite) {return *ite;}

这种程度,依旧会遇到一个问题:如果不是一个class type(比如指针,引用),就无法进行正确的参数推导。可以使用模板偏特化来处理这种情形:

template<typename T>
struct Iter<T*> { typename T value_type; };

我们需要处理的核心问题:通过traits技术如何获得iterator描述的型别?

template<typename T>
struct 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; };

同时,iterator_traits必须对传入的型别为pointer和pointer-to-const者设计特化版本。

template<typename T>
struct iterator_traits<T*> { ... typedef random_access_iterator_tag iterator_category; } template<typename T> struct iterator_traits<const T*> { ... typedef random_access_iretator_tag iterator_category; }

型别:

  • value type:描述iterator指向对象的型别。
  • difference type:描述两个iterator之间的距离,默认情况下使用C++内建的ptrdiff_t类型
  • reference type:描述iterator所指向对象的引用
  • pointer type:描述iterator所指向对象的指针
  • iterator_category:描述迭代器的相应性别
    • Input Iterator:只读迭代器
    • Output Iterator:只写迭代器
    • Forward Iterator:读写迭代器
    • Bidirectional Iterator:双向移动迭代器,可读写
    • Random Access Iterator:随机移动迭代器,可读写

利用重载机制,通过在编译期就为不同版本的迭代器选择不同版本的函数:

template<typename category,typename T,typename dis=ptrdiff_t,typename poin=T*,typename ref=T&> struct iterator { typedef category iterator_category; typedef T value_type; typedef dis difference_type; typedef poin pointer; typedef ref reference; }; 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 {}; template <typename InputIterator,typename Distance> inline void __advance(InputIterator& iter,Distance n,input_iterator_tag) { while(n--) ++iter; } template <typename ForwardIterator,typename Distance> inline void __advance(ForwardIterator& iter,Distance n,forward_iterator_tag) { __advance(i,n,input_iterator_tag()); } template <typename BidirectionalIterator,typename Distance> inline void __advance(BidirectionalIterator& iter,Distance n,bidirectional_iterator_tag) { if(n > 0) while(n--) ++iter; if(n < 0) while(n--) --iter; } template <typename RandomAccessIterator,typename Distance> inline void __advance(RandomAccessIterator& iter,Distance n,random_access_iterator_tag) { iter += n; }

根据traits机制,需要使用以下 的包装器:

template <typename InputIterator,typename Distance>
inline void __advance(InputIterator& iter,Distance n) { __advance(i,n,iteratir_traits<InputIterator>::iterator_category()); }

获取型别的函数:

template<typename Iterator>
inline typename iterator_traits<Iterator>::iterator_category iteratir_category(const Iterator&) { typedef typename iterator_traits<Iterator>::iterator_category category; return category(); } template<typename Iterator> inline typename iterator_traits<Iterator>::distance_type* distance_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::distance_type*>(0); } template<typename T> inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::value_type*>(0); } 

总结

设计适当的型别,是迭代器的责任。
设计适当的迭代器,是容器的责任。

__type_traits
traits技术弥补了C++语言本身的不足,但是traits技术不仅存在于Iterator之中,也存在于STL之中。iterator_traits负责萃取迭代器特性,__type_traits则负责萃取型别参数。此处的型别参数是指:这个型别是否具有non-trivial default ctor?是否具有non-trivial copy ctor?是否具有non-travial assignment operator?是否具有non-trravial dctor?如果没有的话,我们可以使用memcpy(),memmove()采取最有效的操作。否则的话,需要根据ctor,copy,dctor等进行复杂的操作。
可以使用如下类似与iterator_traits的方式:

__type_traits<T>::has_trivial_default_constructor
__type_traits<T>::has_trivial_copy_constructor
__type_traits<T>::has_trivial_assignment_operator
__type_traits<T>::has_trivial_destructor
__type_traits<T>::is_POD_type

struct __true_type {};
struct __false_type {}; template<typename T> struct __type_traits { typedef __false_type has_trivial_default_constructor; typedef __false_type has_trivial_copy_constructor; typedef __false_type has_trivial_assignment_operator typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; }

STL为所有的内嵌性别定义最保守的值,然后再为体统提供类型(char,long,int,double)等设计适当的特化版本。

__STL_TEMPLATE_NULL struct __type_traits<bool> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_NO_BOOL */ __STL_TEMPLATE_NULL struct __type_traits<char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<signed char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_HAS_WCHAR_T __STL_TEMPLATE_NULL struct __type_traits<wchar_t> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_HAS_WCHAR_T */ __STL_TEMPLATE_NULL struct __type_traits<short> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned short> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<int> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned int> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_LONG_LONG __STL_TEMPLATE_NULL struct __type_traits<long long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned long long> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif /* __STL_LONG_LONG */ __STL_TEMPLATE_NULL struct __type_traits<float> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<double> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<long double> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION template <class _Tp> struct __type_traits<_Tp*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ __STL_TEMPLATE_NULL struct __type_traits<char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<signed char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<unsigned char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const signed char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; __STL_TEMPLATE_NULL struct __type_traits<const unsigned char*> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; };

猜你喜欢

转载自www.cnblogs.com/xcb-1024day/p/11332501.html
今日推荐