2013-03-01 151 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