How to convert const_iterators to iterators using std::distance and std::advance

A short posting demonstrating how to remove the const-ness of a const_iterator, given that it is not possible to use re-casting along the lines of const_cast to convert from const_iterator to iterator.

Consider the following example:

#include <iostream>
#include <vector>

class A
{
public:
	A( int x ) { val = x; }
	void DoStuff() { std::cout << "val = " << val << std::endl; }
private:
	int val;
};

int main()
{
	// Initialise vector with pointers to A objects
	A* a[] = { new A( 1 ), 
		       new A( 2 ), 
			   new A( 3 ), 
			   new A( 4 ) };

	std::vector<A*> v( a, a + 4 );	
	
	// Iterate over the elements
	for ( std::vector<A*>::const_iterator cit = v.begin(); 
		  cit != v.end(); 
		  ++cit )
	{
		std::vector<A*>::iterator it = cit;
	}
	
	return 0;
}

Which results in the following compilation error:

error C2440: 'initializing' : cannot convert from 'std::_Vector_const_iterator<_myvec>' to 'std::_Vector_iterator<_myvec>'

One approach, already explained in much detail over at Dr Dobbs’ site is that of defining an iterator which is made to move linearly until it reaches the element to which const_iterator points.

First define some suitable typedefs for your iterators and const_iterators (iter and const_iter), and use std::advance and std::distance to access the iterators. Like so:

#include <iostream>
#include <vector>

class A
{
public:
	A( int x ) { val = x; }
	void DoStuff() { std::cout << "val = " << val << std::endl; }
private:
	int val;
};


// Define our iterators
typedef std::vector<A*>::iterator iter;
typedef std::vector<A*>::const_iterator c_iter;

int main()
{
	// Initialise vector with pointers to A objects
	A* a[] = { new A( 1 ), 
		       new A( 2 ), 
			   new A( 3 ), 
			   new A( 4 ) };

	std::vector<A*> v( a, a + 4 );	
	
	// Iterate over the elements
	iter it = v.begin();	
	for ( c_iter cit = v.begin(); cit != v.end(); ++cit )
	{		
		std::advance (it, std::distance<c_iter>(it, cit ) );
		(*it)->DoStuff();
	}
		
	return 0;
}

This solving the problem of compilation and giving us access to the iterators we want:

Leave a Reply