2012-04-30 47 views
2

有幾個類似的線程Q1Q2到這個,但不完全。爲通用容器中的begin()和end()函數避免重複的代碼

的問題是簡單地寫在一個優雅的方式將以下代碼,而無需重複代碼:

template <typename T, class Container = std::vector<T> > 
class container{ 
    iterator begin(){ 
     return iterator(data_.begin(), 1); 
    } 

    const_iterator begin() const{ 
     return const_iterator(data_.begin(), 1); 
    } 
    Container data_; 
}; 

Q2有一種優雅的方式來避免const和non-const函數的代碼複製具有完全相同的簽名。但是,這不是這種情況,因爲沒有強制將const_iterator轉換爲迭代器。

Q1提供了一個使用模板的好方法,但是,一旦容器是一個類,begin_impl函數變爲static並且同時變成friend

最優雅的代碼我想出是:

template <T> 
class container{ 
     template< typename I, typename C > 
     static I begin_impl(C & c){ 
      return I(data_.begin(), 1); 
     } 

     template< typename I, typename C > 
     friend I container<T>::begin_impl(C & c); 

     iterator begin(){ 
      return container<T>::template begin_impl<iterator>(*this); 
     } 

     const_iterator begin() const{ 
      return container<T>::template begin_impl<const_iterator>(*this); 
     } 
} 

我的問題是,這是否是您認爲最優雅的方式。如果不是,請提供一些更好的代碼。

編輯:我的迭代器實現:

class container{ 
     template <bool isConst> 
     class iterator_ { 

     public: 
      typedef Container container_type; 
      typedef typename Container::value_type value_type; 
      typedef typename Container::difference_type difference_type; 
      typedef typename Container::size_type size_type; 
      typedef typename Container::reference reference; 
      typedef typename Container::const_reference const_reference; 
      typedef typename Container::pointer pointer; 
      typedef typename Container::const_pointer const_pointer; 
      typedef typename std::forward_iterator_tag iterator_category; 

      template<bool isCond, typename cref, typename ref> 
      struct IS_CONST_REF{ 
       typedef ref reference_type; 
      }; 
      template<typename cref, typename ref> 
      struct IS_CONST_REF<true, cref, ref>{ 
       typedef cref reference_type; 
      };    
      typedef typename IS_CONST_REF<isConst, const_reference, reference>::reference_type ref; 

      template<bool isCond, typename citr, typename itr> 
      struct IS_CONST_ITR{ 
       typedef itr iterator_type; 
      }; 
      template<typename citr, typename itr> 
      struct IS_CONST_ITR<true, citr, itr>{ 
       typedef citr iterator_type; 
      };    
      typedef typename IS_CONST_ITR<isConst, typename Container::const_iterator, typename Container::iterator>::iterator_type itr; 

      iterator_() 
      :data_(), stepSize_(0){ 
      } 

      iterator_(itr data, difference_type stepSize) 
      :data_(data), stepSize_(stepSize){ 
      } 

      iterator_(const iterator_<false>& src) 
      :data_(src.getData()), stepSize_(src.getStepSize()){ 
      } 

     [some more code ...] 

     protected: 
      itr data_; 
      difference_type stepSize_; 
     }; 

     typedef iterator_<true> const_iterator; 
     typedef iterator_<false> iterator; 
}; 
+1

那豈不是更容易使'const_iterator'私下兌換成'iterator',並在常量方面實現非const'begin' 'begin'? – ildjarn

+0

它不是構成嚴重的安全漏洞? – guinny

+0

如果轉換函數沒有公開訪問的話,那就不行了...... – ildjarn

回答

1

好了,顯然這仍然是最好的答案:

template <T> 
class container{ 
     template< typename I, typename C > 
     static I begin_impl(C & c){ 
      return I(data_.begin(), 1); 
     } 

     template< typename I, typename C > 
     friend I container<T>::begin_impl(C & c); 

     iterator begin(){ 
      return container<T>::template begin_impl<iterator>(*this); 
     } 

     const_iterator begin() const{ 
      return container<T>::template begin_impl<const_iterator>(*this); 
     } 
} 
2

怎麼樣:

class container{ 
    iterator begin(){ 
     return iterator(getStuff()); 
    } 

    const_iterator begin() const{ 
     return const_iterator(getStuff()); 
    } 

    private: 
     Stuff getStuff() const { [some code here] } 
}; 

如果你有共同的代碼。
將其移至執行該作業的私人方法。

+0

與OP的'begin_impl'方法有何不同? – ildjarn

+0

@ildjarn:我看不到需要模板或使其成爲靜態方法。 –

+0

這似乎沒有足夠的不同,以保證IMO的答案。 /聳聳肩 – ildjarn