L
Lorenzo Castelli
This is an old problem of mine.
Basically I have an abstract base class which represents a generic iterator
over a collection of elements, and various derived classes that implement
the traversing on specific data structures.
For each iterator I want to be able to specify the four possible const
combinations, corresponding to the various [const] void* [const] for
pointers, with the possibility to perform conversions from non-const to
const just like you can do with pointers.
Also I obviously want the conversions from the specific iterators to the
generic base.
The first solution I employed was to create a hierarchy like
AbstractConstIterator <-- AbstractIterator <-- ConcreteIterator.
Client code used just AbstractConstIterator and AbstractIterator, so that
all possible combinations of const and all conversions were possible.
Unfortunately the elements pointed by the iterators are themselves a
hierarchy, and in particular there is an AbstractElement class and some
derived ConcreteElement. Each ConcreteIterator corresponds to a particular
ConcreteElement.
Also the various ConcreteElement classes extend the functionalities
available in the abstract base class with some new methods specific of the
type.
Since the client code sometimes needs to access those specific
functionalities, I had to make ConcreteIterator externally visible and
provide the specific ConcreteElements using covariance return.
In order to provide the four possible combinations of const and all the
required conversions, I changed the hierarchy this way:
- AbstractConstIterator <-- AbstractIterator
- AbstractConstIterator <-- ConcreteConstIterator
- AbstractIterator, ConcreteConstIterator <-- ConcreteIterator
Then I made the two inheritances from AbstractConstIterator virtual, in
order to avoid a double base class in ConcreteIterator (among the other
things, to avoid problems when comparing pointers to AbstractConstIterator
for equality).
Now the problem is that, while this design works correctly and provides the
functionalities I need, I don't like the fact that I'm using a run-time
facility (virtual inheritance) only to solve a compile-time problem
(const-correctness).
I thought this scenario were pretty common, but I haven't been able to find
previous discussions about it.
Do you have any suggestion?
Basically I have an abstract base class which represents a generic iterator
over a collection of elements, and various derived classes that implement
the traversing on specific data structures.
For each iterator I want to be able to specify the four possible const
combinations, corresponding to the various [const] void* [const] for
pointers, with the possibility to perform conversions from non-const to
const just like you can do with pointers.
Also I obviously want the conversions from the specific iterators to the
generic base.
The first solution I employed was to create a hierarchy like
AbstractConstIterator <-- AbstractIterator <-- ConcreteIterator.
Client code used just AbstractConstIterator and AbstractIterator, so that
all possible combinations of const and all conversions were possible.
Unfortunately the elements pointed by the iterators are themselves a
hierarchy, and in particular there is an AbstractElement class and some
derived ConcreteElement. Each ConcreteIterator corresponds to a particular
ConcreteElement.
Also the various ConcreteElement classes extend the functionalities
available in the abstract base class with some new methods specific of the
type.
Since the client code sometimes needs to access those specific
functionalities, I had to make ConcreteIterator externally visible and
provide the specific ConcreteElements using covariance return.
In order to provide the four possible combinations of const and all the
required conversions, I changed the hierarchy this way:
- AbstractConstIterator <-- AbstractIterator
- AbstractConstIterator <-- ConcreteConstIterator
- AbstractIterator, ConcreteConstIterator <-- ConcreteIterator
Then I made the two inheritances from AbstractConstIterator virtual, in
order to avoid a double base class in ConcreteIterator (among the other
things, to avoid problems when comparing pointers to AbstractConstIterator
for equality).
Now the problem is that, while this design works correctly and provides the
functionalities I need, I don't like the fact that I'm using a run-time
facility (virtual inheritance) only to solve a compile-time problem
(const-correctness).
I thought this scenario were pretty common, but I haven't been able to find
previous discussions about it.
Do you have any suggestion?