Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vinniefalco/7c47915f55c66d10505c612869c798c6 to your computer and use it in GitHub Desktop.
Save vinniefalco/7c47915f55c66d10505c612869c798c6 to your computer and use it in GitHub Desktop.
// This simple variant gets the job done without
// causing too much trouble with template depth:
//
// * Always allows an empty state I==0
// * emplace() and get() support 1-based indexes only
// * Basic exception guarantee
// * Max 255 types
//
template<class... TN>
class variant
{
std::array<char, max_sizeof<TN...>()> buf_;
unsigned char i_ = 0;
template<std::size_t I>
using type = typename std::tuple_element<
I , std::tuple<TN...>>::type;
template<std::size_t I>
using C = std::integral_constant<std::size_t, I>;
public:
variant() = default;
~variant()
{
if(n_)
destroy(C<0>{});
}
template<std::size_t I, class... Args>
void
emplace(Args&&... args)
{
if(n_ != 0)
destroy(C<0>{});
n_ = 0;
new(buf_.data()) type<I>(
std::forward<Args>(args)...);
n_ = I;
}
template<std::size_t I>
type<I-1>&
get()
{
BOOST_ASSERT(I == n_ - 1);
return *reinterpret_cast<
type<I>*>(buf_.data());
}
template<std::size_t I>
type<I-1>&
get() const
{
BOOST_ASSERT(I == n_ - 1);
return *reinterpret_cast<
type<I> const*>(buf_.data());
}
private:
void
destroy(C<sizeof...(TN)>)
{
return;
}
template<std::size_t I>
void
destroy(C<I>)
{
if(I == n_ - 1)
{
type<I>.~type<I>();
return;
}
destroy(C<I+1>{});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment