Re: about the interator of map
void print_data(const Data& stats)
{
double sum = 0;
int count = 0;
for(Data::iterator p = stats.begin(); p != stats.end(); ++p)//when
i modify iterator to const_iterator it can work
you just answered your own question.
'stats' is a const reference to an instance of std::map
so stats.begin( ) returns a const_iterator because
stats.begin( ) resolves to the const version
of std::map< ... >::begin( ) which returns const_iterator.
compiler cannot convert typedef-ed std::map< ... >::const_iterator to
non const std::map< ... >::iterator because for the compiler they are
just different types with no means to convert from the const version
to the non const version (like conversion operators or constructors).
for your specific compiler (gcc) these iterators are implemented as
_Rb_tree_iterator and _Rb_tree_const_iterator and if you take a look
at include/c++/bits/stl_tree.h you can see their implementation.
so, with your const Data & use
for(Data::const_iterator p = stats.begin(); ...
it also shows your intention to only read the content of p (the
iterator).
note that _Rb_tree_const_iterator has conversion constructor from
_Rb_tree_iterator:
template<typename _Tp>
struct _Rb_tree_const_iterator
{
// ...
typedef _Rb_tree_iterator<_Tp> iterator;
// ...
_Rb_tree_const_iterator(const iterator& __it)
: _M_node(__it._M_node) { }
// ...
};
what this means to you is: you can use const iterator on non const
data:
void print_data( /* const */ Data& stats) {
// ...
for(Data::const_iterator p = stats.begin(); p != stats.end(); ++p)
// ...
}
because the compiler can convert the non const iterator returned by
stats.begin( ) to const iterator using above constructor.
the != operator works similar (with one user defined conversion).
bottom rule:
const container can use only const_iterator;
non const container can use both allowing you to express your
intentions.
cheers,
gil
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]