any.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // See http://www.boost.org/libs/any for Documentation.
  2. #ifndef BOOST_ANY_INCLUDED
  3. #define BOOST_ANY_INCLUDED
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. // what: variant type boost::any
  8. // who: contributed by Kevlin Henney,
  9. // with features contributed and bugs found by
  10. // Antony Polukhin, Ed Brey, Mark Rodgers,
  11. // Peter Dimov, and James Curran
  12. // when: July 2001, April 2013 - May 2013
  13. #include <algorithm>
  14. #include <typeinfo>
  15. #include "boost/config.hpp"
  16. #include <boost/type_traits/remove_reference.hpp>
  17. #include <boost/type_traits/decay.hpp>
  18. #include <boost/type_traits/add_reference.hpp>
  19. #include <boost/type_traits/is_reference.hpp>
  20. #include <boost/type_traits/is_const.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <boost/static_assert.hpp>
  23. #include <boost/utility/enable_if.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. #include <boost/type_traits/is_const.hpp>
  26. // See boost/python/type_id.hpp
  27. // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
  28. # if (defined(__GNUC__) && __GNUC__ >= 3) \
  29. || defined(_AIX) \
  30. || ( defined(__sgi) && defined(__host_mips)) \
  31. || (defined(__hpux) && defined(__HP_aCC)) \
  32. || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
  33. # define BOOST_AUX_ANY_TYPE_ID_NAME
  34. #include <cstring>
  35. # endif
  36. #if defined(_MSC_VER)
  37. #pragma warning(push)
  38. #pragma warning(disable: 4172) // Mistakenly warns: returning address of local variable or temporary
  39. #endif
  40. namespace boost
  41. {
  42. class any
  43. {
  44. public: // structors
  45. any() BOOST_NOEXCEPT
  46. : content(0)
  47. {
  48. }
  49. template<typename ValueType>
  50. any(const ValueType & value)
  51. : content(new holder<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>(value))
  52. {
  53. }
  54. any(const any & other)
  55. : content(other.content ? other.content->clone() : 0)
  56. {
  57. }
  58. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  59. // Move constructor
  60. any(any&& other) BOOST_NOEXCEPT
  61. : content(other.content)
  62. {
  63. other.content = 0;
  64. }
  65. // Perfect forwarding of ValueType
  66. template<typename ValueType>
  67. any(ValueType&& value
  68. , typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&`
  69. , typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&`
  70. : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value)))
  71. {
  72. }
  73. #endif
  74. ~any() BOOST_NOEXCEPT
  75. {
  76. delete content;
  77. }
  78. public: // modifiers
  79. any & swap(any & rhs) BOOST_NOEXCEPT
  80. {
  81. std::swap(content, rhs.content);
  82. return *this;
  83. }
  84. #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
  85. template<typename ValueType>
  86. any & operator=(const ValueType & rhs)
  87. {
  88. any(rhs).swap(*this);
  89. return *this;
  90. }
  91. any & operator=(any rhs)
  92. {
  93. any(rhs).swap(*this);
  94. return *this;
  95. }
  96. #else
  97. any & operator=(const any& rhs)
  98. {
  99. any(rhs).swap(*this);
  100. return *this;
  101. }
  102. // move assignement
  103. any & operator=(any&& rhs) BOOST_NOEXCEPT
  104. {
  105. rhs.swap(*this);
  106. any().swap(rhs);
  107. return *this;
  108. }
  109. // Perfect forwarding of ValueType
  110. template <class ValueType>
  111. any & operator=(ValueType&& rhs)
  112. {
  113. any(static_cast<ValueType&&>(rhs)).swap(*this);
  114. return *this;
  115. }
  116. #endif
  117. public: // queries
  118. bool empty() const BOOST_NOEXCEPT
  119. {
  120. return !content;
  121. }
  122. void clear() BOOST_NOEXCEPT
  123. {
  124. any().swap(*this);
  125. }
  126. const std::type_info & type() const BOOST_NOEXCEPT
  127. {
  128. return content ? content->type() : typeid(void);
  129. }
  130. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  131. private: // types
  132. #else
  133. public: // types (public so any_cast can be non-friend)
  134. #endif
  135. class placeholder
  136. {
  137. public: // structors
  138. virtual ~placeholder()
  139. {
  140. }
  141. public: // queries
  142. virtual const std::type_info & type() const BOOST_NOEXCEPT = 0;
  143. virtual placeholder * clone() const = 0;
  144. };
  145. template<typename ValueType>
  146. class holder : public placeholder
  147. {
  148. public: // structors
  149. holder(const ValueType & value)
  150. : held(value)
  151. {
  152. }
  153. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  154. holder(ValueType&& value)
  155. : held(static_cast< ValueType&& >(value))
  156. {
  157. }
  158. #endif
  159. public: // queries
  160. virtual const std::type_info & type() const BOOST_NOEXCEPT
  161. {
  162. return typeid(ValueType);
  163. }
  164. virtual placeholder * clone() const
  165. {
  166. return new holder(held);
  167. }
  168. public: // representation
  169. ValueType held;
  170. private: // intentionally left unimplemented
  171. holder & operator=(const holder &);
  172. };
  173. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  174. private: // representation
  175. template<typename ValueType>
  176. friend ValueType * any_cast(any *) BOOST_NOEXCEPT;
  177. template<typename ValueType>
  178. friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT;
  179. #else
  180. public: // representation (public so any_cast can be non-friend)
  181. #endif
  182. placeholder * content;
  183. };
  184. inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT
  185. {
  186. lhs.swap(rhs);
  187. }
  188. class BOOST_SYMBOL_VISIBLE bad_any_cast : public std::bad_cast
  189. {
  190. public:
  191. virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
  192. {
  193. return "boost::bad_any_cast: "
  194. "failed conversion using boost::any_cast";
  195. }
  196. };
  197. template<typename ValueType>
  198. ValueType * any_cast(any * operand) BOOST_NOEXCEPT
  199. {
  200. return operand &&
  201. #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
  202. std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
  203. #else
  204. operand->type() == typeid(ValueType)
  205. #endif
  206. ? &static_cast<any::holder<ValueType> *>(operand->content)->held
  207. : 0;
  208. }
  209. template<typename ValueType>
  210. inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT
  211. {
  212. return any_cast<ValueType>(const_cast<any *>(operand));
  213. }
  214. template<typename ValueType>
  215. ValueType any_cast(any & operand)
  216. {
  217. typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
  218. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  219. // If 'nonref' is still reference type, it means the user has not
  220. // specialized 'remove_reference'.
  221. // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
  222. // to generate specialization of remove_reference for your class
  223. // See type traits library documentation for details
  224. BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
  225. #endif
  226. nonref * result = any_cast<nonref>(&operand);
  227. if(!result)
  228. boost::throw_exception(bad_any_cast());
  229. // Attempt to avoid construction of a temporary object in cases when
  230. // `ValueType` is not a reference. Example:
  231. // `static_cast<std::string>(*result);`
  232. // which is equal to `std::string(*result);`
  233. typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
  234. boost::is_reference<ValueType>,
  235. ValueType,
  236. BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type
  237. >::type ref_type;
  238. return static_cast<ref_type>(*result);
  239. }
  240. template<typename ValueType>
  241. inline ValueType any_cast(const any & operand)
  242. {
  243. typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
  244. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  245. // The comment in the above version of 'any_cast' explains when this
  246. // assert is fired and what to do.
  247. BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
  248. #endif
  249. return any_cast<const nonref &>(const_cast<any &>(operand));
  250. }
  251. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  252. template<typename ValueType>
  253. inline ValueType&& any_cast(any&& operand)
  254. {
  255. BOOST_STATIC_ASSERT_MSG(
  256. boost::is_rvalue_reference<ValueType&&>::value
  257. || boost::is_const< typename boost::remove_reference<ValueType>::type >::value,
  258. "boost::any_cast shall not be used for getting nonconst references to temporary objects"
  259. );
  260. return any_cast<ValueType&&>(operand);
  261. }
  262. #endif
  263. // Note: The "unsafe" versions of any_cast are not part of the
  264. // public interface and may be removed at any time. They are
  265. // required where we know what type is stored in the any and can't
  266. // use typeid() comparison, e.g., when our types may travel across
  267. // different shared libraries.
  268. template<typename ValueType>
  269. inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT
  270. {
  271. return &static_cast<any::holder<ValueType> *>(operand->content)->held;
  272. }
  273. template<typename ValueType>
  274. inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT
  275. {
  276. return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
  277. }
  278. }
  279. // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
  280. //
  281. // Distributed under the Boost Software License, Version 1.0. (See
  282. // accompanying file LICENSE_1_0.txt or copy at
  283. // http://www.boost.org/LICENSE_1_0.txt)
  284. #if defined(_MSC_VER)
  285. #pragma warning(pop)
  286. #endif
  287. #endif