You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

568 lines
16KB

  1. // <experimental/any> -*- C++ -*-
  2. // Copyright (C) 2014-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file experimental/any
  21. * This is a TS C++ Library header.
  22. * @ingroup libfund-ts
  23. */
  24. #ifndef _GLIBCXX_EXPERIMENTAL_ANY
  25. #define _GLIBCXX_EXPERIMENTAL_ANY 1
  26. #pragma GCC system_header
  27. #if __cplusplus >= 201402L
  28. #include <typeinfo>
  29. #include <new>
  30. #include <utility>
  31. #include <type_traits>
  32. #include <experimental/bits/lfts_config.h>
  33. namespace std _GLIBCXX_VISIBILITY(default)
  34. {
  35. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  36. namespace experimental
  37. {
  38. inline namespace fundamentals_v1
  39. {
  40. /**
  41. * @defgroup any Type-safe container of any type
  42. * @ingroup libfund-ts
  43. *
  44. * A type-safe container for single values of value types, as
  45. * described in n3804 "Any Library Proposal (Revision 3)".
  46. *
  47. * @{
  48. */
  49. #define __cpp_lib_experimental_any 201411
  50. /**
  51. * @brief Exception class thrown by a failed @c any_cast
  52. * @ingroup exceptions
  53. */
  54. class bad_any_cast : public bad_cast
  55. {
  56. public:
  57. virtual const char* what() const noexcept { return "bad any_cast"; }
  58. };
  59. /// @cond undocumented
  60. [[gnu::noreturn]] inline void __throw_bad_any_cast()
  61. {
  62. #if __cpp_exceptions
  63. throw bad_any_cast{};
  64. #else
  65. __builtin_abort();
  66. #endif
  67. }
  68. /// @endcond
  69. /**
  70. * @brief A type-safe container of any type.
  71. *
  72. * An @c any object's state is either empty or it stores a contained object
  73. * of CopyConstructible type.
  74. */
  75. class any
  76. {
  77. // Holds either pointer to a heap object or the contained object itself.
  78. union _Storage
  79. {
  80. // This constructor intentionally doesn't initialize anything.
  81. _Storage() = default;
  82. // Prevent trivial copies of this type, buffer might hold a non-POD.
  83. _Storage(const _Storage&) = delete;
  84. _Storage& operator=(const _Storage&) = delete;
  85. void* _M_ptr;
  86. aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer;
  87. };
  88. template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>,
  89. bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))
  90. && (alignof(_Tp) <= alignof(_Storage))>
  91. using _Internal = std::integral_constant<bool, _Safe::value && _Fits>;
  92. template<typename _Tp>
  93. struct _Manager_internal; // uses small-object optimization
  94. template<typename _Tp>
  95. struct _Manager_external; // creates contained object on the heap
  96. template<typename _Tp>
  97. using _Manager = conditional_t<_Internal<_Tp>::value,
  98. _Manager_internal<_Tp>,
  99. _Manager_external<_Tp>>;
  100. template<typename _Tp, typename _Decayed = decay_t<_Tp>>
  101. using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
  102. public:
  103. // construct/destruct
  104. /// Default constructor, creates an empty object.
  105. any() noexcept : _M_manager(nullptr) { }
  106. /// Copy constructor, copies the state of @p __other
  107. any(const any& __other)
  108. {
  109. if (__other.empty())
  110. _M_manager = nullptr;
  111. else
  112. {
  113. _Arg __arg;
  114. __arg._M_any = this;
  115. __other._M_manager(_Op_clone, &__other, &__arg);
  116. }
  117. }
  118. /**
  119. * @brief Move constructor, transfer the state from @p __other
  120. *
  121. * @post @c __other.empty() (this postcondition is a GNU extension)
  122. */
  123. any(any&& __other) noexcept
  124. {
  125. if (__other.empty())
  126. _M_manager = nullptr;
  127. else
  128. {
  129. _Arg __arg;
  130. __arg._M_any = this;
  131. __other._M_manager(_Op_xfer, &__other, &__arg);
  132. }
  133. }
  134. /// Construct with a copy of @p __value as the contained object.
  135. template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
  136. typename _Mgr = _Manager<_Tp>,
  137. typename enable_if<is_constructible<_Tp, _ValueType&&>::value,
  138. bool>::type = true>
  139. any(_ValueType&& __value)
  140. : _M_manager(&_Mgr::_S_manage)
  141. {
  142. _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
  143. static_assert(is_copy_constructible<_Tp>::value,
  144. "The contained object must be CopyConstructible");
  145. }
  146. /// Construct with a copy of @p __value as the contained object.
  147. template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
  148. typename _Mgr = _Manager<_Tp>,
  149. typename enable_if<!is_constructible<_Tp, _ValueType&&>::value,
  150. bool>::type = false>
  151. any(_ValueType&& __value)
  152. : _M_manager(&_Mgr::_S_manage)
  153. {
  154. _Mgr::_S_create(_M_storage, __value);
  155. static_assert(is_copy_constructible<_Tp>::value,
  156. "The contained object must be CopyConstructible");
  157. }
  158. /// Destructor, calls @c clear()
  159. ~any() { clear(); }
  160. // assignments
  161. /// Copy the state of another object.
  162. any& operator=(const any& __rhs)
  163. {
  164. *this = any(__rhs);
  165. return *this;
  166. }
  167. /**
  168. * @brief Move assignment operator
  169. *
  170. * @post @c __rhs.empty() (not guaranteed for other implementations)
  171. */
  172. any& operator=(any&& __rhs) noexcept
  173. {
  174. if (__rhs.empty())
  175. clear();
  176. else if (this != &__rhs)
  177. {
  178. clear();
  179. _Arg __arg;
  180. __arg._M_any = this;
  181. __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
  182. }
  183. return *this;
  184. }
  185. /// Store a copy of @p __rhs as the contained object.
  186. template<typename _ValueType>
  187. enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
  188. operator=(_ValueType&& __rhs)
  189. {
  190. *this = any(std::forward<_ValueType>(__rhs));
  191. return *this;
  192. }
  193. // modifiers
  194. /// If not empty, destroy the contained object.
  195. void clear() noexcept
  196. {
  197. if (!empty())
  198. {
  199. _M_manager(_Op_destroy, this, nullptr);
  200. _M_manager = nullptr;
  201. }
  202. }
  203. /// Exchange state with another object.
  204. void swap(any& __rhs) noexcept
  205. {
  206. if (empty() && __rhs.empty())
  207. return;
  208. if (!empty() && !__rhs.empty())
  209. {
  210. if (this == &__rhs)
  211. return;
  212. any __tmp;
  213. _Arg __arg;
  214. __arg._M_any = &__tmp;
  215. __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
  216. __arg._M_any = &__rhs;
  217. _M_manager(_Op_xfer, this, &__arg);
  218. __arg._M_any = this;
  219. __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
  220. }
  221. else
  222. {
  223. any* __empty = empty() ? this : &__rhs;
  224. any* __full = empty() ? &__rhs : this;
  225. _Arg __arg;
  226. __arg._M_any = __empty;
  227. __full->_M_manager(_Op_xfer, __full, &__arg);
  228. }
  229. }
  230. // observers
  231. /// Reports whether there is a contained object or not.
  232. _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_manager == nullptr; }
  233. #if __cpp_rtti
  234. /// The @c typeid of the contained object, or @c typeid(void) if empty.
  235. const type_info& type() const noexcept
  236. {
  237. if (empty())
  238. return typeid(void);
  239. _Arg __arg;
  240. _M_manager(_Op_get_type_info, this, &__arg);
  241. return *__arg._M_typeinfo;
  242. }
  243. #endif
  244. template<typename _Tp>
  245. static constexpr bool __is_valid_cast()
  246. { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
  247. private:
  248. enum _Op {
  249. _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer
  250. };
  251. union _Arg
  252. {
  253. void* _M_obj;
  254. const std::type_info* _M_typeinfo;
  255. any* _M_any;
  256. };
  257. void (*_M_manager)(_Op, const any*, _Arg*);
  258. _Storage _M_storage;
  259. template<typename _Tp>
  260. friend enable_if_t<is_object<_Tp>::value, void*>
  261. __any_caster(const any* __any);
  262. // Manage in-place contained object.
  263. template<typename _Tp>
  264. struct _Manager_internal
  265. {
  266. static void
  267. _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
  268. template<typename _Up>
  269. static void
  270. _S_create(_Storage& __storage, _Up&& __value)
  271. {
  272. void* __addr = &__storage._M_buffer;
  273. ::new (__addr) _Tp(std::forward<_Up>(__value));
  274. }
  275. };
  276. // Manage external contained object.
  277. template<typename _Tp>
  278. struct _Manager_external
  279. {
  280. static void
  281. _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
  282. template<typename _Up>
  283. static void
  284. _S_create(_Storage& __storage, _Up&& __value)
  285. {
  286. __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
  287. }
  288. };
  289. };
  290. /// Exchange the states of two @c any objects.
  291. inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
  292. /**
  293. * @brief Access the contained object.
  294. *
  295. * @tparam _ValueType A const-reference or CopyConstructible type.
  296. * @param __any The object to access.
  297. * @return The contained object.
  298. * @throw bad_any_cast If <code>
  299. * __any.type() != typeid(remove_reference_t<_ValueType>)
  300. * </code>
  301. */
  302. template<typename _ValueType>
  303. inline _ValueType any_cast(const any& __any)
  304. {
  305. static_assert(any::__is_valid_cast<_ValueType>(),
  306. "Template argument must be a reference or CopyConstructible type");
  307. auto __p = any_cast<add_const_t<remove_reference_t<_ValueType>>>(&__any);
  308. if (__p)
  309. return *__p;
  310. __throw_bad_any_cast();
  311. }
  312. /**
  313. * @brief Access the contained object.
  314. *
  315. * @tparam _ValueType A reference or CopyConstructible type.
  316. * @param __any The object to access.
  317. * @return The contained object.
  318. * @throw bad_any_cast If <code>
  319. * __any.type() != typeid(remove_reference_t<_ValueType>)
  320. * </code>
  321. *
  322. * @{
  323. */
  324. template<typename _ValueType>
  325. inline _ValueType any_cast(any& __any)
  326. {
  327. static_assert(any::__is_valid_cast<_ValueType>(),
  328. "Template argument must be a reference or CopyConstructible type");
  329. auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
  330. if (__p)
  331. return *__p;
  332. __throw_bad_any_cast();
  333. }
  334. template<typename _ValueType,
  335. typename enable_if<!is_move_constructible<_ValueType>::value
  336. || is_lvalue_reference<_ValueType>::value,
  337. bool>::type = true>
  338. inline _ValueType any_cast(any&& __any)
  339. {
  340. static_assert(any::__is_valid_cast<_ValueType>(),
  341. "Template argument must be a reference or CopyConstructible type");
  342. auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
  343. if (__p)
  344. return *__p;
  345. __throw_bad_any_cast();
  346. }
  347. template<typename _ValueType,
  348. typename enable_if<is_move_constructible<_ValueType>::value
  349. && !is_lvalue_reference<_ValueType>::value,
  350. bool>::type = false>
  351. inline _ValueType any_cast(any&& __any)
  352. {
  353. static_assert(any::__is_valid_cast<_ValueType>(),
  354. "Template argument must be a reference or CopyConstructible type");
  355. auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
  356. if (__p)
  357. return std::move(*__p);
  358. __throw_bad_any_cast();
  359. }
  360. // @}
  361. /// @cond undocumented
  362. template<typename _Tp>
  363. enable_if_t<is_object<_Tp>::value, void*>
  364. __any_caster(const any* __any)
  365. {
  366. // any_cast<T> returns non-null if __any->type() == typeid(T) and
  367. // typeid(T) ignores cv-qualifiers so remove them:
  368. using _Up = remove_cv_t<_Tp>;
  369. // The contained value has a decayed type, so if decay_t<U> is not U,
  370. // then it's not possible to have a contained value of type U.
  371. using __does_not_decay = is_same<decay_t<_Up>, _Up>;
  372. // Only copy constructible types can be used for contained values.
  373. using __is_copyable = is_copy_constructible<_Up>;
  374. // If the type _Tp could never be stored in an any we don't want to
  375. // instantiate _Manager<_Tp>, so use _Manager<any::_Op> instead, which
  376. // is explicitly specialized and has a no-op _S_manage function.
  377. using _Vp = conditional_t<__and_<__does_not_decay, __is_copyable>::value,
  378. _Up, any::_Op>;
  379. // First try comparing function addresses, which works without RTTI
  380. if (__any->_M_manager == &any::_Manager<_Vp>::_S_manage
  381. #if __cpp_rtti
  382. || __any->type() == typeid(_Tp)
  383. #endif
  384. )
  385. {
  386. any::_Arg __arg;
  387. __any->_M_manager(any::_Op_access, __any, &__arg);
  388. return __arg._M_obj;
  389. }
  390. return nullptr;
  391. }
  392. // This overload exists so that std::any_cast<void(*)()>(a) is well-formed.
  393. template<typename _Tp>
  394. enable_if_t<!is_object<_Tp>::value, _Tp*>
  395. __any_caster(const any*) noexcept
  396. { return nullptr; }
  397. /// @endcond
  398. /**
  399. * @brief Access the contained object.
  400. *
  401. * @tparam _ValueType The type of the contained object.
  402. * @param __any A pointer to the object to access.
  403. * @return The address of the contained object if <code>
  404. * __any != nullptr && __any.type() == typeid(_ValueType)
  405. * </code>, otherwise a null pointer.
  406. *
  407. * @{
  408. */
  409. template<typename _ValueType>
  410. inline const _ValueType* any_cast(const any* __any) noexcept
  411. {
  412. if (__any)
  413. return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
  414. return nullptr;
  415. }
  416. template<typename _ValueType>
  417. inline _ValueType* any_cast(any* __any) noexcept
  418. {
  419. if (__any)
  420. return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
  421. return nullptr;
  422. }
  423. // @}
  424. template<typename _Tp>
  425. void
  426. any::_Manager_internal<_Tp>::
  427. _S_manage(_Op __which, const any* __any, _Arg* __arg)
  428. {
  429. // The contained object is in _M_storage._M_buffer
  430. auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
  431. switch (__which)
  432. {
  433. case _Op_access:
  434. __arg->_M_obj = const_cast<_Tp*>(__ptr);
  435. break;
  436. case _Op_get_type_info:
  437. #if __cpp_rtti
  438. __arg->_M_typeinfo = &typeid(_Tp);
  439. #endif
  440. break;
  441. case _Op_clone:
  442. ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
  443. __arg->_M_any->_M_manager = __any->_M_manager;
  444. break;
  445. case _Op_destroy:
  446. __ptr->~_Tp();
  447. break;
  448. case _Op_xfer:
  449. ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
  450. (std::move(*const_cast<_Tp*>(__ptr)));
  451. __ptr->~_Tp();
  452. __arg->_M_any->_M_manager = __any->_M_manager;
  453. const_cast<any*>(__any)->_M_manager = nullptr;
  454. break;
  455. }
  456. }
  457. template<typename _Tp>
  458. void
  459. any::_Manager_external<_Tp>::
  460. _S_manage(_Op __which, const any* __any, _Arg* __arg)
  461. {
  462. // The contained object is *_M_storage._M_ptr
  463. auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
  464. switch (__which)
  465. {
  466. case _Op_access:
  467. __arg->_M_obj = const_cast<_Tp*>(__ptr);
  468. break;
  469. case _Op_get_type_info:
  470. #if __cpp_rtti
  471. __arg->_M_typeinfo = &typeid(_Tp);
  472. #endif
  473. break;
  474. case _Op_clone:
  475. __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
  476. __arg->_M_any->_M_manager = __any->_M_manager;
  477. break;
  478. case _Op_destroy:
  479. delete __ptr;
  480. break;
  481. case _Op_xfer:
  482. __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr;
  483. __arg->_M_any->_M_manager = __any->_M_manager;
  484. const_cast<any*>(__any)->_M_manager = nullptr;
  485. break;
  486. }
  487. }
  488. // Dummy specialization used by __any_caster.
  489. template<>
  490. struct any::_Manager_internal<any::_Op>
  491. {
  492. static void
  493. _S_manage(_Op, const any*, _Arg*) { }
  494. };
  495. // @} group any
  496. } // namespace fundamentals_v1
  497. } // namespace experimental
  498. _GLIBCXX_END_NAMESPACE_VERSION
  499. } // namespace std
  500. #endif // C++14
  501. #endif // _GLIBCXX_EXPERIMENTAL_ANY