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