简体   繁体   中英

Dereference operator with iterator and const_iterator

I have been struggling with a problem related to developing a template class iterator. More specifically in the proper way to implement the dereferencing operator (operator*()) so that the template class covers the case for both iterator and const_iterator. I am sure I am missing something obvious here but I cannot see it. Could you help me?

Suppose I have the following template class ( Iterator.hpp ) that I want to use to iterate over objects of classes that wrap a STL container (std::map, std::vector) as a private member.

#include <iostream>
#include <iterator>

template<typename iterator_type>
class Iterator
{
  public:

    /** \brief Type to be returned when de-referencing the iterator*/
    typedef typename std::iterator_traits<iterator_type>::value_type value_type;

    /** \brief Constructor*/
    inline Iterator(iterator_type i) : iterator(i) {}

    /** \brief Dereference operator */ 
    inline value_type& operator*() {return *iterator;}

    inline const value_type& operator*() const {return *iterator;}

    /** \brief Increment operator */
    inline Iterator & operator++() {++iterator; return *this;}

    /** \brief Inequality operator */
    inline bool operator!=(const Iterator & right) const
                                            {return iterator != right.iterator;}

    /** \brief Inequality operator */
    inline bool operator!=(const iterator_type & right) const
                                                     {return iterator != right;}

    /** \brief Distance between iterators */
    inline int operator-(const Iterator & right) const
                               {return std::distance(right.iterator, iterator);}

    /** \brief Distance between iterators */
    inline int operator-(const iterator_type & right) const
                               {return std::distance(right, iterator);}

  private:

    /** \brief Internal member, of iterator type*/
    iterator_type iterator;
};

Now suppose I have a main ( example.cpp ) that creates a vector of ints and tries to print them out using a const_iterator , like so:

#include "Iterator.hpp"
#include <vector>

typedef std::vector<int> IntVector;

int main(int argc, char* argv[]) {

    unsigned int nElements(10);
    IntVector intVector(nElements);

    for (unsigned int i = 0; i < nElements; ++i) {
        intVector[i] = i;
    }

    std::cerr << "    Printout of the vector \n";
    Iterator<IntVector::const_iterator> it(intVector.begin());
    for(; it != intVector.end(); ++it) {

        std::cerr << *it << "\n";

    }


}

If I try to compile this code: g++ example.cpp -std=c++11 -stdlib=libc++ . I will get the following error:

./Iterator.hpp:16:48: error: binding of reference to type 'value_type' (aka 'int') to a value of type 'const int' drops
      qualifiers
        inline value_type& operator*() {return *iterator;}
                                               ^~~~~~~~~
example.cpp:19:22: note: in instantiation of member function 'Iterator<std::__1::__wrap_iter<const int *> >::operator*'
      requested here
        std::cerr << *it << "\n";
                     ^
1 error generated.

I thought that by simply overloading the operator*() with the const and non-const versions as done in the Iterator.hpp template would suffice, but that is obviously not the case. Do you know what I am missing here? any help on this issue would be greatly appreciated.

Many thanks!

const_iterator and iterator are different types, and should be implemented as separate types. const_iterator should return a const reference in it's dereference operator, normal iterator returns modifiable reference.

You should not confuse const_iterator with const iterator .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM