Operator! = Ambiguous for std :: reverse_iterator C ++

I am working on a container that implements its own iterator, which I use with std :: reverse_iterator <> to get reverse iteration functionality. I can assign a reverse iterator for parsing or rbegin, but when I try to access any of its functionality (like! = Or ==), I get the following:

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

Overloading my iterator:

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

and my reverse iterator implementation

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;

and typedefs 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;

How do I use the operator

    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
    {
    }

and iterator class (const_iterator is the same thing, but with constant 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;
    }
};

and tree class:

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
source share
4 answers

In this line:

rit != myTree.rend()

You are comparing two types of objects:

avltree<char,int>::reverse_iterator

, , :

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

++ std:: operator !=, (. 24.5 ++ 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_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() .

, , != , .

+2

const_reverse_iterator _, rend() , . . std:: set, .

Anyway, there is a good approach that will work around this issue until IMHO is even more elegant:

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

In other words, always use a pair of iterators declared in the for-loop header. using C ++ 11 "auto", it gets even shorter. While a single end () call is not accelerated with any intermediate compiler, I personally find it a bit clearer.

-1
source

All Articles