I've been fiddling with templates and compile time stuff i implemented a variant container and wanted some opinions and recommendations this is just a learning exercise, a couple template classes not included here are tl_type_at
which gives the type in a typelist at a given index; and tl_index_of
which gives the index of the first occurrence of the given type in a typelist:
template <size_t Index, typename T, typename ... Ts>
struct variant_deleter
{
variant_deleter<Index + 1, Ts...> next;
void operator()(size_t HeldIndex, void* HeldPtr) const
{
if(Index == HeldIndex)
delete static_cast<T*>(HeldPtr);
else
next(HeldIndex, HeldPtr);
}
};
template <size_t Index, typename T>
struct variant_deleter<Index, T>
{
void operator()(size_t HeldIndex, void* HeldPtr) const
{
if(Index == HeldIndex)
delete static_cast<T*>(HeldPtr);
}
};
struct bad_variant_access {};
template <typename T, typename ... Ts>
struct variant
{
typedef typelist<T, Ts...> types;
variant()
: union_(new T())
, held_(0)
{}
template <typename I>
variant(I Init)
: union_(new typename tl_type_at< tl_index_of<I, types>::index, types >::type())
, held_(tl_index_of<I, types>::index)
{}
~variant()
{ variant<T, Ts...>::deleter_(held_, union_); }
template <typename P>
variant<T, Ts...>& operator=(const P& rhs)
{
union_ = new(union_) P(rhs);
held_ = tl_index_of<P, types>::index;
return *this;
}
template <typename G>
G& get()
{
if(held_ == tl_index_of<G, types>::index)
return *static_cast<G*>(union_);
else
throw bad_variant_access {};
}
private:
void* union_;
size_t held_;
static const variant_deleter<0, T, Ts...> deleter_;
};