1. 程式人生 > >C++標準庫(六)之traits技術

C++標準庫(六)之traits技術

對象的引用 pointer 處的 fde ifd partial clas .... n)

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;
};

C++標準庫(六)之traits技術