Consider the following code:
#include <vector>
using namespace std;
struct foo
{
void bar()
{
}
};
int main()
{
{
vector<foo*> a;
a.push_back(new foo());
a.push_back(new foo());
a.push_back(new foo());
vector<foo*>::const_iterator itr = a.begin();
(*itr)->bar(); // compiles - this becomes more confusing
// when found in a const method. On first
// glance, one will (or at least me) may
// assume that bar() must be const if the
// method where it is being called from is
// const
// The above compiles because internally, this is what happens
// (ignore the fact that the pointer has not been newd)
foo* const * element;
(*element)->bar(); // compiles
// What I would expect however (maybe it is just me) is for const_iterator
// to behave something like this
const foo* const_element;
const_element->bar(); // compile error
}
{
vector<foo> a;
a.resize(10);
vector<foo>::const_iterator itr = a.begin();
itr->bar(); // compile error
}
}
I understand why it can be called. The const_iterator stores the const-ness like this: const T* which for the pointer translates to foo* const * and for the object foo const *.
So my question is, why are we allowed to call a non-const member function from a const_iterator? Isn’t it more intuitive to not allow the call to a non-const member function from a const_iterator? Shouldn’t the design of iterators with the const option prevent this behaviour?
The more important question now is this: What if I want const_iterator to disallow calling of non-const member functions of the pointed to object?
It does. You’re just expecting it to be a different operation.
As you discovered, a container of pointers… contains pointers, not objects. Therefore, a
const_iteratorto such pointers means that the pointers are constant, not the objects they point to.That’s not going to change, nor should it. The standard library containers are generally designed to contain full-fledged objects, not pointers. So they shouldn’t encourage users to make
vectors of pointers and other dubious constructs.If you really need a
vectorto contain pointers, then you should use a container that is actually designed to do so. Like Boost’s pointer container classes. Theirconst_iteratorsmake the objects being pointed toconstproperly. They also do other useful things, like own the objects they point to (so that they are properly deleted) and so forth.