utility 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #ifndef __GBLIBCPP_UTILITY__
  2. #define __GBLIBCPP_UTILITY__
  3. #include <cstddef>
  4. #include <bits/forward>
  5. #include <bits/sequence>
  6. #include <bits/tuple_tools>
  7. #include <type_traits>
  8. namespace std {
  9. template <typename T, typename U = T>
  10. constexpr T exchange(T& dst, U&& val)
  11. {
  12. T tmp = move(dst);
  13. dst = forward<U>(val);
  14. return tmp;
  15. }
  16. template <typename T>
  17. constexpr void swap(T& a, T& b)
  18. {
  19. T tmp(std::move(a));
  20. a = std::move(b);
  21. b = std::move(tmp);
  22. }
  23. struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
  24. inline constexpr piecewise_construct_t piecewise_construct {};
  25. template <typename... Types>
  26. class tuple;
  27. template <typename T1, typename T2>
  28. struct pair;
  29. template <typename T1, typename T2>
  30. struct tuple_size<std::pair<T1, T2>>
  31. : public std::integral_constant<std::size_t, 2> {};
  32. template <typename T1, typename T2>
  33. struct tuple_element<0, std::pair<T1, T2>> { using type = T1; };
  34. template <typename T1, typename T2>
  35. struct tuple_element<1, std::pair<T1, T2>> { using type = T2; };
  36. template <std::size_t I, typename T1, typename T2>
  37. struct tuple_element<I, std::pair<T1, T2>> {
  38. static_assert(I < 2, "std::pair has only 2 elements");
  39. };
  40. template <typename T1, typename T2>
  41. struct pair {
  42. using first_type = T1;
  43. using second_type = T2;
  44. T1 first;
  45. T2 second;
  46. template <typename U1 = T1, typename U2 = T2, std::enable_if_t<
  47. std::is_default_constructible_v<U1>
  48. && std::is_default_constructible_v<U2>
  49. , bool> = true>
  50. constexpr pair() : first(), second() {}
  51. template <typename U1 = T1, typename U2 = T2, std::enable_if_t<
  52. std::is_copy_constructible_v<U1>
  53. && std::is_copy_constructible_v<U2>
  54. , bool> = true>
  55. constexpr pair(const T1& t1, const T2& t2)
  56. : first(t1), second(t2) {}
  57. template <typename U1, typename U2, std::enable_if_t<
  58. std::is_constructible_v<T1, U1> && std::is_constructible_v<T2, U2>
  59. , bool> = true>
  60. constexpr pair(U1&& t1, U2&& t2)
  61. : first(std::forward<U1>(t1))
  62. , second(std::forward<U2>(t2)) {}
  63. template <typename U1, typename U2, std::enable_if_t<
  64. std::is_constructible_v<T1, const U1&>
  65. && std::is_constructible_v<T2, const U2&>
  66. , bool> = true>
  67. constexpr pair(const pair<U1, U2>& p)
  68. : first(p.first) , second(p.second) {}
  69. template <typename U1, typename U2, std::enable_if_t<
  70. std::is_constructible_v<T1, U1>
  71. && std::is_constructible_v<T2, U2>
  72. , bool> = true>
  73. constexpr pair(pair<U1, U2>&& p)
  74. : first(std::forward<U1>(p.first))
  75. , second(std::forward<U2>(p.second)) {}
  76. template <typename... Args1, typename... Args2>
  77. constexpr pair(std::piecewise_construct_t,
  78. std::tuple<Args1...> first_args,
  79. std::tuple<Args2...> second_args)
  80. : first(std::make_from_tuple<T1>(std::move(first_args)))
  81. , second(std::make_from_tuple<T2>(std::move(second_args))) {}
  82. constexpr pair(const pair&) = default;
  83. constexpr pair(pair&&) = default;
  84. constexpr pair& operator=(const pair& other) = default;
  85. constexpr pair& operator=(pair&& other) = default;
  86. template <typename U1, typename U2, std::enable_if_t<
  87. std::is_assignable_v<T1&, const U1&>
  88. && std::is_assignable_v<T2&, const U2&>
  89. , bool> = true>
  90. constexpr pair& operator=(const pair<U1, U2>& other)
  91. {
  92. first = other.first;
  93. second = other.second;
  94. return *this;
  95. }
  96. template <typename U1, typename U2, std::enable_if_t<
  97. std::is_assignable_v<T1&, U1>
  98. && std::is_assignable_v<T2&, U2>
  99. , bool> = true>
  100. constexpr pair& operator=(pair<U1, U2>&& other)
  101. {
  102. first = std::forward<U1>(other.first);
  103. second = std::forward<U2>(other.second);
  104. return *this;
  105. }
  106. constexpr void swap(pair& other)
  107. {
  108. std::swap(first, other.first);
  109. std::swap(second, other.second);
  110. }
  111. };
  112. template <typename T1, typename T2>
  113. pair(T1, T2) -> pair<T1, T2>;
  114. template <typename T1, typename T2>
  115. constexpr auto make_pair(T1&& t1, T2&& t2)
  116. -> std::pair<__helpers::to_tuple_type_t<T1>, __helpers::to_tuple_type_t<T2>>
  117. {
  118. return { std::forward<T1>(t1), std::forward<T2>(t2) };
  119. }
  120. template <std::size_t I, typename T1, typename T2>
  121. constexpr auto get(std::pair<T1, T2>& p) noexcept
  122. -> std::tuple_element_t<I, std::pair<T1, T2>>&
  123. {
  124. if constexpr (I == 0) return p.first;
  125. else return p.second;
  126. }
  127. template <std::size_t I, typename T1, typename T2>
  128. constexpr auto get(std::pair<T1, T2>&& p) noexcept
  129. -> std::tuple_element_t<I, std::pair<T1, T2>>&&
  130. {
  131. if constexpr (I == 0) return std::forward<T1>(p.first);
  132. else return std::forward<T2>(p.second);
  133. }
  134. template <std::size_t I, typename T1, typename T2>
  135. constexpr auto get(const std::pair<T1, T2>& p) noexcept
  136. -> std::tuple_element_t<I, std::pair<T1, T2>> const&
  137. {
  138. if constexpr (I == 0) return p.first;
  139. else return p.second;
  140. }
  141. template <std::size_t I, typename T1, typename T2>
  142. constexpr auto get(const std::pair<T1, T2>&& p) noexcept
  143. -> std::tuple_element_t<I, std::pair<T1, T2>> const&&
  144. {
  145. if constexpr (I == 0) return std::forward<T1>(p.first);
  146. else return std::forward<T2>(p.second);
  147. }
  148. template <typename T1, typename T2>
  149. constexpr void swap(std::pair<T1, T2>& lhs, std::pair<T1, T2>& rhs)
  150. noexcept(noexcept(lhs.swap(rhs)))
  151. {
  152. lhs.swap(rhs);
  153. }
  154. } // namespace std
  155. #endif