Advertisement
Guest User

Untitled

a guest
Mar 23rd, 2019
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.87 KB | None | 0 0
  1. #ifndef VARIANT_H
  2. #define VARIANT_H
  3. #include <iostream>
  4. #include <utility>
  5. #include <typeinfo>
  6. #include <type_traits>
  7. #include <functional>
  8. #include "storage.h"
  9. #include "util.h"
  10.  
  11. /////////////////////////////////////////////////////// ALTERNATIVE
  12.  
  13. template<typename A, typename ... As>
  14. struct variant;
  15.  
  16. template<size_t N, typename A>
  17. struct variant_alternative;
  18.  
  19. template<size_t N, typename A, typename ... As>
  20. struct variant_alternative<N, variant<A, As...>> {
  21. using type = typename variant_alternative<N - 1, variant<As...>>::type;
  22. };
  23.  
  24. template<typename A, typename ... As>
  25. struct variant_alternative<0, variant<A, As...>> {
  26. using type = A;
  27. };
  28.  
  29. template <size_t N, typename A>
  30. using variant_alternative_t = typename variant_alternative<N, A>::type;
  31.  
  32.  
  33. struct empty;
  34.  
  35. template<size_t N, typename ... As>
  36. struct variant_alternative<N, variant<As...>> {
  37. using type = empty;
  38. };
  39.  
  40. template <typename ... As>
  41. inline const size_t variant_size_v = sizeof ... (As);
  42.  
  43.  
  44. template<typename U, typename ... Ts>
  45. inline const bool is_unique_v = count_type<U, Ts...>::value <= 1;
  46.  
  47.  
  48. template<typename T>
  49. struct single_type {
  50. static T f(T);
  51. };
  52.  
  53. template<typename T, typename ... Ts>
  54. struct select_type : single_type<T>, select_type<Ts...> {
  55. using select_type<Ts...>::f;
  56. using single_type<T>::f;
  57. };
  58.  
  59. template<typename T>
  60. struct select_type<T> : single_type<T> {
  61. using single_type<T>::f;
  62. };
  63.  
  64. template<typename U, typename T, typename ... Ts>
  65. using select_type_t = decltype(select_type<T, Ts...>::f(std::declval<U>()));
  66.  
  67.  
  68. template<typename T>
  69. struct is_in_place_index_specialization {
  70. static const bool value = false;
  71. };
  72.  
  73. template<size_t N>
  74. struct is_in_place_index_specialization<std::in_place_index_t<N>> {
  75. static const bool value = true;
  76. };
  77.  
  78. class bad_variant_access : std::exception {};
  79.  
  80. template <size_t N, typename ... Ts>
  81. decltype(auto) get(variant<Ts...>& v) {
  82. if (v.index() != N) {
  83. throw bad_variant_access();
  84. }
  85. return get_storage_data(pos<N>(), v.get_storage());
  86. }
  87.  
  88. template <size_t N, typename ... Ts>
  89. variant_alternative_t<N, variant<Ts...>>&& get(variant<Ts...>&& v) {
  90. if (v.index() != N) {
  91. throw bad_variant_access();
  92. }
  93. return get_storage_data(pos<N>(), std::move(v).get_storage());
  94. }
  95.  
  96. template <size_t N, typename ... Ts>
  97. decltype(auto) get(const variant<Ts...> & v) {
  98. if (v.index() != N) {
  99. throw bad_variant_access();
  100. }
  101. return get_storage_data(pos<N>(), v.get_storage());
  102. }
  103.  
  104. template <size_t N, typename ... Ts>
  105. decltype(auto) get(const variant<Ts...>&& v) {
  106. if (v.index() != N) {
  107. throw bad_variant_access();
  108. }
  109. return get_storage_data(pos<N>(), std::move(v).get_storage());
  110. }
  111.  
  112. template <typename T, typename ... Ts,
  113. size_t N = get_type_index<T, Ts...>::value>
  114. decltype(auto) get(variant<Ts...>& v) {
  115. return get<N>(v);
  116. }
  117.  
  118. template <typename T, typename ... Ts,
  119. size_t N = get_type_index<T, Ts...>::value>
  120. decltype(auto) get(variant<Ts...>&& v) {
  121. return get<N>(std::move(v));
  122. }
  123.  
  124. template <typename T, typename ... Ts,
  125. size_t N = get_type_index<T, Ts...>::value>
  126. decltype(auto) get(variant<Ts...> const& v) {
  127. return get<N>(v);
  128. }
  129.  
  130. template <typename T, typename ... Ts,
  131. size_t N = get_type_index<T, Ts...>::value>
  132. decltype(auto) get(variant<Ts...> const&& v) {
  133. return get<N>(std::move(v));
  134. }
  135.  
  136. template<typename T0, typename... Ts>
  137. struct variant: copy_assignable_storage_t<T0, Ts...> {
  138. private:
  139. using data = copy_assignable_storage_t<T0, Ts...>;
  140.  
  141. using data::valueless_by_exception_impl;
  142. using data::set_index;
  143. using data::ind;
  144. using data::reset;
  145. using data::move_constructor;
  146. using data::build_at;
  147.  
  148. template <size_t N>
  149. using get_type_t = variant_alternative_t<N, variant>;
  150.  
  151. public:
  152. template<typename = std::enable_if_t<std::is_default_constructible_v<T0>>>
  153. variant(): data(pos<0>()) {}
  154.  
  155. template <typename T, typename varT = select_type_t<T, T0, Ts...>,
  156. typename = std::enable_if_t<
  157. !std::is_same_v<std::decay_t<T>, variant> &&
  158. std::is_constructible_v<varT, T> &&
  159. is_unique_v<varT, T0, Ts...> >,
  160. size_t N = get_type_index<varT, T0, Ts...>::value>
  161. variant(T&& t): data(pos<N>(), std::forward<T>(t)) {}
  162.  
  163.  
  164. template <typename T, typename ...Args,
  165. size_t N = get_type_index<T, T0, Ts...>::value,
  166. typename = std::enable_if_t<
  167. (N != -1) &&
  168. std::is_constructible_v<T, Args...> &&
  169. is_unique_v<std::in_place_type<T>, T0, Ts...> >>
  170. variant(std::in_place_type_t<T> t, Args&&... args):
  171. data(pos<N>(), std::forward<Args>(args)...) {}
  172.  
  173. template <size_t N, typename ...Args, typename T = get_type_t<N>,
  174. typename = std::enable_if_t<
  175. (N != -1) &&
  176. std::is_constructible_v<T, Args...>
  177. >
  178. >
  179. variant(std::in_place_index_t<N>, Args&&... args):
  180. data(pos<N>(), std::forward<Args>(args)...) {}
  181.  
  182. template<typename T, typename varT = select_type_t<T, T0, Ts...>,
  183. typename = std::enable_if_t<std::is_constructible_v<varT, T> && std::is_assignable_v<varT&, T>&&
  184. is_unique_v<varT, T0, Ts...> >,
  185. size_t N = get_type_index<varT, T0, Ts...>::value>
  186. variant& operator=(T&& t) {
  187. if(N == index()) {
  188. get<N>(*this) = std::forward<T>(t);
  189. return *this;
  190. }
  191. return this->operator=(variant(std::forward<T>(t)));
  192. }
  193.  
  194. size_t index() const {
  195. return ind();
  196. // -1
  197. }
  198.  
  199. template <typename T, typename... Args, size_t N = get_type_index<T, T0, Ts...>::value,
  200. typename = std::enable_if_t<std::is_constructible_v<T, Args...> && is_unique_v<T, T0, Ts...> >>
  201. T& emplace(Args&&... args) {
  202. reset(index());
  203. build_at(index(), std::forward<Args>(args)...);
  204. return get_storage_data(pos<N>(), *this);
  205. }
  206. template <size_t N, typename... Args, typename T = get_type_t<N>,
  207. typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
  208. variant_alternative_t<N, variant>& emplace(Args&&... args) {
  209. return emplace<T>(std::forward<Args>(args)...);
  210. }
  211.  
  212. bool valueless_by_exception() const {
  213. return valueless_by_exception_impl();
  214. }
  215. };
  216.  
  217. template <typename T, typename ... Types>
  218. bool holds_alternative(const variant<Types...>& v) {
  219. return !v.valueless_by_exception() && v.index() == get_type_index<T, Types...>::value;
  220. }
  221.  
  222. template <size_t N, typename ... Ts>
  223. decltype(auto) get_if(variant<Ts...>* pv) {
  224. if (N >= sizeof... (Ts)) {
  225. throw bad_variant_access();
  226. }
  227. if (pv != nullptr && pv->index() != N) {
  228. return &get<N>(*pv);
  229. }
  230. return nullptr;
  231. }
  232.  
  233. template <size_t N, typename ... Ts>
  234. decltype(auto) get_if(const variant<Ts...>* pv) {
  235. if (N >= sizeof...(Ts)) {
  236. throw bad_variant_access();
  237. }
  238. if (pv != nullptr && pv->index() != N) {
  239. return &get<N>(*pv);
  240. }
  241. return nullptr;
  242. }
  243.  
  244. template <typename T, typename ... Ts, typename = std::enable_if_t<is_unique_v<T, Ts...> > >
  245. decltype(auto) get_if(variant<Ts...>* pv) {
  246. size_t N = get_type_index<T, Ts...>();
  247. return get_if<N>(pv);
  248. }
  249.  
  250. template <typename T, typename ... Ts, typename = std::enable_if_t<is_unique_v<T, Ts...> > >
  251. decltype(auto) get_if(const variant<Ts...>* pv) {
  252. size_t N = get_type_index<T, Ts...>();
  253. return get_if<N>(pv);
  254. }
  255.  
  256.  
  257. template<typename T, size_t... dimensions>
  258. struct multi_array {
  259. constexpr const T& access() const{
  260. return data;
  261. }
  262. T data;
  263. };
  264.  
  265. template<typename T, size_t first, size_t... rest>
  266. struct multi_array<T, first, rest...> {
  267. template<typename... Args>
  268. constexpr const T& access(size_t first_index, Args... rest_indices) const {
  269. return arr[first_index].access(rest_indices...);
  270. }
  271.  
  272. multi_array<T, rest...> arr[first];
  273. };
  274.  
  275. template<typename array_type, typename variant_tuple, typename index_seq>
  276. struct gen_vtable_impl;
  277.  
  278. template<typename result_type, typename visitor, size_t... dimensions, typename... variants, size_t... indices>
  279. struct gen_vtable_impl<
  280. multi_array<result_type (*)(visitor, variants...), dimensions...>,
  281. std::tuple<variants...>, std::index_sequence<indices...> > {
  282. using next = std::remove_reference_t<typename nth_type<sizeof...(indices),variants...>::type>;
  283. using array_type = multi_array<result_type (*)(visitor, variants...), dimensions...>;
  284.  
  285. static constexpr array_type apply()
  286. {
  287. array_type vtable{};
  288. apply_all(vtable, std::make_index_sequence<variant_size_v<next>>());
  289. return vtable;
  290. }
  291.  
  292. template<size_t... var_indices>
  293. static constexpr void apply_all(array_type& vtable, std::index_sequence<var_indices...>) {
  294. (apply_single<var_indices>(vtable.arr[var_indices]), ...);
  295. }
  296.  
  297. template<size_t index, typename T>
  298. static constexpr void apply_single(T& element) {
  299. element = gen_vtable_impl<
  300. std::remove_reference_t<decltype(element)>,
  301. std::tuple<variants...>,
  302. std::index_sequence<indices..., index>>::apply();
  303. }
  304. };
  305.  
  306. template<typename result_type, typename visitor, typename... variants, size_t... indices>
  307. struct gen_vtable_impl<
  308. multi_array<result_type (*)(visitor, variants...)>,
  309. std::tuple<variants...>,
  310. std::index_sequence<indices...> > {
  311. using array_type = multi_array<result_type (*)(visitor&&, variants...)>;
  312.  
  313. decltype(auto) static constexpr visit_invoke(visitor&& vis, variants... vars) {
  314. return std::invoke(std::forward<visitor>(vis), get<indices>(std::forward<variants>(vars))...);
  315. }
  316. static constexpr auto apply() {
  317. return array_type{&visit_invoke};
  318. }
  319. };
  320.  
  321. template<typename result_type, typename visitor, typename... variants>
  322. struct gen_vtable {
  323. using func_ptr = result_type (*)(visitor&&, variants...);
  324. using array_type = multi_array<func_ptr, variant_size_v<std::remove_reference_t<variants>>...>;
  325.  
  326. static constexpr array_type apply()
  327. {
  328. return gen_vtable_impl<array_type, std::tuple<variants...>, std::index_sequence<>>::apply();
  329. }
  330.  
  331. static constexpr auto vtable = apply();
  332. };
  333.  
  334. template<typename Visitor, typename... Variants>
  335. constexpr decltype(auto) visit(Visitor&& visitor, Variants&& ... variants) {
  336. if ((variants.valueless_by_exception() || ...)) {
  337. throw bad_variant_access();
  338. }
  339.  
  340. using result_type = decltype(std::forward<Visitor>(visitor)(get<0>(std::forward<Variants>(variants))...));
  341.  
  342. constexpr auto& v_table = gen_vtable<result_type, Visitor&&, Variants&&...>::vtable;
  343. auto func_ptr = v_table.access(variants.index()...);
  344.  
  345. return (*func_ptr)(std::forward<Visitor>(visitor), std::forward<Variants>(variants)...);
  346. }
  347.  
  348. auto comparator = [](auto&& action) constexpr {
  349. return ([action](auto&& a, auto&& b) constexpr -> bool {
  350. if constexpr(std::is_same_v<decltype(a), decltype(b)>){
  351. return action(a, b);
  352. } else {
  353. return 0;
  354. }
  355. });
  356. };
  357.  
  358. //template<typename T, size_t... dimensions>
  359. //struct multi_array {
  360. // const T& access() const {
  361. // return data;
  362. // }
  363. // T data;
  364. //};
  365.  
  366. //template<typename T, size_t first, size_t... rest>
  367. //struct multi_array<T, first, rest...> {
  368. // template<typename... Args>
  369. // const T& access(size_t first_index, Args... rest_indices) const {
  370. // return arr[first_index].access(rest_indices...);
  371. // }
  372.  
  373. // multi_array<T, rest...> arr[first];
  374. //};
  375.  
  376. //template<typename array_type, typename variant_tuple, typename index_seq>
  377. //struct gen_vtable_impl;
  378.  
  379. //template<typename result_type, typename visitor, size_t... dimensions, typename... variants, size_t... indices>
  380. //struct gen_vtable_impl<
  381. // multi_array<result_type (*)(visitor, variants...), dimensions...>,
  382. // std::tuple<variants...>,
  383. // std::index_sequence<indices...> > {
  384. // using next = std::remove_reference_t<typename nth_type<size_t(sizeof...(indices)),variants...>::type>;
  385. // using array_type = multi_array<result_type (*)(visitor, variants...), dimensions...>;
  386.  
  387. // static array_type apply() {
  388. // array_type vtable{};
  389. // apply_all(vtable, std::make_index_sequence<variant_size_v<next>>());
  390. // return vtable;
  391. // }
  392.  
  393. // template<size_t... var_indices>
  394. // static void apply_all(array_type& vtable, std::index_sequence<var_indices...>) {
  395. // (apply_single<var_indices>(vtable.arr[var_indices]), ...);
  396. // }
  397.  
  398. // template<size_t index, typename T>
  399. // static void apply_single(T& element) {
  400. // element = gen_vtable_impl<
  401. // std::remove_reference_t<decltype(element)>,
  402. // std::tuple<variants...>,
  403. // std::index_sequence<indices..., index>>::apply();
  404. // }
  405. //};
  406.  
  407. //template<typename result_type, typename visitor, typename... variants, size_t... indices>
  408. //struct gen_vtable_impl<
  409. // multi_array<result_type (*)(visitor, variants...)>,
  410. // std::tuple<variants...>,
  411. // std::index_sequence<indices...> > {
  412. // using array_type = multi_array<result_type (*)(visitor&&, variants...)>;
  413.  
  414. // decltype(auto) static visit_invoke(visitor&& vis, variants... vars) {
  415. // return std::invoke(std::forward<visitor>(vis), get<indices>(std::forward<variants>(vars))...);
  416. // }
  417. // static auto apply() {
  418. // return array_type(&visit_invoke);
  419. // }
  420. //};
  421.  
  422. //template<typename result_type, typename visitor, typename... variants>
  423. //struct gen_vtable {
  424. // using func_ptr = result_type (*)(visitor&&, variants...);
  425. // using array_type = multi_array<func_ptr, variant_size_v<std::remove_reference_t<variants>>...>;
  426.  
  427. // static array_type apply() {
  428. // return gen_vtable_impl<array_type, std::tuple<variants...>, std::index_sequence<>>::apply();
  429. // }
  430.  
  431. // static const auto vtable = apply();
  432. //};
  433.  
  434.  
  435. //template<typename Var, typename ... Vars>
  436. //bool check_valueless(Var one, Vars ... other) {
  437. // return one.valueless_by_exception() || check_valueless(other.valueless_by_exception() ...);
  438. //}
  439.  
  440. //bool check_valueless() {
  441. // return false;
  442. //}
  443.  
  444.  
  445. //template<typename V, typename ... Vars>
  446. //decltype(auto) visit(V&& visitor, Vars&& ... vars) {
  447. // if (check_valueless(vars ...)) {
  448. // throw bad_variant_access();
  449. // }
  450.  
  451. // using result_type = decltype(std::forward<V>(visitor)(get<0>(std::forward<Vars>(vars))...));
  452.  
  453. // auto& v_table = gen_vtable<result_type, V&&, Vars&&...>::vtable;
  454. // auto func_ptr = v_table.access(vars.index()...);
  455.  
  456. // return (*func_ptr)(std::forward<V>(visitor), std::forward<Vars>(vars)...);
  457. //}
  458.  
  459. #endif // VARIANT_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement