tuple 11 KB

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