tuple 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #ifndef __GBLIBCPP_TUPLE__
  2. #define __GBLIBCPP_TUPLE__
  3. #include <cstddef>
  4. #include <type_traits>
  5. #include <utility>
  6. #include <functional>
  7. #include <bits/tuple_tools>
  8. #include <bits/sequence>
  9. namespace std {
  10. template <std::size_t I, typename T>
  11. struct tuple_element<I, const T> {
  12. using type = std::add_const_t<tuple_element_t<I, T>>;
  13. };
  14. template <std::size_t I, typename T>
  15. struct tuple_element<I, volatile T> {
  16. using type = std::add_volatile_t<tuple_element_t<I, T>>;
  17. };
  18. template <std::size_t I, typename T>
  19. struct tuple_element<I, const volatile T> {
  20. using type = std::add_cv_t<tuple_element_t<I, T>>;
  21. };
  22. namespace __helpers {
  23. template <typename T, typename = void>
  24. struct __const_tuple_size {};
  25. template <typename T>
  26. struct __const_tuple_size<T, void_t<decltype(std::tuple_size<T>::value)>>
  27. : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
  28. } // namespace __helpers
  29. template <typename T>
  30. struct tuple_size<const T> : __helpers::__const_tuple_size<T> {};
  31. template <typename... Types>
  32. class tuple;
  33. template <std::size_t I, typename Type, typename... Types>
  34. struct tuple_element<I, std::tuple<Type, Types...>>
  35. : tuple_element<I-1, std::tuple<Types...>> {};
  36. template <typename Type, typename... Types>
  37. struct tuple_element<0, std::tuple<Type, Types...>> { using type = Type; };
  38. template <typename... Types>
  39. struct tuple_size<std::tuple<Types...>>
  40. : std::integral_constant<std::size_t, sizeof...(Types)> {};
  41. namespace __helpers {
  42. template <std::size_t I, typename Type, typename... Types>
  43. class tuple_impl {
  44. template <std::size_t, typename, typename...>
  45. friend class tuple_impl;
  46. template <std::size_t J, typename... UTypes>
  47. friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
  48. -> tuple_element_t<J, std::tuple<UTypes...>>&;
  49. template <std::size_t J, typename... UTypes>
  50. friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
  51. -> tuple_element_t<J, std::tuple<UTypes...>>&&;
  52. template <std::size_t J, typename... UTypes>
  53. friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
  54. -> tuple_element_t<J, std::tuple<UTypes...>> const&;
  55. template <std::size_t J, typename... UTypes>
  56. friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
  57. -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
  58. Type val;
  59. tuple_impl<I+1, Types...> next;
  60. template <std::size_t J>
  61. constexpr auto& _getl(void)
  62. {
  63. if constexpr (I == J)
  64. return val;
  65. else
  66. return next.template _getl<J>();
  67. }
  68. template <std::size_t J>
  69. constexpr const auto& _getl(void) const
  70. {
  71. if constexpr (I == J)
  72. return val;
  73. else
  74. return next.template _getl<J>();
  75. }
  76. template <std::size_t J>
  77. constexpr auto&& _getr(void)
  78. {
  79. if constexpr (I == J)
  80. return std::move(val);
  81. else
  82. return std::move(next.template _getr<J>());
  83. }
  84. template <std::size_t J>
  85. constexpr const auto&& _getr(void) const
  86. {
  87. if constexpr (I == J)
  88. return std::move(val);
  89. else
  90. return std::move(next.template _getr<J>());
  91. }
  92. public:
  93. constexpr tuple_impl()
  94. : val(), next() {}
  95. constexpr tuple_impl(const tuple_impl& arg) = default;
  96. constexpr tuple_impl(tuple_impl&& arg) = default;
  97. constexpr tuple_impl(const Type& val, const Types&... vals)
  98. : val(val), next(vals...) {}
  99. template <typename UType, typename... UTypes>
  100. constexpr tuple_impl(UType&& val, UTypes&&... vals)
  101. : val(std::forward<UType>(val)), next(std::forward<UTypes>(vals)...) {}
  102. template <typename... UTypes>
  103. constexpr tuple_impl(const std::tuple<UTypes...>& other)
  104. : val(std::get<I>(other)), next(other) {}
  105. template <typename... UTypes>
  106. constexpr tuple_impl(std::tuple<UTypes...>&& other)
  107. : val(std::get<I>(other)), next(std::move(other)) {}
  108. constexpr tuple_impl& operator=(const tuple_impl& other) = default;
  109. constexpr tuple_impl& operator=(tuple_impl&& other) = default;
  110. };
  111. template <std::size_t I, typename Type>
  112. class tuple_impl<I, Type> {
  113. template <std::size_t, typename, typename...>
  114. friend class tuple_impl;
  115. template <std::size_t J, typename... UTypes>
  116. friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
  117. -> tuple_element_t<J, std::tuple<UTypes...>>&;
  118. template <std::size_t J, typename... UTypes>
  119. friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
  120. -> tuple_element_t<J, std::tuple<UTypes...>>&&;
  121. template <std::size_t J, typename... UTypes>
  122. friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
  123. -> tuple_element_t<J, std::tuple<UTypes...>> const&;
  124. template <std::size_t J, typename... UTypes>
  125. friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
  126. -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
  127. Type val;
  128. template <std::size_t>
  129. constexpr Type& _getl(void) { return val; }
  130. template <std::size_t>
  131. constexpr Type const& _getl(void) const { return val; }
  132. template <std::size_t>
  133. constexpr Type&& _getr(void) { return std::move(val); }
  134. template <std::size_t>
  135. constexpr Type const&& _getr(void) const { return std::move(val); }
  136. public:
  137. constexpr tuple_impl()
  138. : val() {}
  139. constexpr tuple_impl(const tuple_impl& arg) = default;
  140. constexpr tuple_impl(tuple_impl&& arg) = default;
  141. constexpr tuple_impl(const Type& val) : val(val) {}
  142. template <typename UType>
  143. constexpr tuple_impl(UType&& val) : val(std::forward<UType>(val)) {}
  144. template <typename... UTypes>
  145. constexpr tuple_impl(const std::tuple<UTypes...>& other)
  146. : val(std::get<I>(other)) {}
  147. template <typename... UTypes>
  148. constexpr tuple_impl(std::tuple<UTypes...>&& other)
  149. : val(std::get<I>(other)) {}
  150. constexpr tuple_impl& operator=(const tuple_impl& other) = default;
  151. constexpr tuple_impl& operator=(tuple_impl&& other) = default;
  152. };
  153. template <typename... Types>
  154. struct tuple_constraints {
  155. static constexpr std::size_t Tsize = sizeof...(Types);
  156. template <std::size_t... I>
  157. static constexpr auto idx_seq(std::index_sequence<I...> seq)
  158. { return seq; }
  159. template <typename UTuple, typename Seq, typename... UTypes>
  160. struct tuple_copy_move_constructible_impl;
  161. template <typename UTuple, typename... UTypes, std::size_t... I>
  162. struct tuple_copy_move_constructible_impl<UTuple,
  163. std::index_sequence<I...>, UTypes...> : std::bool_constant<
  164. Tsize == sizeof...(UTypes)
  165. && (... && std::is_constructible_v<Types, decltype(
  166. std::get<I>(std::declval<UTuple>()))>)
  167. && ((Tsize != 1) || (!(... && std::is_convertible_v<UTuple, Types>)
  168. && !(... && std::is_constructible_v<Types, UTuple>)
  169. && !(... && std::is_same_v<Types, UTypes>)))
  170. > {};
  171. template <typename UTuple, typename... UTypes>
  172. struct tuple_copy_move_constructible : tuple_copy_move_constructible_impl<
  173. UTuple, decltype(idx_seq(std::index_sequence_for<UTypes...>{})), UTypes...> {};
  174. template <typename Pair, typename = std::index_sequence<0, 1>>
  175. struct tuple_pair_constructible;
  176. template <typename Pair, std::size_t... I>
  177. struct tuple_pair_constructible<Pair, std::index_sequence<I...>>
  178. : std::bool_constant<sizeof...(Types) == 2
  179. && (... && std::is_constructible_v<Types,
  180. decltype(std::get<I>(std::declval<Pair>()))>)
  181. > {};
  182. template <typename... Us>
  183. struct tuple_pair_copy_assignable : std::bool_constant<
  184. sizeof...(Types) == 2
  185. && (... && std::is_assignable_v<Types&, const Us&>)
  186. > {};
  187. template <typename... Us>
  188. struct tuple_pair_move_assignable : std::bool_constant<
  189. sizeof...(Types) == 2
  190. && (... && std::is_assignable_v<Types&, Us>)
  191. > {};
  192. };
  193. } // namespace __helpers
  194. template <typename... Types>
  195. class tuple : public __helpers::tuple_impl<0, Types...> {
  196. private:
  197. using base = __helpers::tuple_impl<0, Types...>;
  198. template <typename... UTypes, std::size_t... I>
  199. constexpr void __copy_assignment(
  200. const tuple<UTypes...>& other, std::index_sequence<I...>)
  201. { ((std::get<I>(*this) = std::get<I>(other)), ...); }
  202. template <typename... UTypes, std::size_t... I>
  203. constexpr void __move_assignment(
  204. tuple<UTypes...>&& other, std::index_sequence<I...>)
  205. {
  206. ((std::get<I>(*this) = std::forward<UTypes>(std::get<I>(other))), ...);
  207. }
  208. public:
  209. template <typename _ = void, std::enable_if_t<
  210. (... && std::is_default_constructible_v<Types>)
  211. && __helpers::template_true_type<_>::value
  212. , bool> = true>
  213. constexpr tuple() : base() {}
  214. template <typename _ = void, std::enable_if_t<
  215. sizeof...(Types) >= 1
  216. && (... && std::is_copy_constructible_v<Types>)
  217. && __helpers::template_true_type<_>::value
  218. , bool> = true>
  219. constexpr tuple(const Types&... args)
  220. : base(args...) {}
  221. template <typename... UTypes, std::enable_if_t<
  222. sizeof...(UTypes) == sizeof...(Types)
  223. && sizeof...(Types) >= 1
  224. && (... && std::is_constructible_v<Types, UTypes>)
  225. && !(sizeof...(Types) == 1
  226. && (... && std::is_same_v<tuple, std::remove_cvref_t<UTypes>>))
  227. , bool> = true>
  228. constexpr tuple(UTypes&&... args)
  229. : base(std::forward<UTypes>(args)...) {}
  230. template <typename... UTypes, std::enable_if_t<
  231. __helpers::tuple_constraints<Types...>::template
  232. tuple_copy_move_constructible<const tuple<UTypes...>&, UTypes...>::value
  233. , bool> = true>
  234. constexpr tuple(const tuple<UTypes...>& other)
  235. : base(other) {}
  236. template <typename... UTypes, std::enable_if_t<
  237. __helpers::tuple_constraints<Types...>::template
  238. tuple_copy_move_constructible<tuple<UTypes...>&&, UTypes...>::value
  239. , bool> = true>
  240. constexpr tuple(tuple<UTypes...>&& other)
  241. : base(std::move(other)) {}
  242. template <typename U1, typename U2, std::enable_if_t<
  243. __helpers::tuple_constraints<Types...>::template
  244. tuple_pair_constructible<const std::pair<U1, U2>&>::value
  245. , bool> = true>
  246. constexpr tuple(const std::pair<U1, U2>& p)
  247. : base(std::get<0>(p), std::get<1>(p)) {}
  248. template <typename U1, typename U2, std::enable_if_t<
  249. __helpers::tuple_constraints<Types...>::template
  250. tuple_pair_constructible<std::pair<U1, U2>&&>::value
  251. , bool> = true>
  252. constexpr tuple(std::pair<U1, U2>&& p)
  253. : base(std::get<0>(std::move(p)), std::get<1>(std::move(p))) {}
  254. constexpr tuple(const tuple&) = default;
  255. constexpr tuple(tuple&&) = default;
  256. constexpr tuple& operator=(const tuple& other) = default;
  257. constexpr tuple& operator=(tuple&& other) = default;
  258. template <typename... UTypes, std::enable_if_t<
  259. sizeof...(Types) == sizeof...(UTypes)
  260. && (... && std::is_assignable_v<Types&, const UTypes&>)
  261. , bool> = true>
  262. constexpr tuple& operator=(const tuple<UTypes...>& other)
  263. {
  264. __copy_assignment(other, index_sequence_for<Types...> {});
  265. return *this;
  266. }
  267. template <typename... UTypes, std::enable_if_t<
  268. sizeof...(Types) == sizeof...(UTypes)
  269. && (... && std::is_assignable_v<Types&, UTypes>)
  270. , bool> = true>
  271. constexpr tuple& operator=(tuple<UTypes...>&& other)
  272. {
  273. __move_assignment(std::move(other), index_sequence_for<Types...> {});
  274. return *this;
  275. }
  276. template <typename U1, typename U2, std::enable_if_t<
  277. __helpers::tuple_constraints<Types...>::template
  278. tuple_pair_copy_assignable<U1, U2>::value
  279. , bool> = true>
  280. constexpr tuple& operator=(const std::pair<U1, U2>& p)
  281. {
  282. std::get<0>(*this) = p.first;
  283. std::get<1>(*this) = p.second;
  284. return *this;
  285. }
  286. template <typename U1, typename U2, std::enable_if_t<
  287. __helpers::tuple_constraints<Types...>::template
  288. tuple_pair_move_assignable<U1, U2>::value
  289. , bool> = true>
  290. constexpr tuple& operator=(std::pair<U1, U2>&& p)
  291. {
  292. std::get<0>(*this) = std::forward<U1>(p.first);
  293. std::get<1>(*this) = std::forward<U2>(p.second);
  294. return *this;
  295. }
  296. constexpr void swap(tuple& other) { std::swap(*this, other); }
  297. };
  298. template <typename... Types>
  299. tuple(Types...) -> tuple<Types...>;
  300. namespace __helpers {
  301. struct ignore_t {
  302. template <typename T>
  303. constexpr void operator=(T&&) const noexcept {}
  304. };
  305. template <typename Func, typename Tuple, std::size_t... I>
  306. constexpr auto apply_impl(Func&& func, Tuple&& tpl, std::index_sequence<I...>)
  307. {
  308. return std::invoke(
  309. std::forward<Func>(func),
  310. std::get<I>(std::forward<Tuple>(tpl))...);
  311. }
  312. } // namespace __helpers
  313. inline constexpr __helpers::ignore_t ignore;
  314. template <typename... Types>
  315. constexpr void swap(std::tuple<Types...>& lhs, std::tuple<Types...>& rhs)
  316. noexcept(noexcept(lhs.swap(rhs)))
  317. {
  318. lhs.swap(rhs);
  319. }
  320. template <typename... Types>
  321. constexpr auto make_tuple(Types&&... args)
  322. -> std::tuple<__helpers::to_tuple_type_t<Types>...>
  323. {
  324. return std::tuple<__helpers::to_tuple_type_t<Types>...>
  325. { std::forward<Types>(args)... };
  326. }
  327. template <typename... Types>
  328. constexpr std::tuple<Types&...> tie(Types&... args) noexcept
  329. {
  330. return { args... };
  331. }
  332. template <typename... Types>
  333. constexpr std::tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept
  334. {
  335. return { std::forward<Types>(args)... };
  336. }
  337. template <typename Func, typename Tuple>
  338. constexpr decltype(auto) apply(Func&& func, Tuple&& tpl)
  339. {
  340. return __helpers::apply_impl(
  341. std::forward<Func>(func), std::forward<Tuple>(tpl),
  342. std::make_index_sequence<
  343. std::tuple_size_v<std::remove_cvref_t<Tuple>>> {}
  344. );
  345. }
  346. } // namespace std
  347. #endif