| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 | 
							- #ifndef __GBLIBCPP_TUPLE__
 
- #define __GBLIBCPP_TUPLE__
 
- #include <cstddef>
 
- #include <type_traits>
 
- #include <utility>
 
- #include <functional>
 
- #include <bits/tuple_tools>
 
- #include <bits/sequence>
 
- namespace std {
 
- template <std::size_t I, typename T>
 
- struct tuple_element<I, const T> {
 
-     using type = std::add_const_t<tuple_element_t<I, T>>;
 
- };
 
- template <std::size_t I, typename T>
 
- struct tuple_element<I, volatile T> {
 
-     using type = std::add_volatile_t<tuple_element_t<I, T>>;
 
- };
 
- template <std::size_t I, typename T>
 
- struct tuple_element<I, const volatile T> {
 
-     using type = std::add_cv_t<tuple_element_t<I, T>>;
 
- };
 
- namespace __helpers {
 
- template <typename T, typename = void>
 
- struct __const_tuple_size {};
 
- template <typename T>
 
- struct __const_tuple_size<T, void_t<decltype(std::tuple_size<T>::value)>>
 
-     : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
 
- } // namespace __helpers
 
- template <typename T>
 
- struct tuple_size<const T> : __helpers::__const_tuple_size<T> {};
 
- template <typename... Types>
 
- class tuple;
 
- template <std::size_t I, typename Type, typename... Types>
 
- struct tuple_element<I, std::tuple<Type, Types...>>
 
-     : tuple_element<I-1, std::tuple<Types...>> {};
 
- template <typename Type, typename... Types>
 
- struct tuple_element<0, std::tuple<Type, Types...>> { using type = Type; };
 
- template <typename... Types>
 
- struct tuple_size<std::tuple<Types...>>
 
-     : std::integral_constant<std::size_t, sizeof...(Types)> {};
 
- namespace __helpers {
 
- template <std::size_t I, typename Type, typename... Types>
 
- class tuple_impl {
 
-     template <std::size_t, typename, typename...>
 
-     friend class tuple_impl;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>>&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>>&&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>> const&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
 
-     Type val;
 
-     tuple_impl<I+1, Types...> next;
 
-     template <std::size_t J>
 
-     constexpr auto& _getl(void)
 
-     {
 
-         if constexpr (I == J)
 
-             return val;
 
-         else
 
-             return next.template _getl<J>();
 
-     }
 
-     template <std::size_t J>
 
-     constexpr const auto& _getl(void) const
 
-     {
 
-         if constexpr (I == J)
 
-             return val;
 
-         else
 
-             return next.template _getl<J>();
 
-     }
 
-     template <std::size_t J>
 
-     constexpr auto&& _getr(void)
 
-     {
 
-         if constexpr (I == J)
 
-             return std::move(val);
 
-         else
 
-             return std::move(next.template _getr<J>());
 
-     }
 
-     template <std::size_t J>
 
-     constexpr const auto&& _getr(void) const
 
-     {
 
-         if constexpr (I == J)
 
-             return std::move(val);
 
-         else
 
-             return std::move(next.template _getr<J>());
 
-     }
 
- public:
 
-     constexpr tuple_impl()
 
-         : val(), next() {}
 
-     
 
-     constexpr tuple_impl(const tuple_impl& arg) = default;
 
-     constexpr tuple_impl(tuple_impl&& arg) = default;
 
-     constexpr tuple_impl(const Type& val, const Types&... vals)
 
-         : val(val), next(vals...) {}
 
-     
 
-     template <typename UType, typename... UTypes>
 
-     constexpr tuple_impl(UType&& val, UTypes&&... vals)
 
-         : val(std::forward<UType>(val)), next(std::forward<UTypes>(vals)...) {}
 
-     template <typename... UTypes>
 
-     constexpr tuple_impl(const std::tuple<UTypes...>& other)
 
-         : val(std::get<I>(other)), next(other) {}
 
-     template <typename... UTypes>
 
-     constexpr tuple_impl(std::tuple<UTypes...>&& other)
 
-         : val(std::get<I>(other)), next(std::move(other)) {}
 
-     
 
-     constexpr tuple_impl& operator=(const tuple_impl& other) = default;
 
-     constexpr tuple_impl& operator=(tuple_impl&& other) = default;
 
- };
 
- template <std::size_t I, typename Type>
 
- class tuple_impl<I, Type> {
 
-     template <std::size_t, typename, typename...>
 
-     friend class tuple_impl;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>>&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>>&&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>> const&;
 
-     template <std::size_t J, typename... UTypes>
 
-     friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
 
-         -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
 
-     Type val;
 
-     template <std::size_t>
 
-     constexpr Type& _getl(void) { return val; }
 
-     template <std::size_t>
 
-     constexpr Type const& _getl(void) const { return val; }
 
-     template <std::size_t>
 
-     constexpr Type&& _getr(void) { return std::move(val); }
 
-     template <std::size_t>
 
-     constexpr Type const&& _getr(void) const { return std::move(val); }
 
- public:
 
-     constexpr tuple_impl()
 
-         : val() {}
 
-     
 
-     constexpr tuple_impl(const tuple_impl& arg) = default;
 
-     constexpr tuple_impl(tuple_impl&& arg) = default;
 
-     constexpr tuple_impl(const Type& val) : val(val) {}
 
-     template <typename UType>
 
-     constexpr tuple_impl(UType&& val) : val(std::forward<UType>(val)) {}
 
-     template <typename... UTypes>
 
-     constexpr tuple_impl(const std::tuple<UTypes...>& other)
 
-         : val(std::get<I>(other)) {}
 
-     template <typename... UTypes>
 
-     constexpr tuple_impl(std::tuple<UTypes...>&& other)
 
-         : val(std::get<I>(other)) {}
 
-     constexpr tuple_impl& operator=(const tuple_impl& other) = default;
 
-     constexpr tuple_impl& operator=(tuple_impl&& other) = default;
 
- };
 
- template <typename... Types>
 
- struct tuple_constraints {
 
-     static constexpr std::size_t Tsize = sizeof...(Types);
 
-     template <std::size_t... I>
 
-     static constexpr auto idx_seq(std::index_sequence<I...> seq)
 
-     { return seq; }
 
-     template <typename UTuple, typename Seq, typename... UTypes>
 
-     struct tuple_copy_move_constructible_impl;
 
-     template <typename UTuple, typename... UTypes, std::size_t... I>
 
-     struct tuple_copy_move_constructible_impl<UTuple,
 
-         std::index_sequence<I...>, UTypes...> : std::bool_constant<
 
-         Tsize == sizeof...(UTypes)
 
-         && (... && std::is_constructible_v<Types, decltype(
 
-             std::get<I>(std::declval<UTuple>()))>)
 
-         && ((Tsize != 1) || (!(... && std::is_convertible_v<UTuple, Types>)
 
-             && !(... && std::is_constructible_v<Types, UTuple>)
 
-             && !(... && std::is_same_v<Types, UTypes>)))
 
-     > {};
 
-     template <typename UTuple, typename... UTypes>
 
-     struct tuple_copy_move_constructible : tuple_copy_move_constructible_impl<
 
-         UTuple, decltype(idx_seq(std::index_sequence_for<UTypes...>{})), UTypes...> {};
 
-     template <typename Pair, typename = std::index_sequence<0, 1>>
 
-     struct tuple_pair_constructible;
 
-     template <typename Pair, std::size_t... I>
 
-     struct tuple_pair_constructible<Pair, std::index_sequence<I...>>
 
-         : std::bool_constant<sizeof...(Types) == 2
 
-             && (... && std::is_constructible_v<Types,
 
-                 decltype(std::get<I>(std::declval<Pair>()))>)
 
-     > {};
 
-     template <typename... Us>
 
-     struct tuple_pair_copy_assignable : std::bool_constant<
 
-         sizeof...(Types) == 2
 
-         && (... && std::is_assignable_v<Types&, const Us&>)
 
-     > {};
 
-     template <typename... Us>
 
-     struct tuple_pair_move_assignable : std::bool_constant<
 
-         sizeof...(Types) == 2
 
-         && (... && std::is_assignable_v<Types&, Us>)
 
-     > {};
 
- };
 
- } // namespace __helpers
 
- template <typename... Types>
 
- class tuple : public __helpers::tuple_impl<0, Types...> {
 
- private:
 
-     using base = __helpers::tuple_impl<0, Types...>;
 
-     template <typename... UTypes, std::size_t... I>
 
-     constexpr void __copy_assignment(
 
-         const tuple<UTypes...>& other, std::index_sequence<I...>)
 
-     { ((std::get<I>(*this) = std::get<I>(other)), ...); }
 
-     template <typename... UTypes, std::size_t... I>
 
-     constexpr void __move_assignment(
 
-         tuple<UTypes...>&& other, std::index_sequence<I...>)
 
-     {
 
-         ((std::get<I>(*this) = std::forward<UTypes>(std::get<I>(other))), ...);
 
-     }
 
- public:
 
-     template <typename _ = void, std::enable_if_t<
 
-         (... && std::is_default_constructible_v<Types>)
 
-         && __helpers::template_true_type<_>::value
 
-     , bool> = true>
 
-     constexpr tuple() : base() {}
 
-     template <typename _ = void, std::enable_if_t<
 
-         sizeof...(Types) >= 1
 
-         && (... && std::is_copy_constructible_v<Types>)
 
-         && __helpers::template_true_type<_>::value
 
-     , bool> = true>
 
-     constexpr tuple(const Types&... args)
 
-         : base(args...) {}
 
-     
 
-     template <typename... UTypes, std::enable_if_t<
 
-         sizeof...(UTypes) == sizeof...(Types)
 
-         && sizeof...(Types) >= 1
 
-         && (... && std::is_constructible_v<Types, UTypes>)
 
-         && !(sizeof...(Types) == 1
 
-             && (... && std::is_same_v<tuple, std::remove_cvref_t<UTypes>>))
 
-     , bool> = true>
 
-     constexpr tuple(UTypes&&... args)
 
-         : base(std::forward<UTypes>(args)...) {}
 
-     template <typename... UTypes, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_copy_move_constructible<const tuple<UTypes...>&, UTypes...>::value
 
-     , bool> = true>
 
-     constexpr tuple(const tuple<UTypes...>& other)
 
-         : base(other) {}
 
-     template <typename... UTypes, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_copy_move_constructible<tuple<UTypes...>&&, UTypes...>::value
 
-     , bool> = true>
 
-     constexpr tuple(tuple<UTypes...>&& other)
 
-         : base(std::move(other)) {}
 
-     
 
-     template <typename U1, typename U2, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_pair_constructible<const std::pair<U1, U2>&>::value
 
-     , bool> = true>
 
-     constexpr tuple(const std::pair<U1, U2>& p)
 
-         : base(std::get<0>(p), std::get<1>(p)) {}
 
-     
 
-     template <typename U1, typename U2, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_pair_constructible<std::pair<U1, U2>&&>::value
 
-     , bool> = true>
 
-     constexpr tuple(std::pair<U1, U2>&& p)
 
-         : base(std::get<0>(std::move(p)), std::get<1>(std::move(p))) {}
 
-     constexpr tuple(const tuple&) = default;
 
-     constexpr tuple(tuple&&) = default;
 
-     constexpr tuple& operator=(const tuple& other) = default;
 
-     constexpr tuple& operator=(tuple&& other) = default;
 
-     template <typename... UTypes, std::enable_if_t<
 
-         sizeof...(Types) == sizeof...(UTypes)
 
-         && (... && std::is_assignable_v<Types&, const UTypes&>)
 
-         , bool> = true>
 
-     constexpr tuple& operator=(const tuple<UTypes...>& other)
 
-     {
 
-         __copy_assignment(other, index_sequence_for<Types...> {});
 
-         return *this;
 
-     }
 
-     template <typename... UTypes, std::enable_if_t<
 
-         sizeof...(Types) == sizeof...(UTypes)
 
-         && (... && std::is_assignable_v<Types&, UTypes>)
 
-         , bool> = true>
 
-     constexpr tuple& operator=(tuple<UTypes...>&& other)
 
-     {
 
-         __move_assignment(std::move(other), index_sequence_for<Types...> {});
 
-         return *this;
 
-     }
 
-     template <typename U1, typename U2, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_pair_copy_assignable<U1, U2>::value
 
-     , bool> = true>
 
-     constexpr tuple& operator=(const std::pair<U1, U2>& p)
 
-     {
 
-         std::get<0>(*this) = p.first;
 
-         std::get<1>(*this) = p.second;
 
-         return *this;
 
-     }
 
-     template <typename U1, typename U2, std::enable_if_t<
 
-         __helpers::tuple_constraints<Types...>::template
 
-             tuple_pair_move_assignable<U1, U2>::value
 
-     , bool> = true>
 
-     constexpr tuple& operator=(std::pair<U1, U2>&& p)
 
-     {
 
-         std::get<0>(*this) = std::forward<U1>(p.first);
 
-         std::get<1>(*this) = std::forward<U2>(p.second);
 
-         return *this;
 
-     }
 
-     constexpr void swap(tuple& other) { std::swap(*this, other); }
 
- };
 
- template <typename... Types>
 
- tuple(Types...) -> tuple<Types...>;
 
- namespace __helpers {
 
- struct ignore_t {
 
-     template <typename T>
 
-     constexpr void operator=(T&&) const noexcept {}
 
- };
 
- template <typename Func, typename Tuple, std::size_t... I>
 
- constexpr auto apply_impl(Func&& func, Tuple&& tpl, std::index_sequence<I...>)
 
- {
 
-     return std::invoke(
 
-         std::forward<Func>(func),
 
-         std::get<I>(std::forward<Tuple>(tpl))...);
 
- }
 
- } // namespace __helpers
 
- inline constexpr __helpers::ignore_t ignore;
 
- template <typename... Types>
 
- constexpr void swap(std::tuple<Types...>& lhs, std::tuple<Types...>& rhs)
 
-     noexcept(noexcept(lhs.swap(rhs)))
 
- {
 
-     lhs.swap(rhs);
 
- }
 
- template <typename... Types>
 
- constexpr auto make_tuple(Types&&... args)
 
-     -> std::tuple<__helpers::to_tuple_type_t<Types>...>
 
- {
 
-     return std::tuple<__helpers::to_tuple_type_t<Types>...>
 
-         { std::forward<Types>(args)... };
 
- }
 
- template <typename... Types>
 
- constexpr std::tuple<Types&...> tie(Types&... args) noexcept
 
- {
 
-     return { args... };
 
- }
 
- template <typename... Types>
 
- constexpr std::tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept
 
- {
 
-     return { std::forward<Types>(args)... };
 
- }
 
- template <typename Func, typename Tuple>
 
- constexpr decltype(auto) apply(Func&& func, Tuple&& tpl)
 
- {
 
-     return __helpers::apply_impl(
 
-         std::forward<Func>(func), std::forward<Tuple>(tpl),
 
-         std::make_index_sequence<
 
-             std::tuple_size_v<std::remove_cvref_t<Tuple>>> {}
 
-     );
 
- }
 
- } // namespace std
 
- #endif
 
 
  |