итератор — Оператор! = является неоднозначным для std :: reverse_iterator Переполнение стека

Я работаю над контейнером, который реализует свой собственный итератор, который я использую с std :: reverse_iterator<> чтобы получить функциональность обратной итерации. Я могу назначить обратный итератор для рендеринга или запуска, но когда я пытаюсь получить доступ к любой из его функций (например,! = Или ==), я получаю это:

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;

итератор typedefs:

    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_iterator это то же самое, но с 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

5

Решение

На этой линии:

rit != myTree.rend()

Вы сравниваете два объекта типа:

avltree<char,int>::reverse_iterator

Что в свою очередь является псевдонимом для:

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

Стандартная библиотека C ++ определяет в std:: пространство имен, шаблонное operator != что является точным соответствием для сравнения обратных итераторов (см. пункт 24.5 стандарта C ++ 11):

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)
4

Другие решения

Ваш operator != пытается сравнить в любое время, в том числе reverse_iterators, вы можете попробовать использовать

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() не должно быть двусмысленным.

Тем не менее, объявив что-то, что может применяться != в любой два объекта одного типа — опасная идея.

2

Вы пытаетесь сравнить const_reverse_iterator с reverse_iterator, вызов rend () всегда будет использовать неконстантную перегрузку, если она доступна. Исправление для этого должно быть очевидным. Та же проблема существовала с некоторыми ранними реализациями std :: set, если я правильно помню.

Во всяком случае, есть хороший подход, который обойдет эту проблему, будучи ИМХО еще более элегантным:

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

Другими словами, всегда используйте пару итераторов, которые объявлены в заголовке цикла for. используя «авто» в C ++ 11, это становится еще короче. Хотя одиночный вызов end () не является быстрым с любым наполовину современным компилятором, я лично нахожу это немного яснее.

-1
По вопросам рекламы [email protected]