2
\$\begingroup\$

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_;
};
Pieter Witvoet
8,27916 silver badges28 bronze badges
asked Sep 12, 2017 at 8:57
\$\endgroup\$
1
  • \$\begingroup\$ As explained in the help center, please do not modify your code, because it invalidates existing answers. If you want your updated code to be reviewed you can post a new question for it. \$\endgroup\$ Commented Sep 14, 2017 at 8:17

1 Answer 1

2
\$\begingroup\$

Some issues:

  • the assignment operator doesn't call the destructor of the existing data, before setting a new value (results in UB, likely a resource leak).

  • by default you do not instantiate an empty variant with the default constructor; the first type in the union may not even be default-constructible.

  • bad_variant_access should probably inherit from a standard exception (std::runtime_error or std::logic_error are common as base classes).

answered Sep 12, 2017 at 11:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.