2013-03-01 38 views
5

我正在處理一個容器,它實現了自己的迭代器,我使用std :: reverse_iterator> <>來獲得反向迭代功能。我可以分配逆向迭代撕裂或rbegin,但是當我試圖訪問它的功能(如=或==!)我得到這樣的:運算符!=對std :: reverse_iterator不明確C++

1 IntelliSense: more than one operator "!=" matches these operands: 
     function template "bool std::operator!=(const std::reverse_iterator<_RanIt1> &_Left, const std::reverse_iterator<_RanIt2> &_Right)" 
     function template "bool avl::operator!=(const tree &left, const tree &right)" 
     operand types are: std::reverse_iterator<avl::avl_iterator<avl::avltree<char, int, std::less<char>, std::allocator<std::pair<const char, int>>>>> != std::reverse_iterator<avl::avl_iterator<avl::avltree<char, int, std::less<char>, std::allocator<std::pair<const char, int>>>>> 

我的迭代運算符重載:

bool operator == (const avl_iterator& rhs) const { return (_node == rhs._node); } 
    bool operator != (const avl_iterator& rhs) const { return (_node != rhs._node); } 

和我實現反向迭代的

typedef typename avl_iterator<tree>        iterator; 
typedef typename const_avl_iterator<tree>       const_iterator; 
typedef typename std::reverse_iterator<iterator>     reverse_iterator; 
typedef typename std::reverse_iterator<const_iterator>    const_reverse_iterator; 

和迭代器類型定義:

typedef typename tree::node     node; 
    typedef typename tree::node_ptr    node_ptr; 
    typedef typename tree::value_type*   pointer;// for std reverse iterator 
    typedef typename tree::value_type&   reference; 
    typedef typename tree::const_node_ptr  const_node_ptr; 
    typedef typename tree::utilities   utilities; 
    typedef typename tree::value_type   value_type; 
    typedef std::bidirectional_iterator_tag  iterator_category; 
    typedef std::ptrdiff_t      difference_type; 

我如何使用操作

avltree<char,int> myTree; 
    myTree.insert(std::pair<char,int>('a',1)); 
    myTree.insert(std::pair<char,int>('b',2)); 
    myTree.insert(std::pair<char,int>('c',3)); 

    avltree<char,int>::reverse_iterator rit = myTree.rbegin(); 

    for(; rit != myTree.rend(); ++rit) //fails on this line 
    { 
    } 

和迭代器類(常量性是一回事,但有一個const VALUE_TYPE)

template <class tree> 
class avl_iterator { 
public: 
    typedef typename tree::node     node; 
    typedef typename tree::node_ptr    node_ptr; 
    typedef typename tree::value_type*   pointer;// for std reverse iterator 
    typedef typename tree::value_type&   reference; 
    typedef typename tree::const_node_ptr  const_node_ptr; 
    typedef typename tree::utilities   utilities; 
    typedef typename tree::value_type   value_type; 
    typedef std::bidirectional_iterator_tag  iterator_category; 
    typedef std::ptrdiff_t      difference_type; 

private: 
    friend class const_avl_iterator<tree>; 
    node_ptr _node; 
public: 
    avl_iterator() : _node() { } 
    avl_iterator(const node_ptr node) : _node (node) { } 
    avl_iterator(const avl_iterator& iterator) { 
     (*this) = iterator; 
    } 
    ~avl_iterator() { _node = NULL; } 

    avl_iterator& operator=(const avl_iterator& rhs) { 
     _node = rhs._node; 
     return (*this); 
    } 
    avl_iterator& operator=(const const_avl_iterator<tree>& rhs) { 
     _node = rhs._node; 
     return (*this); 
    } 

    bool operator == (const avl_iterator& rhs) const { return (_node == rhs._node); } 
    bool operator != (const avl_iterator& rhs) const { return (_node != rhs._node); } 

    avl_iterator& operator++() 
    { 
     _node = utilities::next_node(_node); 
     return (*this); 
    } 
    avl_iterator operator ++(int) { 
     avl_iterator temp(*this); 
     ++(*this); 
     return(temp); 
    } 

    avl_iterator& operator --() { 
     _node = utilities::prev_node(_node); 
     return (*this); 
    } 

    avl_iterator operator -- (int) { 
     avl_iterator temp(*this); 
     --(*this); 
     return(temp); 
    } 

    value_type& operator *() const { 
     assert(! utilities::is_header(_node)); 
     return _node->_value; 
    } 

