/* 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 constexpr Size TupleSize = detail::Undefined(); template constexpr Size TupleSize = TupleSize; template constexpr Size TupleSize = TupleSize; template constexpr Size TupleSize = 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 constexpr bool IsTupleLike = false; template constexpr bool IsTupleLike = IsTupleLike; template constexpr bool IsTupleLike = IsTupleLike; template constexpr bool IsTupleLike = IsTupleLike; /* tuple specializations */ template constexpr bool IsTupleLike> = true; template inline TupleElement> &get(Tuple &); template inline const TupleElement> &get(const Tuple &); template inline TupleElement> &&get(Tuple &&); template inline const TupleElement> &&get(const Tuple &&); /* pair specializations */ template constexpr bool IsTupleLike> = true; template inline TupleElement> &get(Pair &); template inline const TupleElement> &get(const Pair &); template inline TupleElement> &&get(Pair &&); template inline const TupleElement> &&get(const Pair &&); /* array specializations */ template constexpr bool IsTupleLike> = true; template inline T &get(Array &); template inline const T &get(const Array &); template inline T &&get(Array &&); template inline const T &&get(const 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 constexpr Size TupleSize> = sizeof...(T); template constexpr bool IsTupleLike> = true; /* make tuple types */ namespace detail { template struct MakeTupleTypesBase; template struct MakeTupleTypesBase, T, S, E> { using TR = RemoveReference; using Type = typename MakeTupleTypesBase< TupleTypes< TS..., Conditional< IsLvalueReference, 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>, Size S = 0> using MakeTupleTypes = typename MakeTupleTypesImpl::Type; } /* tuple convertible */ namespace detail { template constexpr bool TupleConvertibleBase = false; template constexpr bool TupleConvertibleBase< TupleTypes, TupleTypes > = IsConvertible && TupleConvertibleBase, TupleTypes>; template<> constexpr bool TupleConvertibleBase, TupleTypes<>> = true; template constexpr bool TupleConvertibleApply = false; template constexpr bool TupleConvertibleApply = TupleConvertibleBase, MakeTupleTypes>; template< typename T, typename U, bool = IsTupleLike>, bool = IsTupleLike > constexpr bool TupleConvertible = false; template constexpr bool TupleConvertible = TupleConvertibleApply< TupleSize> == TupleSize, T, U >; } /* tuple constructible */ namespace detail { template constexpr bool TupleConstructibleBase = false; template constexpr bool TupleConstructibleBase< TupleTypes, TupleTypes > = IsConstructible && TupleConstructibleBase, TupleTypes>; template<> constexpr bool TupleConstructibleBase, TupleTypes<>> = true; template constexpr bool TupleConstructibleApply = false; template constexpr bool TupleConstructibleApply = TupleConstructibleBase, MakeTupleTypes>; template< typename T, typename U, bool = IsTupleLike>, bool = IsTupleLike > constexpr bool TupleConstructible = false; template constexpr bool TupleConstructible = TupleConstructibleApply< TupleSize> == TupleSize, T, U >; } /* tuple assignable */ namespace detail { template constexpr bool TupleAssignableBase = false; template constexpr bool TupleAssignableBase< TupleTypes, TupleTypes > = IsAssignable && TupleAssignableBase, TupleTypes>; template<> constexpr bool TupleAssignableBase, TupleTypes<>> = true; template constexpr bool TupleAssignableApply = false; template constexpr bool TupleAssignableApply = TupleAssignableBase, MakeTupleTypes>; template< typename T, typename U, bool = IsTupleLike>, bool = IsTupleLike > constexpr bool TupleAssignable = false; template constexpr bool TupleAssignable = TupleAssignableApply< TupleSize> == TupleSize, T, U >; } } /* namespace ostd */ #endif