#include <iostream>
#include <cstddef>
#include <utility>
#include <cassert>
#include <array>
template <typename first, typename ... rest>
struct find_biggest_size
{
constexpr static std::size_t value = (sizeof(first) > find_biggest_size<rest...>::value) ? sizeof(first) : find_biggest_size<rest...>::value;
};
template <typename first>
struct find_biggest_size<first>
{
constexpr static std::size_t value = sizeof(first);
};
template <typename first, typename second>
struct find_biggest_size<first, second>
{
constexpr static std::size_t value = (sizeof(first) > sizeof(second)) ? sizeof(first) : sizeof(second);
};
template <typename type, typename first, typename ... rest>
struct is_present
{
static constexpr bool value = (is_present<type, rest...>::value) ? true : std::is_same<type, first>::value;
static constexpr std::size_t index = is_present<type, rest...>::index + 1;
};
template <typename type, typename first>
struct is_present<type, first>
{
static constexpr bool value = std::is_same<type, first>::value;
static constexpr std::size_t index = 0;
};
template <std::size_t ind, typename ... Types>
struct extract
{};
template <std::size_t ind, typename first, typename ... rest>
struct extract<ind, first, rest...>
{
using type = typename extract<ind - 1, rest...>::type;
};
template <typename T>
struct extract<0, T>
{
using type = T;
};
template <typename T>
struct in_place_t
{};
struct bad_variant_access
{};
template <typename ... alternatives>
class variant
{
char object[find_biggest_size<alternatives...>::value];
std::size_t index;
public:
template <typename T>
variant(T&& other)
{
static_assert(is_present<T, alternatives...>::value, "type is not in range");
new ((T*)&object[0]) T(std::forward<T>(other));
index = is_present<T, alternatives...>::index;
}
template <typename T>
variant(const T& other)
{
static_assert(is_present<T, alternatives...>::value, "type is not in range");
new ((T*)&object[0]) T(std::forward<T>(other));
index = is_present<T, alternatives...>::index;
}
template <typename T, typename ... ArgTypes>
variant(in_place_t<T>, ArgTypes&& ... args)
{
static_assert(is_present<T, alternatives...>::value, "type is not in range");
new ((T*)&object[0]) T(std::forward<ArgTypes>(args)...);
index = is_present<T, alternatives...>::index;
}
template <std::size_t ind, typename ... alts>
friend typename extract<ind, alts...>::type get(variant<alts...>& v)
{
using T = typename extract<ind, alts...>::type;
if (v.index != ind)
{
throw bad_variant_access{};
}
return *((T*)(v.object));
}
~variant()
{
static std::array<void(*)(char*), sizeof...(alternatives)> destructors
{
std::addressof(invoke_destructor_impl<alternatives>)...
};
destructors[index](object);
}
private:
template<class T> static void invoke_destructor_impl(char* object)
{
auto pt = reinterpret_cast<T*>(object);
pt->~T();
}
};
int main() {
variant<int, char, bool> v(true);
std::cout << get<2>(v);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y3N0ZGRlZj4KI2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxjYXNzZXJ0PgojaW5jbHVkZSA8YXJyYXk+CgoJdGVtcGxhdGUgPHR5cGVuYW1lIGZpcnN0LCB0eXBlbmFtZSAuLi4gcmVzdD4KCXN0cnVjdCBmaW5kX2JpZ2dlc3Rfc2l6ZQoJewoJCWNvbnN0ZXhwciBzdGF0aWMgc3RkOjpzaXplX3QgdmFsdWUgPSAoc2l6ZW9mKGZpcnN0KSA+IGZpbmRfYmlnZ2VzdF9zaXplPHJlc3QuLi4+Ojp2YWx1ZSkgPyBzaXplb2YoZmlyc3QpIDogZmluZF9iaWdnZXN0X3NpemU8cmVzdC4uLj46OnZhbHVlOwoJfTsKCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgZmlyc3Q+CglzdHJ1Y3QgZmluZF9iaWdnZXN0X3NpemU8Zmlyc3Q+Cgl7CgkJY29uc3RleHByIHN0YXRpYyBzdGQ6OnNpemVfdCB2YWx1ZSA9IHNpemVvZihmaXJzdCk7Cgl9OwoKCXRlbXBsYXRlIDx0eXBlbmFtZSBmaXJzdCwgdHlwZW5hbWUgc2Vjb25kPgoJc3RydWN0IGZpbmRfYmlnZ2VzdF9zaXplPGZpcnN0LCBzZWNvbmQ+Cgl7CgkJY29uc3RleHByIHN0YXRpYyBzdGQ6OnNpemVfdCB2YWx1ZSA9IChzaXplb2YoZmlyc3QpID4gc2l6ZW9mKHNlY29uZCkpID8gc2l6ZW9mKGZpcnN0KSA6IHNpemVvZihzZWNvbmQpOwoJfTsKCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgdHlwZSwgdHlwZW5hbWUgZmlyc3QsIHR5cGVuYW1lIC4uLiByZXN0PgoJc3RydWN0IGlzX3ByZXNlbnQKCXsKCQlzdGF0aWMgY29uc3RleHByIGJvb2wgdmFsdWUgPSAoaXNfcHJlc2VudDx0eXBlLCByZXN0Li4uPjo6dmFsdWUpID8gdHJ1ZSA6IHN0ZDo6aXNfc2FtZTx0eXBlLCBmaXJzdD46OnZhbHVlOwoJCXN0YXRpYyBjb25zdGV4cHIgc3RkOjpzaXplX3QgaW5kZXggPSBpc19wcmVzZW50PHR5cGUsIHJlc3QuLi4+OjppbmRleCArIDE7Cgl9OwoKCXRlbXBsYXRlIDx0eXBlbmFtZSB0eXBlLCB0eXBlbmFtZSBmaXJzdD4KCXN0cnVjdCBpc19wcmVzZW50PHR5cGUsIGZpcnN0PgoJewoJCXN0YXRpYyBjb25zdGV4cHIgYm9vbCB2YWx1ZSA9IHN0ZDo6aXNfc2FtZTx0eXBlLCBmaXJzdD46OnZhbHVlOwoJCXN0YXRpYyBjb25zdGV4cHIgc3RkOjpzaXplX3QgaW5kZXggPSAwOwoJfTsKCgl0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgaW5kLCB0eXBlbmFtZSAuLi4gVHlwZXM+CglzdHJ1Y3QgZXh0cmFjdAoJe307CgoJdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IGluZCwgdHlwZW5hbWUgZmlyc3QsIHR5cGVuYW1lIC4uLiByZXN0PgoJc3RydWN0IGV4dHJhY3Q8aW5kLCBmaXJzdCwgcmVzdC4uLj4KCXsKCQl1c2luZyB0eXBlID0gdHlwZW5hbWUgZXh0cmFjdDxpbmQgLSAxLCByZXN0Li4uPjo6dHlwZTsKCX07CgoJdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CglzdHJ1Y3QgZXh0cmFjdDwwLCBUPgoJewoJCXVzaW5nIHR5cGUgPSBUOwoJfTsKCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KCXN0cnVjdCBpbl9wbGFjZV90Cgl7fTsKCglzdHJ1Y3QgYmFkX3ZhcmlhbnRfYWNjZXNzCgl7fTsKCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uIGFsdGVybmF0aXZlcz4KCWNsYXNzIHZhcmlhbnQKCXsKCQljaGFyIG9iamVjdFtmaW5kX2JpZ2dlc3Rfc2l6ZTxhbHRlcm5hdGl2ZXMuLi4+Ojp2YWx1ZV07CgkJc3RkOjpzaXplX3QgaW5kZXg7CglwdWJsaWM6CgkJdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CgkJdmFyaWFudChUJiYgb3RoZXIpCgkJewoJCQlzdGF0aWNfYXNzZXJ0KGlzX3ByZXNlbnQ8VCwgYWx0ZXJuYXRpdmVzLi4uPjo6dmFsdWUsICJ0eXBlIGlzIG5vdCBpbiByYW5nZSIpOwoJCQluZXcgKChUKikmb2JqZWN0WzBdKSBUKHN0ZDo6Zm9yd2FyZDxUPihvdGhlcikpOwoJCQlpbmRleCA9IGlzX3ByZXNlbnQ8VCwgYWx0ZXJuYXRpdmVzLi4uPjo6aW5kZXg7CgkJfQoKCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KCQl2YXJpYW50KGNvbnN0IFQmIG90aGVyKQoJCXsKCQkJc3RhdGljX2Fzc2VydChpc19wcmVzZW50PFQsIGFsdGVybmF0aXZlcy4uLj46OnZhbHVlLCAidHlwZSBpcyBub3QgaW4gcmFuZ2UiKTsKCQkJbmV3ICgoVCopJm9iamVjdFswXSkgVChzdGQ6OmZvcndhcmQ8VD4ob3RoZXIpKTsKCQkJaW5kZXggPSBpc19wcmVzZW50PFQsIGFsdGVybmF0aXZlcy4uLj46OmluZGV4OwoJCX0KCgkJdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIC4uLiBBcmdUeXBlcz4KCQl2YXJpYW50KGluX3BsYWNlX3Q8VD4sIEFyZ1R5cGVzJiYgLi4uIGFyZ3MpCgkJewoJCQlzdGF0aWNfYXNzZXJ0KGlzX3ByZXNlbnQ8VCwgYWx0ZXJuYXRpdmVzLi4uPjo6dmFsdWUsICJ0eXBlIGlzIG5vdCBpbiByYW5nZSIpOwoJCQluZXcgKChUKikmb2JqZWN0WzBdKSBUKHN0ZDo6Zm9yd2FyZDxBcmdUeXBlcz4oYXJncykuLi4pOwoJCQlpbmRleCA9IGlzX3ByZXNlbnQ8VCwgYWx0ZXJuYXRpdmVzLi4uPjo6aW5kZXg7CgkJfQoKCgoJCXRlbXBsYXRlIDxzdGQ6OnNpemVfdCBpbmQsIHR5cGVuYW1lIC4uLiBhbHRzPgoJCWZyaWVuZCB0eXBlbmFtZSBleHRyYWN0PGluZCwgYWx0cy4uLj46OnR5cGUgZ2V0KHZhcmlhbnQ8YWx0cy4uLj4mIHYpCgkJewoJCQl1c2luZyBUID0gdHlwZW5hbWUgZXh0cmFjdDxpbmQsIGFsdHMuLi4+Ojp0eXBlOwoJCQlpZiAodi5pbmRleCAhPSBpbmQpCgkJCXsKCQkJCXRocm93IGJhZF92YXJpYW50X2FjY2Vzc3t9OwoJCQl9CgoJCQlyZXR1cm4gKigoVCopKHYub2JqZWN0KSk7CgkJfQoKCQl+dmFyaWFudCgpCgkJewoJCQlzdGF0aWMgc3RkOjphcnJheTx2b2lkKCopKGNoYXIqKSwgc2l6ZW9mLi4uKGFsdGVybmF0aXZlcyk+IGRlc3RydWN0b3JzCgkJCXsKCQkJCXN0ZDo6YWRkcmVzc29mKGludm9rZV9kZXN0cnVjdG9yX2ltcGw8YWx0ZXJuYXRpdmVzPikuLi4KCQkJfTsKCQkJZGVzdHJ1Y3RvcnNbaW5kZXhdKG9iamVjdCk7CgkJfQoKCXByaXZhdGU6CgkJdGVtcGxhdGU8Y2xhc3MgVD4gc3RhdGljIHZvaWQgaW52b2tlX2Rlc3RydWN0b3JfaW1wbChjaGFyKiBvYmplY3QpCgkJewoJCQlhdXRvIHB0ID0gcmVpbnRlcnByZXRfY2FzdDxUKj4ob2JqZWN0KTsKCQkJcHQtPn5UKCk7CgkJfQoJfTsKCmludCBtYWluKCkgewoJCXZhcmlhbnQ8aW50LCBjaGFyLCBib29sPiB2KHRydWUpOwoJCXN0ZDo6Y291dCA8PCBnZXQ8Mj4odik7CgkJCgkKCXJldHVybiAwOwp9