[lug] OT: C++ question, const_iterator design

Tkil tkil at scrye.com
Mon Jun 2 00:40:51 MDT 2003


>>>>> "DS" == D Stimits <stimits at attbi.com> writes:

DS> To make a long story short, someone pointed out that the object I
DS> was using had to be const, which I did not believe was the case;
DS> however, after looking at it for a week, I found he was right. So
DS> the whole question was pointless, the const version of begin() was
DS> only called because the object was const, and had nothing to do
DS> with operator= overloads, nor method signatures.

Hm.  Well, as much as I enjoy being right (hoo boy, do I enjoy it), I
think that you might be missing the forest for the trees here.

Your goal is to be able to do a simple assignment from a (non-const)
".begin()" call into a const_iterator.  To quote Denis Leary: "Where's
the problem"?

A const_iterator has a stronger promise than a simple iterator; as
such, implementing a const_iterator as a dumbed-down iterator for a
given container makes perfect sense.

Which gets back to something you mentioned earlier: there's might not
be an automatic conversion, but if you build your const_iterator
constructor so that it can take a non-const element, you should be
fine.

This is acceptable, since "iterator" says "I can move around, examine,
and modify the contents of the associated container" while
"const_iterator" only offers "move around and examine" capabilities.
Put another way, you can use an iterator as a const_iterator, but not
conversely.

In this case, since you're creating your own iterator objects, it
should be pretty straightforward to add the ability to create a
const_iterator from a (non-const) iterator.

The GNU STL has the following bit of code, which might be worth
investigating:

      // Allow iterator to const_iterator conversion
      template<typename _Iter>
      inline __normal_iterator(const __normal_iterator<_Iter, _Container>& __i)
	: _M_current(__i.base()) { }

(in bits/stl_iterator.h)

Without being able to fully parse all the underscored grotesqueness of
that code, I'm relying on the comment to infer that this magic allows
any normal (non-const) iterator to be promoted to a const_iterator
(which, as explained previously, is perfectly reasonable, and ought to
be basically automatic).

So, if you want to create a const_iterator for your particular custom
container, taking a normal iterator and simply wrapping it so that it
is constant is not the end of the world, at least from an external
semantics point of view.

If your const_iterator is substantially different from your iterator
(say, for threading reasons you can use read-only locks in your
const_iterator, while you require read/write locks for your normal
iterator types) then you are in for a rougher road -- but remember
that, as a library provider, you are allowed to take "liberties" with
your classes that users are not supposed to take.

In particular, your const_iterator class could certainly be declared a
friend of your normal iterator class, and should thus be able to grab
the current location and container from the iterator class.  So all is
not lost.

Happy hacking,
t.



More information about the LUG mailing list