variant.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM)
  7. #define BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM
  8. #include <boost/config.hpp>
  9. #include <boost/variant.hpp>
  10. #include <boost/mpl/list.hpp>
  11. #include <utility>
  12. #include <type_traits>
  13. ///////////////////////////////////////////////////////////////////////////////
  14. namespace boost { namespace spirit { namespace x3
  15. {
  16. template <typename T>
  17. class forward_ast
  18. {
  19. public:
  20. typedef T type;
  21. public:
  22. forward_ast() : p_(new T) {}
  23. forward_ast(forward_ast const& operand)
  24. : p_(new T(operand.get())) {}
  25. forward_ast(forward_ast&& operand) BOOST_NOEXCEPT
  26. : p_(operand.p_)
  27. {
  28. operand.p_ = 0;
  29. }
  30. forward_ast(T const& operand)
  31. : p_(new T(operand)) {}
  32. forward_ast(T&& operand)
  33. : p_(new T(std::move(operand))) {}
  34. ~forward_ast()
  35. {
  36. boost::checked_delete(p_);
  37. }
  38. forward_ast& operator=(forward_ast const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value)
  39. {
  40. assign(rhs.get());
  41. return *this;
  42. }
  43. void swap(forward_ast& operand) BOOST_NOEXCEPT
  44. {
  45. T* temp = operand.p_;
  46. operand.p_ = p_;
  47. p_ = temp;
  48. }
  49. forward_ast& operator=(T const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value)
  50. {
  51. assign(rhs);
  52. return *this;
  53. }
  54. forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT
  55. {
  56. swap(rhs);
  57. return *this;
  58. }
  59. forward_ast& operator=(T&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<T>::value)
  60. {
  61. get() = std::move(rhs);
  62. return *this;
  63. }
  64. T& get() BOOST_NOEXCEPT { return *get_pointer(); }
  65. const T& get() const BOOST_NOEXCEPT { return *get_pointer(); }
  66. T* get_pointer() BOOST_NOEXCEPT { return p_; }
  67. const T* get_pointer() const BOOST_NOEXCEPT { return p_; }
  68. operator T const&() const BOOST_NOEXCEPT { return this->get(); }
  69. operator T&() BOOST_NOEXCEPT { return this->get(); }
  70. private:
  71. void assign(const T& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value)
  72. {
  73. this->get() = rhs;
  74. }
  75. T* p_;
  76. };
  77. // function template swap
  78. //
  79. // Swaps two forward_ast<T> objects of the same type T.
  80. //
  81. template <typename T>
  82. inline void swap(forward_ast<T>& lhs, forward_ast<T>& rhs) BOOST_NOEXCEPT
  83. {
  84. lhs.swap(rhs);
  85. }
  86. namespace detail
  87. {
  88. template <typename T>
  89. struct remove_forward : mpl::identity<T>
  90. {};
  91. template <typename T>
  92. struct remove_forward<forward_ast<T>> : mpl::identity<T>
  93. {};
  94. }
  95. #if defined(BOOST_MSVC)
  96. # pragma warning(push)
  97. # pragma warning(disable: 4521) // multiple copy constructors specified
  98. #endif
  99. template <typename ...Types>
  100. struct variant
  101. {
  102. // tell spirit that this is an adapted variant
  103. struct adapted_variant_tag;
  104. using variant_type = boost::variant<Types...>;
  105. using types = mpl::list<typename detail::remove_forward<Types>::type...>;
  106. using base_type = variant; // The current instantiation
  107. template<typename T>
  108. using non_self_t // used only for SFINAE checks below
  109. = std::enable_if_t<!(std::is_base_of<base_type
  110. ,std::remove_reference_t<T>
  111. >
  112. ::value)
  113. >;
  114. variant() BOOST_NOEXCEPT_IF(std::is_nothrow_default_constructible<variant_type>::value) : var() {}
  115. template <typename T, class = non_self_t<T>>
  116. explicit variant(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T const&>::value))
  117. : var(rhs) {}
  118. template <typename T, class = non_self_t<T>>
  119. explicit variant(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T&&>::value))
  120. : var(std::forward<T>(rhs)) {}
  121. variant(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_constructible<variant_type>::value)
  122. : var(rhs.var) {}
  123. variant(variant& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, variant_type&>::value))
  124. : var(rhs.var) {}
  125. variant(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_constructible<variant_type>::value)
  126. : var(std::move(rhs.var)) {}
  127. variant& operator=(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<variant_type>::value)
  128. {
  129. var = rhs.get();
  130. return *this;
  131. }
  132. variant& operator=(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<variant_type>::value)
  133. {
  134. var = std::move(rhs.get());
  135. return *this;
  136. }
  137. template <typename T, class = non_self_t<T>>
  138. variant& operator=(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T const&>::value))
  139. {
  140. var = rhs;
  141. return *this;
  142. }
  143. template <typename T, class = non_self_t<T>>
  144. variant& operator=(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T&&>::value))
  145. {
  146. var = std::forward<T>(rhs);
  147. return *this;
  148. }
  149. template <typename F>
  150. typename F::result_type apply_visitor(F const& v)
  151. {
  152. return var.apply_visitor(v);
  153. }
  154. template <typename F>
  155. typename F::result_type apply_visitor(F const& v) const
  156. {
  157. return var.apply_visitor(v);
  158. }
  159. template <typename F>
  160. typename F::result_type apply_visitor(F& v)
  161. {
  162. return var.apply_visitor(v);
  163. }
  164. template <typename F>
  165. typename F::result_type apply_visitor(F& v) const
  166. {
  167. return var.apply_visitor(v);
  168. }
  169. variant_type const& get() const BOOST_NOEXCEPT
  170. {
  171. return var;
  172. }
  173. variant_type& get() BOOST_NOEXCEPT
  174. {
  175. return var;
  176. }
  177. void swap(variant& rhs) BOOST_NOEXCEPT
  178. {
  179. var.swap(rhs.var);
  180. }
  181. variant_type var;
  182. };
  183. #if defined(BOOST_MSVC)
  184. # pragma warning(pop)
  185. #endif
  186. }}}
  187. namespace boost
  188. {
  189. template <typename T, typename ...Types>
  190. inline T const&
  191. get(boost::spirit::x3::variant<Types...> const& x) BOOST_NOEXCEPT
  192. {
  193. return boost::get<T>(x.get());
  194. }
  195. template <typename T, typename ...Types>
  196. inline T&
  197. get(boost::spirit::x3::variant<Types...>& x) BOOST_NOEXCEPT
  198. {
  199. return boost::get<T>(x.get());
  200. }
  201. template <typename T, typename ...Types>
  202. inline T const*
  203. get(boost::spirit::x3::variant<Types...> const* x) BOOST_NOEXCEPT
  204. {
  205. return boost::get<T>(&x->get());
  206. }
  207. template <typename T, typename ...Types>
  208. inline T*
  209. get(boost::spirit::x3::variant<Types...>* x) BOOST_NOEXCEPT
  210. {
  211. return boost::get<T>(&x->get());
  212. }
  213. }
  214. #endif