std::distance and const vs. non-const iterators

Apr 10, 2009 at 8:52pm
Hmm, so

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <iterator>
#include <vector>

struct Foo {
   typedef std::vector<char> Container;

   Foo() : vec( 10, 'x' ) {}
 
   void bar() {
       typedef Container::const_iterator ConstIter;
       for( ConstIter i = vec.begin(); i != vec.end(); ++i )
           std::cout << "Element #" << std::distance( vec.begin(), i )
                     << " is " << *i << std::endl;
   }

    Container vec;
};

int main() {
    Foo f;
    f.bar();
}


does not compile, giving the complaint


foo.cpp: In member function `void Foo::bar()':
foo.cpp:13: error: no matching function for call to `distance(
__gnu_cxx::__normal_iterator<char*, std::vector<char, std::allocator<char> >
>, Foo::bar()::ConstIter&)'



because the compiler wants to call the non-const version of vector<char>::begin() since the member function bar() is not const, but the other parameter to std::distance() is a const_iterator and std::distance() of course wants two iterators of the same type. So apparently either there is no implicit conversion function from iterator to const_iterator or the compiler can't figure to call it. Anyway...

So, assuming that I cannot make the member function const for reasons far too complicated to go into here, does anyone have a slick way to solve the problem that is not either 1) change the const_iterator to iterator, or 2) use an obnoxious const_cast?
Apr 10, 2009 at 9:01pm
you could make another const_iterator variable to hold vec.begin(), but that's also inelegant. But sticking in a (ConstIter) isn't so bad. Don't need an actual const_cast.
Last edited on Apr 10, 2009 at 9:04pm
Apr 10, 2009 at 9:06pm
what about this:
1
2
3
const Container &v = vec;
std::cout << "Element #" << std::distance( v.begin(), i )
    << " is " << *i << std::endl;
Last edited on Apr 10, 2009 at 9:07pm
Apr 10, 2009 at 10:33pm
Yah, I'm trying to avoid an extra local variable because that's just me :)

I hate being defeated by the language/compiler and having to make another local variable...
Apr 11, 2009 at 11:57am
Why don't you use just the ConstIter constructor?
std::distance( ConstIter(vec.begin()), i )
Apr 11, 2009 at 1:49pm
Aha... why did I not think of that???

That'll work... no more lines of code needed :)

Thanks.
Topic archived. No new replies allowed.