#include <type_traits>
#include <string>
#include <utility>
struct false_t {};
struct true_t {};
template<typename T, typename... Tail>
struct Is_t_in_set;
template<typename T, typename Head_t, typename... Tail>
struct Is_t_in_set<T, Head_t, Tail...> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>,
true_t,
typename Is_t_in_set<T, Tail...>::boolean
>;
};
template<typename T, typename Head_t>
struct Is_t_in_set<T, Head_t> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>, true_t, false_t
>;
};
struct empty_t {};
template<typename T>
struct Alias_type {
using Type = T;
};
template<typename T>
using Alias_type_t = typename Alias_type<T>::Type;
template<typename... Args> struct N_type_unique_set;
template<typename Head_t, typename... Tail>
struct N_type_unique_set<Head_t, Tail...>
: std::conditional_t<
std::is_same_v<typename Is_t_in_set<Head_t, Tail...>::boolean, true_t>,
empty_t,
Alias_type<Head_t>
>, N_type_unique_set<Tail...>
{};
template<typename Head_t>
struct N_type_unique_set<Head_t> : Alias_type<Head_t> {};
template <std::size_t N, typename... _Types>
struct Element_t;
template <std::size_t N, typename Head_t, typename... Tail>
struct Element_t<N, Head_t, Tail...> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
Element_t<N - 1, Tail...> tail;
};
inline Element_t(Head_t& a) : tag{N} {
head.reference = &a;
}
template<typename T>
inline Element_t(T&& a) : tail{ std::forward<T>(a) } {
tag = tail.tag;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == N) {
Func_t{}(*head.reference, std::forward<T>(a));
} else {
tail.template dispatch<Func_t>(std::forward<T>(a));
}
}
inline Head_t& operator=(Head_t& a) {
if (tag == N) {
*head.reference = a;
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
inline Head_t& operator=(Head_t&& a) {
if (tag == N) {
*head.reference = std::move(a);
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
};
template <typename Head_t>
struct Element_t<0, Head_t> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
};
inline Element_t(Head_t& a) : tag{0} {
head.reference = &a;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == 0) {
Func_t{}(*head.reference, std::forward<T>(a));
}
}
};
template <std::size_t N, typename... _Types>
class heterogeneous_list;
template <std::size_t N, typename Head_t, typename... Tail>
class heterogeneous_list<N, Head_t, Tail...> : public heterogeneous_list<N - 1, Tail...> {
Head_t Element;
public:
using type_set = Element_t<N, Head_t, Tail...>;
type_set operator[](std::size_t index) {
if (index == N) {
return type_set(Element);
} else if constexpr (N > 0) {
return heterogeneous_list<N - 1, Tail...>::operator[](index);
} else {
throw std::string{"out of bound access"};
}
}
};
template <typename Head_t>
class heterogeneous_list<0, Head_t> {
Head_t Element;
public:
using type_set = Element_t<0, Head_t>;
type_set operator[](std::size_t index) {
if (index == 0) {
return type_set(Element);
} else {
throw std::string{"out of bound access"};
}
}
};
int main(){
return 0;
}