get.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //-----------------------------------------------------------------------------
  2. // boost variant/get.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2003 Eric Friedman, Itay Maman
  7. // Copyright (c) 2014 Antony Polukhin
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_VARIANT_GET_HPP
  13. #define BOOST_VARIANT_GET_HPP
  14. #include <exception>
  15. #include "boost/config.hpp"
  16. #include "boost/detail/workaround.hpp"
  17. #include "boost/static_assert.hpp"
  18. #include "boost/throw_exception.hpp"
  19. #include "boost/utility/addressof.hpp"
  20. #include "boost/variant/variant_fwd.hpp"
  21. #include "boost/variant/detail/element_index.hpp"
  22. #include "boost/type_traits/add_reference.hpp"
  23. #include "boost/type_traits/add_pointer.hpp"
  24. namespace boost {
  25. //////////////////////////////////////////////////////////////////////////
  26. // class bad_get
  27. //
  28. // The exception thrown in the event of a failed get of a value.
  29. //
  30. class BOOST_SYMBOL_VISIBLE bad_get
  31. : public std::exception
  32. {
  33. public: // std::exception implementation
  34. virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
  35. {
  36. return "boost::bad_get: "
  37. "failed value get using boost::get";
  38. }
  39. };
  40. //////////////////////////////////////////////////////////////////////////
  41. // function template get<T>
  42. //
  43. // Retrieves content of given variant object if content is of type T.
  44. // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
  45. //
  46. namespace detail { namespace variant {
  47. // (detail) class template get_visitor
  48. //
  49. // Generic static visitor that: if the value is of the specified type,
  50. // returns a pointer to the value it visits; else a null pointer.
  51. //
  52. template <typename T>
  53. struct get_visitor
  54. {
  55. private: // private typedefs
  56. typedef typename add_pointer<T>::type pointer;
  57. typedef typename add_reference<T>::type reference;
  58. public: // visitor typedefs
  59. typedef pointer result_type;
  60. public: // visitor interfaces
  61. pointer operator()(reference operand) const BOOST_NOEXCEPT
  62. {
  63. return boost::addressof(operand);
  64. }
  65. template <typename U>
  66. pointer operator()(const U&) const BOOST_NOEXCEPT
  67. {
  68. return static_cast<pointer>(0);
  69. }
  70. };
  71. }} // namespace detail::variant
  72. #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
  73. # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
  74. # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
  75. # else
  76. # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
  77. , t* = 0
  78. # endif
  79. #endif
  80. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. // relaxed_get<U>(variant) methods
  82. //
  83. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  84. inline
  85. typename add_pointer<U>::type
  86. relaxed_get(
  87. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  88. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  89. ) BOOST_NOEXCEPT
  90. {
  91. typedef typename add_pointer<U>::type U_ptr;
  92. if (!operand) return static_cast<U_ptr>(0);
  93. detail::variant::get_visitor<U> v;
  94. return operand->apply_visitor(v);
  95. }
  96. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  97. inline
  98. typename add_pointer<const U>::type
  99. relaxed_get(
  100. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  101. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  102. ) BOOST_NOEXCEPT
  103. {
  104. typedef typename add_pointer<const U>::type U_ptr;
  105. if (!operand) return static_cast<U_ptr>(0);
  106. detail::variant::get_visitor<const U> v;
  107. return operand->apply_visitor(v);
  108. }
  109. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  110. inline
  111. typename add_reference<U>::type
  112. relaxed_get(
  113. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  114. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  115. )
  116. {
  117. typedef typename add_pointer<U>::type U_ptr;
  118. U_ptr result = relaxed_get<U>(&operand);
  119. if (!result)
  120. boost::throw_exception(bad_get());
  121. return *result;
  122. }
  123. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  124. inline
  125. typename add_reference<const U>::type
  126. relaxed_get(
  127. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  128. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  129. )
  130. {
  131. typedef typename add_pointer<const U>::type U_ptr;
  132. U_ptr result = relaxed_get<const U>(&operand);
  133. if (!result)
  134. boost::throw_exception(bad_get());
  135. return *result;
  136. }
  137. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  138. // strict_get<U>(variant) methods
  139. //
  140. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  141. inline
  142. typename add_pointer<U>::type
  143. strict_get(
  144. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  145. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  146. ) BOOST_NOEXCEPT
  147. {
  148. BOOST_STATIC_ASSERT_MSG(
  149. (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
  150. "boost::variant does not contain specified type U, "
  151. "call to boost::get<U>(boost::variant<T...>*) will always return NULL"
  152. );
  153. return relaxed_get<U>(operand);
  154. }
  155. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  156. inline
  157. typename add_pointer<const U>::type
  158. strict_get(
  159. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  160. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  161. ) BOOST_NOEXCEPT
  162. {
  163. BOOST_STATIC_ASSERT_MSG(
  164. (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
  165. "boost::variant does not contain specified type U, "
  166. "call to boost::get<U>(const boost::variant<T...>*) will always return NULL"
  167. );
  168. return relaxed_get<U>(operand);
  169. }
  170. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  171. inline
  172. typename add_reference<U>::type
  173. strict_get(
  174. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  175. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  176. )
  177. {
  178. BOOST_STATIC_ASSERT_MSG(
  179. (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
  180. "boost::variant does not contain specified type U, "
  181. "call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception"
  182. );
  183. return relaxed_get<U>(operand);
  184. }
  185. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  186. inline
  187. typename add_reference<const U>::type
  188. strict_get(
  189. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  190. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  191. )
  192. {
  193. BOOST_STATIC_ASSERT_MSG(
  194. (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
  195. "boost::variant does not contain specified type U, "
  196. "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
  197. );
  198. return relaxed_get<U>(operand);
  199. }
  200. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  201. // get<U>(variant) methods
  202. //
  203. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  204. inline
  205. typename add_pointer<U>::type
  206. get(
  207. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  208. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  209. ) BOOST_NOEXCEPT
  210. {
  211. #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
  212. return relaxed_get<U>(operand);
  213. #else
  214. return strict_get<U>(operand);
  215. #endif
  216. }
  217. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  218. inline
  219. typename add_pointer<const U>::type
  220. get(
  221. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  222. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  223. ) BOOST_NOEXCEPT
  224. {
  225. #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
  226. return relaxed_get<U>(operand);
  227. #else
  228. return strict_get<U>(operand);
  229. #endif
  230. }
  231. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  232. inline
  233. typename add_reference<U>::type
  234. get(
  235. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  236. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  237. )
  238. {
  239. #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
  240. return relaxed_get<U>(operand);
  241. #else
  242. return strict_get<U>(operand);
  243. #endif
  244. }
  245. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  246. inline
  247. typename add_reference<const U>::type
  248. get(
  249. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  250. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  251. )
  252. {
  253. #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
  254. return relaxed_get<U>(operand);
  255. #else
  256. return strict_get<U>(operand);
  257. #endif
  258. }
  259. } // namespace boost
  260. #endif // BOOST_VARIANT_GET_HPP