Consider the following
template<typename T>
struct Wrapper{ T t; };
template<typename T>
struct Variant1 : public Wrapper< T >
{
// ... Member types, static members, non virtual functions ... //
}
template<typename T>
struct Variant2 : public Wrapper< T >
{
// ... Member types, static members, non virtual functions ... //
}
Is there a way to convert for example Variant1<int> &
to Variant2<int> &
without triggering UB. I've searched SO for answers but most questions related to this are of the form "Is it safe to do it this specific way". My question is there any safe way to do this.
Some ways I found are:
( Variant2< int > & ) value
or the same using reinterpret_cast
Wrapper<int> &
and then into Variant2<int> &
Edit
Specific Example:
Variant1< int > val{ .t = 5 };
Variant2< int > & ref = ?Convert?( val );
Goal:
The goal would be to be able to create "Tagged" types which simply act as a proxy around the wrapped type and would prevent accidental mixing of two different tags. However sometimes it is necessary to explicitly convert from one tag to another. This should be a compile time thing, and thus not really cause any overhead.
Is there a way to convert for example
Variant1<int> &
toVariant2<int> &
without triggering UB
No. It also defeats the whole point of your polymorphism if you're just reinterpreting one derived class as another.
What is the point of Wrapper
then, and why couldn't you just use std::any
?
The goal would be to be able to create "Tagged" types which simply act as a proxy around the wrapped type and would prevent accidental mixing of two different tags.
This sounds like Wrapper
should contain T
and also a separate tag type as a member.
Alternatively, a std::variant<Variant1<int>, Variant2<int>>
might make sense, if every VariantX
can be constructed from a Wrapper
.
In such a case, you could use std::visit
to obtain any "tagged type" you want.
In any case, you haven't provided enough details for a full solution.