    value_type* operator ->() const { 
     assert(! utilities::is_header(_node)); 
     return &_node->_value; 
    } 
}; 

和樹類:

template < 
    class Key, 
    class Type, 
    class Traits = std::less<Key>, 
    class Allocator = std::allocator<std::pair<Key const, Type>> 
    > 
    class avltree { 
    private: 
     typedef avltree< Key, Type, Traits, Allocator>      tree; 
    public: 
     typedef std::pair<const Key, Type>         value_type; 
     typedef Allocator             allocator_type; 
     typedef typename allocator_type::size_type       size_type; 
     typedef typename allocator_type::reference       reference; 
     typedef Key               key_type; 
     typedef Type              mapped_type; 
     typedef Traits              key_compare; 
     typedef typename avl_node<tree>         node; 
     typedef typename node::node_ptr          node_ptr; 
     typedef typename node::const_node_ptr        const_node_ptr; 
     typedef typename avl_utilities<tree>        utilities; 
     typedef typename avl_iterator<tree>        iterator; 
     typedef typename const_avl_iterator<tree>       const_iterator; 
     typedef typename std::reverse_iterator<iterator>     reverse_iterator; 
     typedef typename std::reverse_iterator<const_iterator>    const_reverse_iterator; 
    private: 
     node_ptr _header; 
     std::size_t _size; 
     key_compare _comparer; 
     allocator_type _alloc; 
    public: 
      //c'tors and d'tors 
     //******************************************************* 
     //Iterators 
     //******************************************************* 
     iterator    begin()   { return iterator(node::get_left(_header)); } 
     const_iterator   begin() const { return const_iterator(node::get_left(_header)); } 
     const_iterator   cbegin() const { return const_iterator(node::get_left(_header)); } 
     iterator    end()   { return iterator(_header); } 
     const_iterator   end() const  { return const_iterator(_header); } 
     const_iterator   cend() const { return const_iterator(_header); } 

     reverse_iterator  rbegin()  { return reverse_iterator(_header); } 
     const_reverse_iterator rbegin() const { return const_reverse_iterator(_header); } 
     const_reverse_iterator crbegin() const { return const_reverse_iterator(_header); } 
     reverse_iterator  rend()   { return reverse_iterator(node::get_left(_header)); } 
     const_reverse_iterator rend() const { return const_reverse_iterator(node::get_left(_header)); } 
     const_reverse_iterator crend() const { return const_reverse_iterator(node::get_left(_header)); } 
     bool operator==(const tree& right) 
     { 
      if(_size != right.size()) 
      { 
       return false; 
      } 

      const_iterator lhs = cbegin(); 
      const_iterator rhs = right.cbegin(); 
      while(lhs != cend() && rhs != right.cend()) 
      { 
       if(lhs->first != rhs->first || lhs->second != rhs->second) 
       { 
        return false; 
       } 
       ++lhs; 
       ++rhs; 
      } 
      return true; 
     } 
     bool operator!=(const tree& right) 
     { 
      return (!(*this == right)); 
     } 
     bool operator<(const tree& right) 
     { 
      const_iterator lhs = cbegin(); 
      const_iterator rhs = right.cbegin(); 
      while(lhs != cend() && rhs != right.cend()) 
      { 
       if(lhs->first != rhs->first || lhs->second != rhs->second) 
       { 
        if(lhs->first < rhs->first || lhs->second < rhs->second) 
        { 
         return true; 
        }      
       } 
       ++lhs; 
       ++rhs; 
      } 
      return false; 
     } 
     bool operator>(const tree& right) 
     { 
      return (right < *this); 
     } 
     bool operator<=(const tree& right) 
     { 
      return (!(right < *this)); 
     } 
     bool operator>=(const tree& right) 
     { 
      return (!(*this < right)); 
     } 
}; 
//******************************************************* 
//Relation Operators 
//******************************************************* 
template<class tree> 
bool operator==(const tree& left,const tree& right) 
{ 
    if(left.size() != right.size()) 
    { 
     return false; 
    } 

    tree::const_iterator lhs = left.cbegin(); 
    tree::const_iterator rhs = right.cbegin(); 
    while(lhs != left.cend() && rhs != right.cend()) 
    { 
     if(lhs->first != rhs->first || lhs->second != rhs->second) 
     { 
      return false; 
     } 
     ++lhs; 
     ++rhs; 
    } 
    return true; 
} 
template<class tree> 
bool operator!=(const tree& left,const tree& right) 
{ 
    return (!(left == right)); 
} 
template<class tree> 
bool operator<(const tree& left,const tree& right) 
{ 
    tree::const_iterator lhs = left.cbegin(); 
    tree::const_iterator rhs = right.cbegin(); 
    while(lhs != left.cend() && rhs != right.cend()) 
    { 
     if(lhs->first != rhs->first || lhs->second != rhs->second) 
     { 
      if(lhs->first < rhs->first || lhs->second < rhs->second) 
      { 
       return true; 
      }      
     } 
     ++lhs; 
     ++rhs; 
    } 
    return false; 
} 
template<class tree> 
bool operator>(const tree& left,const tree& right) 
{ 
    return (right < left); 
} 
template<class tree> 
bool operator<=(const tree& left,const tree& right) 
{ 
    return (!(right < left)); 
} 
template<class tree> 
bool operator>=(const tree& left,const tree& right) 
{ 
    return (!(left < right)); 
} 
}//end namespace avl 
+1

