123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #ifndef __GBLIBCPP_UTILITY__
- #define __GBLIBCPP_UTILITY__
- #include <cstddef>
- #include <bits/forward>
- #include <bits/sequence>
- #include <bits/tuple_tools>
- #include <type_traits>
- namespace std {
- template <typename T, typename U = T>
- constexpr T exchange(T& dst, U&& val)
- {
- T tmp = move(dst);
- dst = forward<U>(val);
- return tmp;
- }
- template <typename T>
- constexpr void swap(T& a, T& b)
- {
- T tmp(std::move(a));
- a = std::move(b);
- b = std::move(tmp);
- }
- struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
- inline constexpr piecewise_construct_t piecewise_construct {};
- template <typename... Types>
- class tuple;
- template <typename T1, typename T2>
- struct pair;
- template <typename T1, typename T2>
- struct tuple_size<std::pair<T1, T2>>
- : public std::integral_constant<std::size_t, 2> {};
- template <typename T1, typename T2>
- struct tuple_element<0, std::pair<T1, T2>> { using type = T1; };
- template <typename T1, typename T2>
- struct tuple_element<1, std::pair<T1, T2>> { using type = T2; };
- template <std::size_t I, typename T1, typename T2>
- struct tuple_element<I, std::pair<T1, T2>> {
- static_assert(I < 2, "std::pair has only 2 elements");
- };
- template <typename T1, typename T2>
- struct pair {
- using first_type = T1;
- using second_type = T2;
- T1 first;
- T2 second;
- template <typename U1 = T1, typename U2 = T2, std::enable_if_t<
- std::is_default_constructible_v<U1>
- && std::is_default_constructible_v<U2>
- , bool> = true>
- constexpr pair() : first(), second() {}
- template <typename U1 = T1, typename U2 = T2, std::enable_if_t<
- std::is_copy_constructible_v<U1>
- && std::is_copy_constructible_v<U2>
- , bool> = true>
- constexpr pair(const T1& t1, const T2& t2)
- : first(t1), second(t2) {}
- template <typename U1, typename U2, std::enable_if_t<
- std::is_constructible_v<T1, U1> && std::is_constructible_v<T2, U2>
- , bool> = true>
- constexpr pair(U1&& t1, U2&& t2)
- : first(std::forward<U1>(t1))
- , second(std::forward<U2>(t2)) {}
- template <typename U1, typename U2, std::enable_if_t<
- std::is_constructible_v<T1, const U1&>
- && std::is_constructible_v<T2, const U2&>
- , bool> = true>
- constexpr pair(const pair<U1, U2>& p)
- : first(p.first) , second(p.second) {}
- template <typename U1, typename U2, std::enable_if_t<
- std::is_constructible_v<T1, U1>
- && std::is_constructible_v<T2, U2>
- , bool> = true>
- constexpr pair(pair<U1, U2>&& p)
- : first(std::forward<U1>(p.first))
- , second(std::forward<U2>(p.second)) {}
- template <typename... Args1, typename... Args2>
- constexpr pair(std::piecewise_construct_t,
- std::tuple<Args1...> first_args,
- std::tuple<Args2...> second_args)
- : first(std::make_from_tuple<T1>(std::move(first_args)))
- , second(std::make_from_tuple<T2>(std::move(second_args))) {}
- constexpr pair(const pair&) = default;
- constexpr pair(pair&&) = default;
- constexpr pair& operator=(const pair& other) = default;
- constexpr pair& operator=(pair&& other) = default;
- template <typename U1, typename U2, std::enable_if_t<
- std::is_assignable_v<T1&, const U1&>
- && std::is_assignable_v<T2&, const U2&>
- , bool> = true>
- constexpr pair& operator=(const pair<U1, U2>& other)
- {
- first = other.first;
- second = other.second;
- return *this;
- }
- template <typename U1, typename U2, std::enable_if_t<
- std::is_assignable_v<T1&, U1>
- && std::is_assignable_v<T2&, U2>
- , bool> = true>
- constexpr pair& operator=(pair<U1, U2>&& other)
- {
- first = std::forward<U1>(other.first);
- second = std::forward<U2>(other.second);
- return *this;
- }
-
- constexpr void swap(pair& other)
- {
- std::swap(first, other.first);
- std::swap(second, other.second);
- }
- };
- template <typename T1, typename T2>
- pair(T1, T2) -> pair<T1, T2>;
- template <typename T1, typename T2>
- constexpr auto make_pair(T1&& t1, T2&& t2)
- -> std::pair<__helpers::to_tuple_type_t<T1>, __helpers::to_tuple_type_t<T2>>
- {
- return { std::forward<T1>(t1), std::forward<T2>(t2) };
- }
- template <std::size_t I, typename T1, typename T2>
- constexpr auto get(std::pair<T1, T2>& p) noexcept
- -> std::tuple_element_t<I, std::pair<T1, T2>>&
- {
- if constexpr (I == 0) return p.first;
- else return p.second;
- }
- template <std::size_t I, typename T1, typename T2>
- constexpr auto get(std::pair<T1, T2>&& p) noexcept
- -> std::tuple_element_t<I, std::pair<T1, T2>>&&
- {
- if constexpr (I == 0) return std::forward<T1>(p.first);
- else return std::forward<T2>(p.second);
- }
- template <std::size_t I, typename T1, typename T2>
- constexpr auto get(const std::pair<T1, T2>& p) noexcept
- -> std::tuple_element_t<I, std::pair<T1, T2>> const&
- {
- if constexpr (I == 0) return p.first;
- else return p.second;
- }
- template <std::size_t I, typename T1, typename T2>
- constexpr auto get(const std::pair<T1, T2>&& p) noexcept
- -> std::tuple_element_t<I, std::pair<T1, T2>> const&&
- {
- if constexpr (I == 0) return std::forward<T1>(p.first);
- else return std::forward<T2>(p.second);
- }
- template <typename T1, typename T2>
- constexpr void swap(std::pair<T1, T2>& lhs, std::pair<T1, T2>& rhs)
- noexcept(noexcept(lhs.swap(rhs)))
- {
- lhs.swap(rhs);
- }
- } // namespace std
- #endif
|