/* Some tuple internals for inclusion from various headers. Partially * taken from the libc++ project. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OSTD_INTERNAL_TUPLE_HH #define OSTD_INTERNAL_TUPLE_HH #include "ostd/types.hh" #include "ostd/type_traits.hh" namespace ostd { template class Tuple; template struct Pair; template struct Array; /* tuple size */ template struct TupleSize; template struct TupleSize: public TupleSize {}; template struct TupleSize: public TupleSize {}; template struct TupleSize: public TupleSize {}; /* tuple element */ template struct TupleElementBase; template struct TupleElementBase { using Type = AddConst::Type>; }; template struct TupleElementBase { using Type = AddVolatile::Type>; }; template struct TupleElementBase { using Type = AddCv::Type>; }; template using TupleElement = typename TupleElementBase::Type; /* is tuple-like */ template struct IsTupleLike: False {}; template struct IsTupleLike: IsTupleLike {}; template struct IsTupleLike: IsTupleLike {}; template struct IsTupleLike: IsTupleLike {}; /* tuple specializations */ template struct IsTupleLike>: True {}; template TupleElement> &get(Tuple &); template const TupleElement> &get(const Tuple &); template TupleElement> &&get(Tuple &&); /* pair specializations */ template struct IsTupleLike>: True {}; template TupleElement> &get(Pair &); template const TupleElement> &get(const Pair &); template TupleElement> &&get(Pair &&); /* array specializations */ template struct IsTupleLike>: True {}; template T &get(Array &); template const T &get(const Array &); template T &&get(Array &&); /* make tuple indices */ namespace detail { template struct TupleIndices {}; template struct MakeTupleIndicesBase; template struct MakeTupleIndicesBase, E> { using Type = typename MakeTupleIndicesBase, E>::Type; }; template struct MakeTupleIndicesBase, E> { using Type = TupleIndices; }; template struct MakeTupleIndicesImpl { static_assert(S <= E, "MakeTupleIndices input error"); using Type = typename MakeTupleIndicesBase, E>::Type; }; template using MakeTupleIndices = typename MakeTupleIndicesImpl::Type; } /* tuple types */ namespace detail { template struct TupleTypes {}; } template struct TupleElementBase> { public: static_assert(I == 0, "TupleElement index out of range"); static_assert(I != 0, "TupleElement index out of range"); }; template struct TupleElementBase<0, detail::TupleTypes> { public: using Type = H; }; template struct TupleElementBase> { public: using Type = typename TupleElementBase>::Type; }; template struct TupleSize>: IntegralConstant {}; template struct IsTupleLike>: True {}; /* make tuple types */ namespace detail { template struct MakeTupleTypesBase; template struct MakeTupleTypesBase, T, S, E> { using TR = RemoveReference; using Type = typename MakeTupleTypesBase::value, TupleElement &, TupleElement>>, T, S + 1, E>::Type; }; template struct MakeTupleTypesBase, T, E, E> { using Type = TupleTypes; }; template struct MakeTupleTypesImpl { static_assert(S <= E, "MakeTupleTypes input error"); using Type = typename MakeTupleTypesBase, T, S, E>::Type; }; template>::value, Size S = 0> using MakeTupleTypes = typename MakeTupleTypesImpl::Type; } /* tuple convertible */ namespace detail { template struct TupleConvertibleBase: False {}; template struct TupleConvertibleBase, TupleTypes>: IntegralConstant::value && TupleConvertibleBase, TupleTypes>::value> {}; template<> struct TupleConvertibleBase, TupleTypes<>>: True {}; template struct TupleConvertibleApply: False {}; template struct TupleConvertibleApply: TupleConvertibleBase< MakeTupleTypes, MakeTupleTypes > {}; template>::value, bool = IsTupleLike::value> struct TupleConvertible: False {}; template struct TupleConvertible: TupleConvertibleApply< TupleSize>::value == TupleSize::value, T, U > {}; } /* tuple constructible */ namespace detail { template struct TupleConstructibleBase: False {}; template struct TupleConstructibleBase, TupleTypes>: IntegralConstant::value && TupleConstructibleBase, TupleTypes>::value> {}; template<> struct TupleConstructibleBase, TupleTypes<>>: True {}; template struct TupleConstructibleApply: False {}; template struct TupleConstructibleApply: TupleConstructibleBase< MakeTupleTypes, MakeTupleTypes > {}; template>::value, bool = IsTupleLike::value> struct TupleConstructible: False {}; template struct TupleConstructible: TupleConstructibleApply< TupleSize>::value == TupleSize::value, T, U > {}; } /* tuple assignable */ namespace detail { template struct TupleAssignableBase: False {}; template struct TupleAssignableBase, TupleTypes>: IntegralConstant::value && TupleAssignableBase, TupleTypes>::value> {}; template<> struct TupleAssignableBase, TupleTypes<>>: True {}; template struct TupleAssignableApply: False {}; template struct TupleAssignableApply: TupleAssignableBase< MakeTupleTypes, MakeTupleTypes > {}; template>::value, bool = IsTupleLike::value> struct TupleAssignable: False {}; template struct TupleAssignable: TupleAssignableApply< TupleSize>::value == TupleSize::value, T, U > {}; } } /* namespace ostd */ #endif