/* 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 #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; /* std::tuple specializations */ template constexpr bool IsTupleLike> = true; template constexpr Size TupleSize> = sizeof...(T); template struct TupleElementBase> { using Type = std::tuple_element_t>; }; template inline TupleElement> &get(std::tuple &t) noexcept { return std::get(t); } template inline const TupleElement> &get(const std::tuple &t) noexcept { return std::get(t); } template inline TupleElement> &&get(std::tuple &&t) noexcept { return std::get(std::move(t)); } template inline const TupleElement> &&get(const std::tuple &&t) noexcept{ return std::get(std::move(t)); } /* tuple specializations */ template constexpr bool IsTupleLike> = true; template inline TupleElement> &get(Tuple &) noexcept; template inline const TupleElement> &get(const Tuple &) noexcept; template inline TupleElement> &&get(Tuple &&) noexcept; template inline const TupleElement> &&get(const Tuple &&) noexcept; /* pair specializations */ template constexpr bool IsTupleLike> = true; template inline TupleElement> &get(Pair &) noexcept; template inline const TupleElement> &get(const Pair &) noexcept; template inline TupleElement> &&get(Pair &&) noexcept; template inline const TupleElement> &&get(const Pair &&) noexcept; /* array specializations */ template constexpr bool IsTupleLike> = true; template inline T &get(Array &) noexcept; template inline const T &get(const Array &) noexcept; template inline T &&get(Array &&) noexcept; template inline const T &&get(const Array &&) noexcept; /* 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