Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong type of iterator used

Tags:

c++

I'm implementing a map as part of my HW assignment. The map should support two types of iterators:

  • iterator - allows changing the map.
  • constant_iterator - doesn't allow changing the map.

I have the following methods:

Map::const_iterator begin() const;
Map::const_iterator end() const;
Map::iterator begin();
Map::iterator end(); 

However when I test my implementation with the following code:

for(Map<std::string,int>::const_iterator it = msi.begin(); it != msi.end(); ++it) {
    std::cout << *it << std::endl;
}

I get the following problem:

map_test.cpp:49:43: error: no viable conversion from 'Map<basic_string<char>, int>::iterator' to 'Map<std::string, int>::const_iterator'
        for(Map<std::string,int>::const_iterator it = msi.begin(); it != msi.end(); ++it) {
                                                 ^    ~~~~~~~~~~~
./map_new.h:57:3: note: candidate constructor not viable: no known conversion from 'Map<basic_string<char>, int>::iterator' to 'const
      Map<basic_string<char>, int>::const_iterator &' for 1st argument
                const_iterator(const Map<KeyType, DataType>::const_iterator& sIterator): 
                ^

Which means that the compiler selects the wrong begin/end methods.

How can I solve this problem?

like image 592
Naftaly Avatar asked Jan 09 '14 14:01

Naftaly


People also ask

How can we prevent iterator invalidation?

To avoid invalidation of references to elements you can use a std::deque if you do not insert or erase in the middle. To avoid invalidation of iterators you can use a std::list.

What is difference between iterator and constant iterator?

A const iterator points to an element of constant type which means the element which is being pointed to by a const_iterator can't be modified. Though we can still update the iterator (i.e., the iterator can be incremented or decremented but the element it points to can not be changed).

How do you dereference an iterator?

3. Dereferencing: An input iterator can be dereferenced, using the operator * and -> as an rvalue to obtain the value stored at the position being pointed to by the iterator. 4. Incrementable: An input iterator can be incremented, so that it refers to the next element in the sequence, using operator ++().


2 Answers

By providing an implicit conversion from iterator to const_iterator. You can do this by giving const_iterator a constructor that takes an iterator, or by providing iterator with a const_iterator conversion operator.

This approach is used in the standard library when you do this kind of thing:

std::vector<int> v;
std::vector<int>::const_iterator it = v.begin();

In C++11, you have methods that return const_iterators directly, even for non-const instances. But these need a different name, because you cannot overload by return type:

std::vector<int> v;
std::vector<int>::const_iterator it = v.cbegin();
like image 113
juanchopanza Avatar answered Oct 05 '22 06:10

juanchopanza


You may also create cbegin() and cend() member functions that will return const iterators.

like image 44
Nikita Avatar answered Oct 05 '22 06:10

Nikita