It often happens to me to have a a container C
(or whatever kind of wrapper class, even smart pointers) for a type T1
, and want to convert such C<T1>
into C<T2>
, where T2
is compatible to T1
.
C++ doesn't allow me to directly convert the whole container, and forcing a reinterpet_cast
would result in undefined behavior, so I would need to create a new C<T2>
container and repopulate it with C<T1>
items casted as T2
. This operation could be quite expensive, both in time and space.
Moreover for many cases I'm pretty sure that forcing a reinterpret_cast
would work fine with the code compiled by any compiler ever existed, for example when T2
is T1 const
, or when T1
and T2
are pointers.
Is there any clean and efficient way to convert a C<T1>
in a C<T2>
?
For example a container_cast
operator(/function?) that creates and repopulates a C<T2>
if and only if it wouldn't be binary compatible to C<T1>
?
Besides all the other issues dealt by others:
There is a basic problem in the approach that is not technical at all. Provided that an apple is a fruit, neither a container of fruits is a container of apples (trivially demonstrated) nor a container of apples is a container of fruit. Try to fit a watermelon in a box of apples!
Going to more technical details, and dealing specifically with inheritance where no conversion is even required, (a derived object is already an object of the base class), if you were allowed to cast a container of the derived type to the base type, then you could add invalid elements to the container:
The last line is perfectly correct: you can add a
watermelon
to avector<fruit*>
. But the net effect is that you have added awatermelon
to avector<apple*>
, and in doing so you have broken the type system.Not everything that looks simple in a first look is in fact sane. This is similar to the reason why you cannot convert an
int **
to aconst int **
even if the first thought is that it should be allowed. The fact is that allowing so would break the language (in this case const correctness):Which brings us back to the example you provided in one of the comments to another answer (to prove the point in general, I'll use a vector and instead of a set since set contents are immutable):