206 lines
4.5 KiB
C++
206 lines
4.5 KiB
C++
|
|
#ifndef CLASS_TUPLE
|
|
#define CLASS_TUPLE
|
|
|
|
#include <type_traits>
|
|
|
|
namespace std
|
|
{
|
|
template<class T>
|
|
struct tuple_size;
|
|
|
|
// template<std::size_t I, class... Types>
|
|
// struct tuple_element;
|
|
|
|
template<size_t __i, typename _Tp>
|
|
struct tuple_element;
|
|
|
|
};
|
|
|
|
static constexpr int maximum(int a, int b)
|
|
{
|
|
if (a > b)
|
|
return a;
|
|
return b;
|
|
}
|
|
|
|
template<int index, typename A = void, typename... Args>
|
|
struct ArgType
|
|
{
|
|
using type =
|
|
typename std::conditional<
|
|
index == 0,
|
|
A,
|
|
typename ArgType<maximum(index - 1, 0), Args...>::type>::type;
|
|
};
|
|
|
|
template<typename T>
|
|
struct ArgType<0, T>
|
|
{
|
|
using type = T;
|
|
};
|
|
|
|
template<typename... Ts>
|
|
class tuple
|
|
{
|
|
public:
|
|
struct empty
|
|
{
|
|
auto operator <=> (const empty& other __attribute__((unused))) const
|
|
{
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
template <size_t _index, typename M = void, typename... Es>
|
|
struct elements_t
|
|
{
|
|
static const size_t index = _index;
|
|
|
|
M car;
|
|
|
|
typename std::conditional<
|
|
sizeof...(Es) == 0,
|
|
empty,
|
|
elements_t<_index + 1, Es...>>::type cdr;
|
|
|
|
elements_t()
|
|
{
|
|
;
|
|
}
|
|
|
|
elements_t(M m, Es... e):
|
|
car(m), cdr(e...)
|
|
{
|
|
;
|
|
}
|
|
|
|
int operator <=> (const elements_t& other) const
|
|
{
|
|
auto car_res = (car <=> other.car);
|
|
|
|
if (car_res > 0)
|
|
return 1;
|
|
if (car_res < 0)
|
|
return -1;
|
|
|
|
auto cdr_res = (cdr <=> other.cdr);
|
|
|
|
if (cdr_res > 0)
|
|
return 1;
|
|
if (cdr_res < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
public:
|
|
elements_t<0, Ts...> elements;
|
|
|
|
public:
|
|
tuple()
|
|
{
|
|
;
|
|
}
|
|
|
|
tuple(Ts... _elements):
|
|
elements(_elements...)
|
|
{
|
|
;
|
|
}
|
|
|
|
private:
|
|
template<size_t index, typename R, typename T>
|
|
R& helper(T& holder)
|
|
{
|
|
if constexpr(T::index == index)
|
|
return holder.car;
|
|
else
|
|
return helper<index, R>(holder.cdr);
|
|
};
|
|
|
|
public:
|
|
template<size_t index>
|
|
ArgType<index, Ts...>::type& get()
|
|
{
|
|
return helper<index, typename ArgType<index, Ts...>::type>(elements);
|
|
}
|
|
|
|
auto first()
|
|
{
|
|
return this->get<0>();
|
|
}
|
|
|
|
auto second()
|
|
{
|
|
return this->get<1>();
|
|
}
|
|
|
|
int operator <=> (const tuple& other) const
|
|
{
|
|
return elements <=> other.elements;
|
|
}
|
|
|
|
~tuple()
|
|
{
|
|
;
|
|
}
|
|
};
|
|
|
|
|
|
template<typename... Ts>
|
|
struct std::tuple_size<tuple<Ts ...>>
|
|
{
|
|
static constexpr size_t value = sizeof...(Ts);
|
|
};
|
|
|
|
template<class car, class... cdr>
|
|
struct std::tuple_element<0, std::tuple<car, cdr ...>>
|
|
{
|
|
using type = car;
|
|
};
|
|
|
|
template<std::size_t I, class car, class... cdr>
|
|
struct std::tuple_element<I, std::tuple<car, cdr ...>>:
|
|
std::tuple_element<I - 1, std::tuple<cdr ...>>
|
|
{
|
|
};
|
|
|
|
template<class car, class... cdr>
|
|
struct std::tuple_element<0, tuple<car, cdr ...>>
|
|
{
|
|
using type = car;
|
|
};
|
|
|
|
template<std::size_t I, class car, class... cdr>
|
|
struct std::tuple_element<I, tuple<car, cdr ...>>:
|
|
std::tuple_element<I - 1, tuple<cdr ...>>
|
|
{
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|