STL—迭代器相關類型

迭代器相關類型(associated types)—迭代器指向元素的類型,及此類型衍生的出來的類型。如:

std::vector<int>::iterator it; 
//此迭代器相關類型爲: int(value_type), int*(pointer), int&(reference), size_t(difference_type),

那麼迭代器相關類型有什麼用呢?我們將std::max_element(原型如下)稍微修改一下,將std::max_element的返回值修改爲最大值,而不是指向最大值的迭代器。怎麼做?

// std::max_element原型
template <class ForwardIterator>
  ForwardIterator max_element ( ForwardIterator first, ForwardIterator last )
{
  if (first==last) return last;
  ForwardIterator largest = first;
  while (++first!=last)
    if (*largest<*first)    // or: if (comp(*largest,*first)) for version (2)
      largest=first;
  return largest;
}

假設我們的輸入爲vector::iterator,現在我們只知道輸入是指向int類型的迭代器,要返回一個int型的數據卻不知道怎麼表達。其實這個問題STL已經爲我們解決好了。
traits技術
traits技術的中心思想—爲每一個class type的迭代器定義它的相關類型(value_type、pointer、 reference、difference_type),並使用iterator_traits迭代器的相關類型。
現在我們實現一個簡單的迭代器,並進行類型的提取:

template <typename elemType>
class MyIter {
    typedef elemType   value_type;
    typedef elemType*  pointer;
    typedef elemType&  reference;
    typedef size_t     difference_type;
    // ...
};
// 類型提取
template <typename ForwardIterator>
①typename ForwardIterator::value_type
max_element(ForwardIterator first, ForwardIterator last)
{
  if (first==last) return *last;
  ForwardIterator largest = first;
  while (++first!=last)
    if (*largest<*first)    // or: if (comp(*largest,*first)) for version (2)
      largest=first;
  return *largest;
}

此時類型提取的問題已經解決,但是到目前爲止我們並沒有用到iterator_traits,那麼iterator_traits到底有什麼用?剛纔我們說到爲每一個class type迭代器定義相關類型,非class type呢?如int, double*, …,別忘了我們一樣可以向std::max_element傳入數組指針。非*class type沒有辦法像class type一樣在內部定義value_type,reference等相關類型(associated type。那麼非*class type如何像class type一樣使用typename ForwardIterator::value_type來提取相關類型呢?我們且看iterator_traits定義:

template <class _Iterator>
struct iterator_traits {
  typedef typename _Iterator::iterator_category iterator_category;
  typedef typename _Iterator::value_type        value_type;
  typedef typename _Iterator::difference_type   difference_type;
  typedef typename _Iterator::pointer           pointer;
  typedef typename _Iterator::reference         reference;
};

template <class _Tp>
struct iterator_traits<_Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef _Tp*                        pointer;
  typedef _Tp&                        reference;
};

template <class _Tp>
struct iterator_traits<const _Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef const _Tp*                  pointer;
  typedef const _Tp&                  reference;
}

正如看到的那樣,iterator_traits有兩個特化版本,有了這兩個特化版本,不管是非class type的迭代器(如int或是const int)還是class type型迭代器 都可以通過iterator_traits來提取其相關類型。此時max_element就可以使用同一份實現。max_element就可以修改成這樣:

// 類型提取
template <typename ForwardIterator>
typename iterator_traits<ForwardIterator>::value_type
max_element(ForwardIterator first, ForwardIterator last)
{
  if (first==last) return *last;
  ForwardIterator largest = first;
  while (++first!=last)
    if (*largest<*first)    // or: if (comp(*largest,*first)) for version (2)
      largest=first;
  return *largest;
}
// 類似實現std::distance

注①:ForwardIterator沒有實例化之前,編譯器並不知道ForwairdIterator::value_type代表的是什麼,翻譯器可以將之猜測爲一個類的靜態變量,亦或是一個靜態方法。所以要請編譯器知道它是一個類型,那麼就需要在之前加上一個typename

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章