它編譯?智能感知不是一個編譯器,不應該被信任。 – 2013-03-01 14:40:48

+0

不,它給出以下錯誤:錯誤錯誤C2593:'operator!='含糊不清 – 2013-03-01 14:41:29

+0

您能提供一個小例子來檢查它嗎? – RiaD 2013-03-01 14:45:32

回答

4

在此行中:

rit != myTree.rend() 

你比較這兩類對象:

avltree<char,int>::reverse_iterator 

這又一個別名:

std::reverse_iterator<avl_iterator<char, int>::iterator> 

C++標準庫定義,在std::命名空間中,一個模板化的operator !=這是一個精確匹配fo r比較反向迭代器(見第24段)。在C++ 11標準)5:

template <class Iterator1, class Iterator2> 
bool operator!=(
    const reverse_iterator<Iterator1>& x, 
    const reverse_iterator<Iterator2>& y) 

不過,你也有這樣的:

template<class tree> bool operator!=(const tree& left,const tree& right) 

因爲模板是不受約束的(即使模板參數被命名爲tree,這不意思是模板只接受樹),這也是一個完全匹配,但對於反向迭代器模板化的operator !=仍然更加專業化。

因此,電話應該不是是不明確的。我認爲這是一個編譯器錯誤。


要解決此問題,請確保您的不平等運營商的樹木只接受樹,這無論如何是一個好主意(你真的不希望你的運營商畢竟任何比較):

template<class T> bool operator!=(const avltree<T>& left,const avltree<T>& right) 
+0

完美地工作,謝謝 – 2013-03-01 15:18:23

2

您的operator !=試圖比較任何時間,包括reverse_iterator s,您可以嘗試使用

template<class T> bool operator!= (const avltree<T>& left,const avltree<T>& right) {  
    return (!(left == right)); 
} 
2

看起來像一個破碎的編譯器。

template<typename Iter> 
bool std::operator!=(const std::reverse_iterator<Iter>&, 
        const std::reverse_iterator<Iter>&); 

template<class tree> 
bool avl::operator!=(const tree&, const tree&); 

這樣表達rit != myTree.rend()不應該含糊 「比更專業的」。

不過,聲明一些可以應用!=任意兩個相同類型的對象是一個危險的想法。

-1

您嘗試將const_reverse_iterator與reverse_iterator進行比較,對rend()的調用將始終使用非const過載(如果可用)。對此的修復應該是顯而易見的。如果我沒有記錯的話,一些早期的std :: set實現也存在同樣的問題。

總之,有一個很好的辦法,將解決此問題,同時恕我直言,更顯優雅:

for(container::iterator it=c.begin(), end=c.end(); it!=end; ++it) 
    ... 

換句話說,總是用一對在for循環的頭部聲明迭代器。使用C++ 11的「自動」,這變得更短。儘管使用任何半路現代編譯器對end()的單個調用不會更快,但我個人覺得它更清晰一點。

+0

'rbegin()','rend()'都是'reverse_iterators' – RiaD 2013-03-05 12:02:22

+0

你錯過了這一點。如果逐字採納,你的陳述甚至是錯誤的,因爲它們超載。每個'begin()'和'end()'的重載將返回一個'const_reverse_iterator',另一個重載'reverse_iterator'。雖然從非const轉換爲const顯然工作,但這並不能保證兩者之間的比較。 – 2013-03-05 23:41:54