xvariant.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_XVARIANT_HPP
  10. #define XTL_XVARIANT_HPP
  11. #include "xvariant_impl.hpp"
  12. #include "xclosure.hpp"
  13. #include "xmeta_utils.hpp"
  14. namespace xtl
  15. {
  16. using mpark::variant;
  17. using mpark::monostate;
  18. using mpark::bad_variant_access;
  19. using mpark::variant_size;
  20. #ifdef MPARK_VARIABLE_TEMPLATES
  21. using mpark::variant_size_v;
  22. #endif
  23. using mpark::variant_alternative;
  24. using mpark::variant_alternative_t;
  25. using mpark::variant_npos;
  26. using mpark::visit;
  27. using mpark::holds_alternative;
  28. using mpark::get;
  29. using mpark::get_if;
  30. namespace detail
  31. {
  32. template <class T>
  33. struct xgetter
  34. {
  35. template <class... Ts>
  36. static constexpr T& get(xtl::variant<Ts...>& v)
  37. {
  38. return xtl::get<T>(v);
  39. }
  40. template <class... Ts>
  41. static constexpr T&& get(xtl::variant<Ts...>&& v)
  42. {
  43. return xtl::get<T>(std::move(v));
  44. }
  45. template <class... Ts>
  46. static constexpr const T& get(const xtl::variant<Ts...>& v)
  47. {
  48. return xtl::get<T>(v);
  49. }
  50. template <class... Ts>
  51. static constexpr const T&& get(const xtl::variant<Ts...>&& v)
  52. {
  53. return xtl::get<T>(std::move(v));
  54. }
  55. };
  56. template <class T>
  57. struct xgetter<T&>
  58. {
  59. template <class... Ts>
  60. static constexpr T& get(xtl::variant<Ts...>& v)
  61. {
  62. return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
  63. }
  64. template <class... Ts>
  65. static constexpr T& get(xtl::variant<Ts...>&& v)
  66. {
  67. return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
  68. }
  69. template <class... Ts>
  70. static constexpr const T& get(const xtl::variant<Ts...>& v)
  71. {
  72. return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
  73. }
  74. template <class... Ts>
  75. static constexpr const T& get(const xtl::variant<Ts...>&& v)
  76. {
  77. return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
  78. }
  79. };
  80. template <class T>
  81. struct xgetter<const T&>
  82. {
  83. template <class... Ts>
  84. static constexpr const T& get(const xtl::variant<Ts...>& v)
  85. {
  86. using cl_type = xtl::xclosure_wrapper<const T&>;
  87. return get_impl(v, xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
  88. }
  89. template <class... Ts>
  90. static constexpr const T& get(const xtl::variant<Ts...>&& v)
  91. {
  92. using cl_type = xtl::xclosure_wrapper<const T&>;
  93. return get_impl(std::move(v), xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
  94. }
  95. template <class... Ts>
  96. static constexpr const T& get(xtl::variant<Ts...>& v)
  97. {
  98. return get(static_cast<const xtl::variant<Ts...>&>(v));
  99. }
  100. template <class... Ts>
  101. static constexpr const T& get(xtl::variant<Ts...>&& v)
  102. {
  103. return get(static_cast<const xtl::variant<Ts...>&&>(v));
  104. }
  105. private:
  106. template <class... Ts>
  107. static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<true>)
  108. {
  109. return xtl::get<xtl::xclosure_wrapper<const T&>>(v).get();
  110. }
  111. template <class... Ts>
  112. static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<false>)
  113. {
  114. return static_cast<const xtl::xclosure_wrapper<T&>&>(xtl::get<xtl::xclosure_wrapper<T&>>(v)).get();
  115. }
  116. template <class... Ts>
  117. static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<true>)
  118. {
  119. return xtl::get<xtl::closure_wrapper<const T&>>(std::move(v)).get();
  120. }
  121. template <class... Ts>
  122. static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<false>)
  123. {
  124. return static_cast<const xtl::xclosure_wrapper<T&>&&>(xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v))).get();
  125. }
  126. };
  127. }
  128. template <class T, class... Ts>
  129. constexpr decltype(auto) xget(xtl::variant<Ts...>& v)
  130. {
  131. return detail::xgetter<T>::get(v);
  132. }
  133. template <class T, class... Ts>
  134. constexpr decltype(auto) xget(xtl::variant<Ts...>&& v)
  135. {
  136. return detail::xgetter<T>::get(std::move(v));
  137. }
  138. template <class T, class... Ts>
  139. constexpr decltype(auto) xget(const xtl::variant<Ts...>& v)
  140. {
  141. return detail::xgetter<T>::get(v);
  142. }
  143. template <class T, class... Ts>
  144. constexpr decltype(auto) xget(const xtl::variant<Ts...>&& v)
  145. {
  146. return detail::xgetter<T>::get(std::move(v));
  147. }
  148. /************************
  149. * overload for lambdas *
  150. ************************/
  151. // This hierarchy is required since ellipsis in using declarations are not supported until C++17
  152. template <class... Ts>
  153. struct overloaded;
  154. template <class T>
  155. struct overloaded<T> : T
  156. {
  157. overloaded(T arg) : T(arg) {}
  158. using T::operator();
  159. };
  160. template <class T1, class T2, class... Ts>
  161. struct overloaded<T1, T2, Ts...> : T1, overloaded<T2, Ts...>
  162. {
  163. template <class... Us>
  164. overloaded(T1 t1, T2 t2, Us... args) : T1(t1), overloaded<T2, Ts...>(t2, args...) {}
  165. using T1::operator();
  166. using overloaded<T2, Ts...>::operator();
  167. };
  168. template <class... Ts>
  169. inline overloaded<Ts...> make_overload(Ts... arg)
  170. {
  171. return overloaded<Ts...>{arg...};
  172. }
  173. }
  174. #endif