/* 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>: Constant {}; 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, 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 constexpr bool TupleConvertibleBase = false; template constexpr bool TupleConvertibleBase, TupleTypes> = IsConvertible && TupleConvertibleBase, TupleTypes>; template<> constexpr bool TupleConvertibleBase, TupleTypes<>> = true; template constexpr bool TupleConvertibleApply = false; template constexpr bool TupleConvertibleApply = TupleConvertibleBase, MakeTupleTypes>; template>::value, bool = IsTupleLike::value> constexpr bool TupleConvertible = false; template constexpr bool TupleConvertible = TupleConvertibleApply< TupleSize>::value == TupleSize::value, T, U >; } /* tuple constructible */ namespace detail { template constexpr bool TupleConstructibleBase = false; template constexpr bool TupleConstructibleBase, TupleTypes> = IsConstructible && TupleConstructibleBase, TupleTypes>; template<> constexpr bool TupleConstructibleBase, TupleTypes<>> = true; template constexpr bool TupleConstructibleApply = false; template constexpr bool TupleConstructibleApply = TupleConstructibleBase, MakeTupleTypes>; template>::value, bool = IsTupleLike::value> constexpr bool TupleConstructible = false; template constexpr bool TupleConstructible = TupleConstructibleApply< TupleSize>::value == TupleSize::value, T, U >; } /* tuple assignable */ namespace detail { template constexpr bool TupleAssignableBase = false; template constexpr bool TupleAssignableBase, TupleTypes> = IsAssignable && TupleAssignableBase, TupleTypes>; template<> constexpr bool TupleAssignableBase, TupleTypes<>> = true; template constexpr bool TupleAssignableApply = false; template constexpr bool TupleAssignableApply = TupleAssignableBase, MakeTupleTypes>; template>::value, bool = IsTupleLike::value> constexpr bool TupleAssignable = false; template constexpr bool TupleAssignable = TupleAssignableApply< TupleSize>::value == TupleSize::value, T, U >; } } /* namespace ostd */ #endif