tuple 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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... Types>
  43. class tuple_impl;
  44. template <>
  45. class tuple_impl<0> {
  46. template <std::size_t, typename...>
  47. friend class tuple_impl;
  48. template <std::size_t J, typename... UTypes>
  49. friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
  50. -> tuple_element_t<J, std::tuple<UTypes...>>&;
  51. template <std::size_t J, typename... UTypes>
  52. friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
  53. -> tuple_element_t<J, std::tuple<UTypes...>>&&;
  54. template <std::size_t J, typename... UTypes>
  55. friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
  56. -> tuple_element_t<J, std::tuple<UTypes...>> const&;
  57. template <std::size_t J, typename... UTypes>
  58. friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
  59. -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
  60. template <std::size_t> constexpr void _getl(void) const = delete;
  61. template <std::size_t> constexpr void _getr(void) const = delete;
  62. public:
  63. constexpr tuple_impl() noexcept = default;
  64. constexpr tuple_impl(const tuple_impl& arg) noexcept = default;
  65. constexpr tuple_impl(tuple_impl&& arg) noexcept = default;
  66. template <typename... UTypes>
  67. constexpr tuple_impl(const std::tuple<UTypes...>& other) = delete;
  68. template <typename... UTypes>
  69. constexpr tuple_impl(std::tuple<UTypes...>&& other) = delete;
  70. constexpr tuple_impl& operator=(const tuple_impl& other) noexcept = default;
  71. constexpr tuple_impl& operator=(tuple_impl&& other) noexcept = default;
  72. };
  73. template <std::size_t I, typename Type, typename... Types>
  74. class tuple_impl<I, Type, Types...> {
  75. template <std::size_t, typename...>
  76. friend class tuple_impl;
  77. template <std::size_t J, typename... UTypes>
  78. friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
  79. -> tuple_element_t<J, std::tuple<UTypes...>>&;
  80. template <std::size_t J, typename... UTypes>
  81. friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
  82. -> tuple_element_t<J, std::tuple<UTypes...>>&&;
  83. template <std::size_t J, typename... UTypes>
  84. friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
  85. -> tuple_element_t<J, std::tuple<UTypes...>> const&;
  86. template <std::size_t J, typename... UTypes>
  87. friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
  88. -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
  89. Type val;
  90. tuple_impl<I+1, Types...> next;
  91. template <std::size_t J>
  92. constexpr auto& _getl(void)
  93. {
  94. if constexpr (I == J)
  95. return val;
  96. else
  97. return next.template _getl<J>();
  98. }
  99. template <std::size_t J>
  100. constexpr const auto& _getl(void) const
  101. {
  102. if constexpr (I == J)
  103. return val;
  104. else
  105. return next.template _getl<J>();
  106. }
  107. template <std::size_t J>
  108. constexpr auto&& _getr(void)
  109. {
  110. if constexpr (I == J)
  111. return std::forward<Type>(val);
  112. else
  113. return std::forward<
  114. decltype(next.template _getr<J>())>(
  115. next.template _getr<J>());
  116. }
  117. template <std::size_t J>
  118. constexpr const auto&& _getr(void) const
  119. {
  120. if constexpr (I == J)
  121. return std::forward<Type>(val);
  122. else
  123. return std::forward<
  124. decltype(next.template _getr<J>())>(
  125. next.template _getr<J>());
  126. }
  127. public:
  128. constexpr tuple_impl()
  129. : val(), next() {}
  130. constexpr tuple_impl(const tuple_impl& arg) = default;
  131. constexpr tuple_impl(tuple_impl&& arg) = default;
  132. constexpr tuple_impl(const Type& val, const Types&... vals)
  133. : val(val), next(vals...) {}
  134. template <typename UType, typename... UTypes>
  135. constexpr tuple_impl(UType&& val, UTypes&&... vals)
  136. : val(std::forward<UType>(val)), next(std::forward<UTypes>(vals)...) {}
  137. template <typename... UTypes>
  138. constexpr tuple_impl(const std::tuple<UTypes...>& other)
  139. : val(std::get<I>(other)), next(other) {}
  140. template <typename... UTypes>
  141. constexpr tuple_impl(std::tuple<UTypes...>&& other)
  142. : val(std::get<I>(other)), next(std::move(other)) {}
  143. constexpr tuple_impl& operator=(const tuple_impl& other) = default;
  144. constexpr tuple_impl& operator=(tuple_impl&& other) = default;
  145. };
  146. template <std::size_t I, typename Type>
  147. class tuple_impl<I, Type> {
  148. template <std::size_t, typename...>
  149. friend class tuple_impl;
  150. template <std::size_t J, typename... UTypes>
  151. friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
  152. -> tuple_element_t<J, std::tuple<UTypes...>>&;
  153. template <std::size_t J, typename... UTypes>
  154. friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
  155. -> tuple_element_t<J, std::tuple<UTypes...>>&&;
  156. template <std::size_t J, typename... UTypes>
  157. friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
  158. -> tuple_element_t<J, std::tuple<UTypes...>> const&;
  159. template <std::size_t J, typename... UTypes>
  160. friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
  161. -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
  162. Type val;
  163. template <std::size_t J>
  164. constexpr Type& _getl(void)
  165. {
  166. static_assert(J == I);
  167. return val;
  168. }
  169. template <std::size_t J>
  170. constexpr Type const& _getl(void) const
  171. {
  172. static_assert(J == I);
  173. return val;
  174. }
  175. template <std::size_t J>
  176. constexpr Type&& _getr(void)
  177. {
  178. static_assert(J == I);
  179. return std::forward<Type>(val);
  180. }
  181. template <std::size_t J>
  182. constexpr Type const&& _getr(void) const
  183. {
  184. static_assert(J == I);
  185. return std::forward<Type>(val);
  186. }
  187. public:
  188. constexpr tuple_impl()
  189. : val() {}
  190. constexpr tuple_impl(const tuple_impl& arg) = default;
  191. constexpr tuple_impl(tuple_impl&& arg) = default;
  192. constexpr tuple_impl(const Type& val) : val(val) {}
  193. template <typename UType>
  194. constexpr tuple_impl(UType&& val) : val(std::forward<UType>(val)) {}
  195. template <typename... UTypes>
  196. constexpr tuple_impl(const std::tuple<UTypes...>& other)
  197. : val(std::get<I>(other)) {}
  198. template <typename... UTypes>
  199. constexpr tuple_impl(std::tuple<UTypes...>&& other)
  200. : val(std::get<I>(other)) {}
  201. constexpr tuple_impl& operator=(const tuple_impl& other) = default;
  202. constexpr tuple_impl& operator=(tuple_impl&& other) = default;
  203. };
  204. template <typename... Types>
  205. struct tuple_constraints {
  206. static constexpr std::size_t Tsize = sizeof...(Types);
  207. template <std::size_t... I>
  208. static constexpr auto idx_seq(std::index_sequence<I...> seq)
  209. { return seq; }
  210. template <typename UTuple, typename Seq, typename... UTypes>
  211. struct tuple_copy_move_constructible_impl;
  212. template <typename UTuple, typename... UTypes, std::size_t... I>
  213. struct tuple_copy_move_constructible_impl<UTuple,
  214. std::index_sequence<I...>, UTypes...> : std::bool_constant<
  215. Tsize == sizeof...(UTypes)
  216. && (... && std::is_constructible_v<Types, decltype(
  217. std::get<I>(std::declval<UTuple>()))>)
  218. && ((Tsize != 1) || (!(... && std::is_convertible_v<UTuple, Types>)
  219. && !(... && std::is_constructible_v<Types, UTuple>)
  220. && !(... && std::is_same_v<Types, UTypes>)))
  221. > {};
  222. template <typename UTuple, typename... UTypes>
  223. struct tuple_copy_move_constructible : tuple_copy_move_constructible_impl<
  224. UTuple, decltype(idx_seq(std::index_sequence_for<UTypes...>{})), UTypes...> {};
  225. template <typename Pair, typename = std::index_sequence<0, 1>>
  226. struct tuple_pair_constructible;
  227. template <typename Pair, std::size_t... I>
  228. struct tuple_pair_constructible<Pair, std::index_sequence<I...>>
  229. : std::bool_constant<sizeof...(Types) == 2
  230. && (... && std::is_constructible_v<Types,
  231. decltype(std::get<I>(std::declval<Pair>()))>)
  232. > {};
  233. template <typename... Us>
  234. struct tuple_pair_copy_assignable : std::bool_constant<
  235. sizeof...(Types) == 2
  236. && (... && std::is_assignable_v<Types&, const Us&>)
  237. > {};
  238. template <typename... Us>
  239. struct tuple_pair_move_assignable : std::bool_constant<
  240. sizeof...(Types) == 2
  241. && (... && std::is_assignable_v<Types&, Us>)
  242. > {};
  243. };
  244. } // namespace __helpers
  245. template <typename... Types>
  246. class tuple : public __helpers::tuple_impl<0, Types...> {
  247. private:
  248. using base = __helpers::tuple_impl<0, Types...>;
  249. template <typename... UTypes, std::size_t... I>
  250. constexpr void __copy_assignment(
  251. const tuple<UTypes...>& other, std::index_sequence<I...>)
  252. { ((std::get<I>(*this) = std::get<I>(other)), ...); }
  253. template <typename... UTypes, std::size_t... I>
  254. constexpr void __move_assignment(
  255. tuple<UTypes...>&& other, std::index_sequence<I...>)
  256. {
  257. ((std::get<I>(*this) = std::forward<UTypes>(std::get<I>(other))), ...);
  258. }
  259. public:
  260. template <typename _ = void, std::enable_if_t<
  261. (... && std::is_default_constructible_v<Types>)
  262. && __helpers::template_true_type<_>::value
  263. , bool> = true>
  264. constexpr tuple() : base() {}
  265. template <typename _ = void, std::enable_if_t<
  266. sizeof...(Types) >= 1
  267. && (... && std::is_copy_constructible_v<Types>)
  268. && __helpers::template_true_type<_>::value
  269. , bool> = true>
  270. constexpr tuple(const Types&... args)
  271. : base(args...) {}
  272. template <typename... UTypes, std::enable_if_t<
  273. sizeof...(UTypes) == sizeof...(Types)
  274. && sizeof...(Types) >= 1
  275. && (... && std::is_constructible_v<Types, UTypes>)
  276. && !(sizeof...(Types) == 1
  277. && (... && std::is_same_v<tuple, std::remove_cvref_t<UTypes>>))
  278. , bool> = true>
  279. constexpr tuple(UTypes&&... args)
  280. : base(std::forward<UTypes>(args)...) {}
  281. template <typename... UTypes, std::enable_if_t<
  282. __helpers::tuple_constraints<Types...>::template
  283. tuple_copy_move_constructible<const tuple<UTypes...>&, UTypes...>::value
  284. , bool> = true>
  285. constexpr tuple(const tuple<UTypes...>& other)
  286. : base(other) {}
  287. template <typename... UTypes, std::enable_if_t<
  288. __helpers::tuple_constraints<Types...>::template
  289. tuple_copy_move_constructible<tuple<UTypes...>&&, UTypes...>::value
  290. , bool> = true>
  291. constexpr tuple(tuple<UTypes...>&& other)
  292. : base(std::move(other)) {}
  293. template <typename U1, typename U2, std::enable_if_t<
  294. __helpers::tuple_constraints<Types...>::template
  295. tuple_pair_constructible<const std::pair<U1, U2>&>::value
  296. , bool> = true>
  297. constexpr tuple(const std::pair<U1, U2>& p)
  298. : base(std::get<0>(p), std::get<1>(p)) {}
  299. template <typename U1, typename U2, std::enable_if_t<
  300. __helpers::tuple_constraints<Types...>::template
  301. tuple_pair_constructible<std::pair<U1, U2>&&>::value
  302. , bool> = true>
  303. constexpr tuple(std::pair<U1, U2>&& p)
  304. : base(std::get<0>(std::move(p)), std::get<1>(std::move(p))) {}
  305. constexpr tuple(const tuple&) = default;
  306. constexpr tuple(tuple&&) = default;
  307. constexpr tuple& operator=(const tuple& other) = default;
  308. constexpr tuple& operator=(tuple&& other) = default;
  309. template <typename... UTypes, std::enable_if_t<
  310. sizeof...(Types) == sizeof...(UTypes)
  311. && (... && std::is_assignable_v<Types&, const UTypes&>)
  312. , bool> = true>
  313. constexpr tuple& operator=(const tuple<UTypes...>& other)
  314. {
  315. __copy_assignment(other, index_sequence_for<Types...> {});
  316. return *this;
  317. }
  318. template <typename... UTypes, std::enable_if_t<
  319. sizeof...(Types) == sizeof...(UTypes)
  320. && (... && std::is_assignable_v<Types&, UTypes>)
  321. , bool> = true>
  322. constexpr tuple& operator=(tuple<UTypes...>&& other)
  323. {
  324. __move_assignment(std::move(other), index_sequence_for<Types...> {});
  325. return *this;
  326. }
  327. template <typename U1, typename U2, std::enable_if_t<
  328. __helpers::tuple_constraints<Types...>::template
  329. tuple_pair_copy_assignable<U1, U2>::value
  330. , bool> = true>
  331. constexpr tuple& operator=(const std::pair<U1, U2>& p)
  332. {
  333. std::get<0>(*this) = p.first;
  334. std::get<1>(*this) = p.second;
  335. return *this;
  336. }
  337. template <typename U1, typename U2, std::enable_if_t<
  338. __helpers::tuple_constraints<Types...>::template
  339. tuple_pair_move_assignable<U1, U2>::value
  340. , bool> = true>
  341. constexpr tuple& operator=(std::pair<U1, U2>&& p)
  342. {
  343. std::get<0>(*this) = std::forward<U1>(p.first);
  344. std::get<1>(*this) = std::forward<U2>(p.second);
  345. return *this;
  346. }
  347. constexpr void swap(tuple& other) { std::swap(*this, other); }
  348. };
  349. template <typename... Types>
  350. tuple(Types...) -> tuple<Types...>;
  351. namespace __helpers {
  352. struct ignore_t {
  353. template <typename T>
  354. constexpr void operator=(T&&) const noexcept {}
  355. };
  356. template <typename Func, typename Tuple, std::size_t... I>
  357. constexpr auto apply_impl(Func&& func, Tuple&& tpl, std::index_sequence<I...>)
  358. {
  359. return std::invoke(
  360. std::forward<Func>(func),
  361. std::get<I>(std::forward<Tuple>(tpl))...);
  362. }
  363. } // namespace __helpers
  364. inline constexpr __helpers::ignore_t ignore;
  365. template <typename... Types>
  366. constexpr void swap(std::tuple<Types...>& lhs, std::tuple<Types...>& rhs)
  367. noexcept(noexcept(lhs.swap(rhs)))
  368. {
  369. lhs.swap(rhs);
  370. }
  371. template <typename... Types>
  372. constexpr auto make_tuple(Types&&... args)
  373. -> std::tuple<__helpers::to_tuple_type_t<Types>...>
  374. {
  375. return std::tuple<__helpers::to_tuple_type_t<Types>...>
  376. { std::forward<Types>(args)... };
  377. }
  378. template <typename... Types>
  379. constexpr std::tuple<Types&...> tie(Types&... args) noexcept
  380. {
  381. return { args... };
  382. }
  383. template <typename... Types>
  384. constexpr std::tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept
  385. {
  386. return { std::forward<Types>(args)... };
  387. }
  388. template <typename Func, typename Tuple>
  389. constexpr decltype(auto) apply(Func&& func, Tuple&& tpl)
  390. {
  391. return __helpers::apply_impl(
  392. std::forward<Func>(func), std::forward<Tuple>(tpl),
  393. std::make_index_sequence<
  394. std::tuple_size_v<std::remove_cvref_t<Tuple>>> {}
  395. );
  396. }
  397. } // namespace std
  398. #endif