get.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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
  7. // Eric Friedman, Itay Maman
  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/throw_exception.hpp"
  18. #include "boost/utility/addressof.hpp"
  19. #include "boost/variant/variant_fwd.hpp"
  20. #include "boost/type_traits/add_reference.hpp"
  21. #include "boost/type_traits/add_pointer.hpp"
  22. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  23. # include "boost/mpl/bool.hpp"
  24. # include "boost/mpl/or.hpp"
  25. # include "boost/type_traits/is_same.hpp"
  26. #endif
  27. namespace boost {
  28. //////////////////////////////////////////////////////////////////////////
  29. // class bad_get
  30. //
  31. // The exception thrown in the event of a failed get of a value.
  32. //
  33. class bad_get
  34. : public std::exception
  35. {
  36. public: // std::exception implementation
  37. virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
  38. {
  39. return "boost::bad_get: "
  40. "failed value get using boost::get";
  41. }
  42. };
  43. //////////////////////////////////////////////////////////////////////////
  44. // function template get<T>
  45. //
  46. // Retrieves content of given variant object if content is of type T.
  47. // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
  48. //
  49. namespace detail { namespace variant {
  50. // (detail) class template get_visitor
  51. //
  52. // Generic static visitor that: if the value is of the specified type,
  53. // returns a pointer to the value it visits; else a null pointer.
  54. //
  55. template <typename T>
  56. struct get_visitor
  57. {
  58. private: // private typedefs
  59. typedef typename add_pointer<T>::type pointer;
  60. typedef typename add_reference<T>::type reference;
  61. public: // visitor typedefs
  62. typedef pointer result_type;
  63. public: // visitor interfaces
  64. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  65. pointer operator()(reference operand) const
  66. {
  67. return boost::addressof(operand);
  68. }
  69. template <typename U>
  70. pointer operator()(const U&) const
  71. {
  72. return static_cast<pointer>(0);
  73. }
  74. #else // MSVC6
  75. private: // helpers, for visitor interfaces (below)
  76. pointer execute_impl(reference operand, mpl::true_) const
  77. {
  78. return boost::addressof(operand);
  79. }
  80. template <typename U>
  81. pointer execute_impl(const U& operand, mpl::false_) const
  82. {
  83. return static_cast<pointer>(0);
  84. }
  85. public: // visitor interfaces
  86. template <typename U>
  87. pointer operator()(U& operand) const
  88. {
  89. // MSVC6 finds normal implementation (above) ambiguous,
  90. // so we must explicitly disambiguate
  91. typedef typename mpl::or_<
  92. is_same<U, T>
  93. , is_same<const U, T>
  94. >::type U_is_T;
  95. return execute_impl(operand, U_is_T());
  96. }
  97. #endif // MSVC6 workaround
  98. };
  99. }} // namespace detail::variant
  100. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
  101. # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
  102. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)
  103. #else
  104. # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
  105. , t* = 0
  106. #endif
  107. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  108. inline
  109. typename add_pointer<U>::type
  110. get(
  111. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  112. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  113. )
  114. {
  115. typedef typename add_pointer<U>::type U_ptr;
  116. if (!operand) return static_cast<U_ptr>(0);
  117. detail::variant::get_visitor<U> v;
  118. return operand->apply_visitor(v);
  119. }
  120. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  121. inline
  122. typename add_pointer<const U>::type
  123. get(
  124. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
  125. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  126. )
  127. {
  128. typedef typename add_pointer<const U>::type U_ptr;
  129. if (!operand) return static_cast<U_ptr>(0);
  130. detail::variant::get_visitor<const U> v;
  131. return operand->apply_visitor(v);
  132. }
  133. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  134. inline
  135. typename add_reference<U>::type
  136. get(
  137. boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  138. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  139. )
  140. {
  141. typedef typename add_pointer<U>::type U_ptr;
  142. U_ptr result = get<U>(&operand);
  143. if (!result)
  144. boost::throw_exception(bad_get());
  145. return *result;
  146. }
  147. template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
  148. inline
  149. typename add_reference<const U>::type
  150. get(
  151. const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
  152. BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
  153. )
  154. {
  155. typedef typename add_pointer<const U>::type U_ptr;
  156. U_ptr result = get<const U>(&operand);
  157. if (!result)
  158. boost::throw_exception(bad_get());
  159. return *result;
  160. }
  161. } // namespace boost
  162. #endif // BOOST_VARIANT_GET_HPP