any_cast.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011 Steven Watanabe
  4. //
  5. // Distributed under the Boost Software License Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // $Id$
  10. #ifndef BOOST_TYPE_ERASURE_ANY_CAST_HPP_INCLUDED
  11. #define BOOST_TYPE_ERASURE_ANY_CAST_HPP_INCLUDED
  12. #include <stdexcept>
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/type_traits/add_const.hpp>
  15. #include <boost/type_traits/is_pointer.hpp>
  16. #include <boost/type_traits/remove_cv.hpp>
  17. #include <boost/type_traits/remove_reference.hpp>
  18. #include <boost/type_traits/remove_pointer.hpp>
  19. #include <boost/type_traits/is_void.hpp>
  20. #include <boost/mpl/assert.hpp>
  21. #include <boost/mpl/bool.hpp>
  22. #include <boost/type_erasure/any.hpp>
  23. #include <boost/type_erasure/builtin.hpp>
  24. #include <boost/type_erasure/exception.hpp>
  25. #include <boost/type_erasure/detail/access.hpp>
  26. namespace boost {
  27. namespace type_erasure {
  28. namespace detail {
  29. template<class Concept, class T>
  30. void* get_pointer(::boost::type_erasure::any<Concept, T>& arg)
  31. {
  32. return ::boost::type_erasure::detail::access::data(arg).data;
  33. }
  34. template<class Concept, class T>
  35. const void* get_pointer(const ::boost::type_erasure::any<Concept, T>& arg)
  36. {
  37. return ::boost::type_erasure::detail::access::data(arg).data;
  38. }
  39. template<class Concept, class T>
  40. void* get_pointer(::boost::type_erasure::any<Concept, T&>& arg)
  41. {
  42. return ::boost::type_erasure::detail::access::data(arg).data;
  43. }
  44. template<class Concept, class T>
  45. void* get_pointer(const ::boost::type_erasure::any<Concept, T&>& arg)
  46. {
  47. return ::boost::type_erasure::detail::access::data(arg).data;
  48. }
  49. template<class Concept, class T>
  50. const void* get_pointer(::boost::type_erasure::any<Concept, const T&>& arg)
  51. {
  52. return ::boost::type_erasure::detail::access::data(arg).data;
  53. }
  54. template<class Concept, class T>
  55. const void* get_pointer(const ::boost::type_erasure::any<Concept, const T&>& arg)
  56. {
  57. return ::boost::type_erasure::detail::access::data(arg).data;
  58. }
  59. template<class T, class Concept, class Tag>
  60. bool check_any_cast(const any<Concept, Tag>&, ::boost::mpl::true_)
  61. {
  62. return true;
  63. }
  64. template<class T, class Concept, class Tag>
  65. bool check_any_cast(const any<Concept, Tag>& arg, ::boost::mpl::false_)
  66. {
  67. typedef typename ::boost::remove_cv<
  68. typename ::boost::remove_reference<Tag>::type
  69. >::type tag_type;
  70. return ::boost::type_erasure::detail::access::table(arg)
  71. .template find<typeid_<tag_type> >()() == typeid(T);
  72. }
  73. template<class T, class Concept, class Tag>
  74. bool check_any_cast(const any<Concept, Tag>& arg)
  75. {
  76. return ::boost::type_erasure::detail::check_any_cast<T>(
  77. arg, ::boost::is_void<typename ::boost::remove_reference<T>::type>());
  78. }
  79. }
  80. /**
  81. * Attempts to extract the object that @c arg holds.
  82. * If casting to a pointer fails, \any_cast returns
  83. * a null pointer. Casting to @c void* always succeeds
  84. * and returns the address of stored object.
  85. *
  86. * \code
  87. * any<mpl::vector<typeid_<>, copy_constructible<> > > x(1);
  88. * any_cast<int>(x); // returns 1
  89. * any_cast<int&>(x); // returns a reference to the contents of x
  90. * any_cast<double>(x); // throws bad_any_cast
  91. * any_cast<int*>(&x); // returns a pointer to the contents of x
  92. * any_cast<void*>(&x); // returns a pointer to the contents of x
  93. * any_cast<double*>(&x); // returns NULL
  94. * \endcode
  95. *
  96. * \pre if @c arg is a pointer, @c T must be a pointer type.
  97. * \pre @c Concept must contain @ref typeid_ "typeid_<Tag>".
  98. *
  99. * \throws bad_any_cast if @c arg doesn't contain
  100. * an object of type @c T and we're casting
  101. * to a value or reference.
  102. */
  103. template<class T, class Concept, class Tag>
  104. T any_cast(any<Concept, Tag>& arg)
  105. {
  106. if(::boost::type_erasure::detail::check_any_cast<T>(arg)) {
  107. return *static_cast<
  108. typename ::boost::remove_reference<
  109. typename ::boost::add_const<T>::type
  110. >::type*
  111. >(::boost::type_erasure::detail::get_pointer(arg));
  112. } else {
  113. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast());
  114. }
  115. }
  116. /** \overload */
  117. template<class T, class Concept, class Tag>
  118. T any_cast(const any<Concept, Tag>& arg)
  119. {
  120. if(::boost::type_erasure::detail::check_any_cast<T>(arg)) {
  121. return *static_cast<
  122. typename ::boost::remove_reference<
  123. typename ::boost::add_const<T>::type
  124. >::type*
  125. >(::boost::type_erasure::detail::get_pointer(arg));
  126. } else {
  127. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast());
  128. }
  129. }
  130. /** \overload */
  131. template<class T, class Concept, class Tag>
  132. T any_cast(any<Concept, Tag>* arg)
  133. {
  134. BOOST_MPL_ASSERT((::boost::is_pointer<T>));
  135. if(::boost::type_erasure::detail::check_any_cast<
  136. typename ::boost::remove_pointer<T>::type>(*arg)) {
  137. return static_cast<
  138. typename ::boost::remove_pointer<T>::type*>(
  139. ::boost::type_erasure::detail::get_pointer(*arg));
  140. } else {
  141. return 0;
  142. }
  143. }
  144. /** \overload */
  145. template<class T, class Concept, class Tag>
  146. T any_cast(const any<Concept, Tag>* arg)
  147. {
  148. BOOST_MPL_ASSERT((::boost::is_pointer<T>));
  149. if(::boost::type_erasure::detail::check_any_cast<
  150. typename ::boost::remove_pointer<T>::type>(*arg)) {
  151. return static_cast<
  152. typename ::boost::remove_pointer<T>::type*>(
  153. ::boost::type_erasure::detail::get_pointer(*arg));
  154. } else {
  155. return 0;
  156. }
  157. }
  158. }
  159. }
  160. #endif