1// <any> -*- C++ -*- 2 3// Copyright (C) 2014-2017 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file include/any 26 * This is a Standard C++ Library header. 27 */ 28 29#ifndef _GLIBCXX_ANY 30#define _GLIBCXX_ANY 1 31 32#pragma GCC system_header 33 34#if __cplusplus >= 201703L 35 36#include <typeinfo> 37#include <new> 38#include <utility> 39#include <type_traits> 40 41namespace std _GLIBCXX_VISIBILITY(default) 42{ 43_GLIBCXX_BEGIN_NAMESPACE_VERSION 44 45 /** 46 * @addtogroup utilities 47 * @{ 48 */ 49 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 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 69#define __cpp_lib_any 201603 70 71 /** 72 * @brief A type-safe container of any type. 73 * 74 * An @c any object's state is either empty or it stores a contained object 75 * of CopyConstructible type. 76 */ 77 class any 78 { 79 // Holds either pointer to a heap object or the contained object itself. 80 union _Storage 81 { 82 constexpr _Storage() : _M_ptr{nullptr} {} 83 84 // Prevent trivial copies of this type, buffer might hold a non-POD. 85 _Storage(const _Storage&) = delete; 86 _Storage& operator=(const _Storage&) = delete; 87 88 void* _M_ptr; 89 aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer; 90 }; 91 92 template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>, 93 bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) 94 && (alignof(_Tp) <= alignof(_Storage))> 95 using _Internal = std::integral_constant<bool, _Safe::value && _Fits>; 96 97 template<typename _Tp> 98 struct _Manager_internal; // uses small-object optimization 99 100 template<typename _Tp> 101 struct _Manager_external; // creates contained object on the heap 102 103 template<typename _Tp> 104 using _Manager = conditional_t<_Internal<_Tp>::value, 105 _Manager_internal<_Tp>, 106 _Manager_external<_Tp>>; 107 108 template<typename _Tp, typename _Decayed = decay_t<_Tp>> 109 using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>; 110 111 /// Emplace with an object created from @p __args as the contained object. 112 template <typename _Tp, typename... _Args, 113 typename _Mgr = _Manager<_Tp>> 114 void __do_emplace(_Args&&... __args) 115 { 116 reset(); 117 _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); 118 _M_manager = &_Mgr::_S_manage; 119 } 120 121 /// Emplace with an object created from @p __il and @p __args as 122 /// the contained object. 123 template <typename _Tp, typename _Up, typename... _Args, 124 typename _Mgr = _Manager<_Tp>> 125 void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) 126 { 127 reset(); 128 _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); 129 _M_manager = &_Mgr::_S_manage; 130 } 131 132 public: 133 // construct/destruct 134 135 /// Default constructor, creates an empty object. 136 constexpr any() noexcept : _M_manager(nullptr) { } 137 138 /// Copy constructor, copies the state of @p __other 139 any(const any& __other) 140 { 141 if (!__other.has_value()) 142 _M_manager = nullptr; 143 else 144 { 145 _Arg __arg; 146 __arg._M_any = this; 147 __other._M_manager(_Op_clone, &__other, &__arg); 148 } 149 } 150 151 /** 152 * @brief Move constructor, transfer the state from @p __other 153 * 154 * @post @c !__other.has_value() (this postcondition is a GNU extension) 155 */ 156 any(any&& __other) noexcept 157 { 158 if (!__other.has_value()) 159 _M_manager = nullptr; 160 else 161 { 162 _Arg __arg; 163 __arg._M_any = this; 164 __other._M_manager(_Op_xfer, &__other, &__arg); 165 } 166 } 167 168 template <typename _Res, typename _Tp, typename... _Args> 169 using __any_constructible = 170 enable_if<__and_<is_copy_constructible<_Tp>, 171 is_constructible<_Tp, _Args...>>::value, 172 _Res>; 173 174 template <typename _Tp, typename... _Args> 175 using __any_constructible_t = 176 typename __any_constructible<bool, _Tp, _Args...>::type; 177 178 /// Construct with a copy of @p __value as the contained object. 179 template <typename _ValueType, typename _Tp = _Decay<_ValueType>, 180 typename _Mgr = _Manager<_Tp>, 181 __any_constructible_t<_Tp, _ValueType&&> = true, 182 enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true> 183 any(_ValueType&& __value) 184 : _M_manager(&_Mgr::_S_manage) 185 { 186 _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value)); 187 } 188 189 /// Construct with a copy of @p __value as the contained object. 190 template <typename _ValueType, typename _Tp = _Decay<_ValueType>, 191 typename _Mgr = _Manager<_Tp>, 192 enable_if_t<__and_<is_copy_constructible<_Tp>, 193 __not_<is_constructible<_Tp, _ValueType&&>>, 194 __not_<__is_in_place_type<_Tp>>>::value, 195 bool> = false> 196 any(_ValueType&& __value) 197 : _M_manager(&_Mgr::_S_manage) 198 { 199 _Mgr::_S_create(_M_storage, __value); 200 } 201 202 /// Construct with an object created from @p __args as the contained object. 203 template <typename _ValueType, typename... _Args, 204 typename _Tp = _Decay<_ValueType>, 205 typename _Mgr = _Manager<_Tp>, 206 __any_constructible_t<_Tp, _Args&&...> = false> 207 explicit 208 any(in_place_type_t<_ValueType>, _Args&&... __args) 209 : _M_manager(&_Mgr::_S_manage) 210 { 211 _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); 212 } 213 214 /// Construct with an object created from @p __il and @p __args as 215 /// the contained object. 216 template <typename _ValueType, typename _Up, typename... _Args, 217 typename _Tp = _Decay<_ValueType>, 218 typename _Mgr = _Manager<_Tp>, 219 __any_constructible_t<_Tp, initializer_list<_Up>, 220 _Args&&...> = false> 221 explicit 222 any(in_place_type_t<_ValueType>, 223 initializer_list<_Up> __il, _Args&&... __args) 224 : _M_manager(&_Mgr::_S_manage) 225 { 226 _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); 227 } 228 229 /// Destructor, calls @c reset() 230 ~any() { reset(); } 231 232 // assignments 233 234 /// Copy the state of another object. 235 any& operator=(const any& __rhs) 236 { 237 *this = any(__rhs); 238 return *this; 239 } 240 241 /** 242 * @brief Move assignment operator 243 * 244 * @post @c !__rhs.has_value() (not guaranteed for other implementations) 245 */ 246 any& operator=(any&& __rhs) noexcept 247 { 248 if (!__rhs.has_value()) 249 reset(); 250 else if (this != &__rhs) 251 { 252 reset(); 253 _Arg __arg; 254 __arg._M_any = this; 255 __rhs._M_manager(_Op_xfer, &__rhs, &__arg); 256 } 257 return *this; 258 } 259 260 /// Store a copy of @p __rhs as the contained object. 261 template<typename _ValueType> 262 enable_if_t<is_copy_constructible<_Decay<_ValueType>>::value, any&> 263 operator=(_ValueType&& __rhs) 264 { 265 *this = any(std::forward<_ValueType>(__rhs)); 266 return *this; 267 } 268 269 /// Emplace with an object created from @p __args as the contained object. 270 template <typename _ValueType, typename... _Args> 271 typename __any_constructible<_Decay<_ValueType>&, 272 _Decay<_ValueType>, _Args&&...>::type 273 emplace(_Args&&... __args) 274 { 275 __do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...); 276 any::_Arg __arg; 277 this->_M_manager(any::_Op_access, this, &__arg); 278 return *static_cast<_Decay<_ValueType>*>(__arg._M_obj); 279 } 280 281 /// Emplace with an object created from @p __il and @p __args as 282 /// the contained object. 283 template <typename _ValueType, typename _Up, typename... _Args> 284 typename __any_constructible<_Decay<_ValueType>&, 285 _Decay<_ValueType>, 286 initializer_list<_Up>, 287 _Args&&...>::type 288 emplace(initializer_list<_Up> __il, _Args&&... __args) 289 { 290 __do_emplace<_Decay<_ValueType>, _Up>(__il, 291 std::forward<_Args>(__args)...); 292 any::_Arg __arg; 293 this->_M_manager(any::_Op_access, this, &__arg); 294 return *static_cast<_Decay<_ValueType>*>(__arg._M_obj); 295 } 296 297 // modifiers 298 299 /// If not empty, destroy the contained object. 300 void reset() noexcept 301 { 302 if (has_value()) 303 { 304 _M_manager(_Op_destroy, this, nullptr); 305 _M_manager = nullptr; 306 } 307 } 308 309 /// Exchange state with another object. 310 void swap(any& __rhs) noexcept 311 { 312 if (!has_value() && !__rhs.has_value()) 313 return; 314 315 if (has_value() && __rhs.has_value()) 316 { 317 if (this == &__rhs) 318 return; 319 320 any __tmp; 321 _Arg __arg; 322 __arg._M_any = &__tmp; 323 __rhs._M_manager(_Op_xfer, &__rhs, &__arg); 324 __arg._M_any = &__rhs; 325 _M_manager(_Op_xfer, this, &__arg); 326 __arg._M_any = this; 327 __tmp._M_manager(_Op_xfer, &__tmp, &__arg); 328 } 329 else 330 { 331 any* __empty = !has_value() ? this : &__rhs; 332 any* __full = !has_value() ? &__rhs : this; 333 _Arg __arg; 334 __arg._M_any = __empty; 335 __full->_M_manager(_Op_xfer, __full, &__arg); 336 } 337 } 338 339 // observers 340 341 /// Reports whether there is a contained object or not. 342 bool has_value() const noexcept { return _M_manager != nullptr; } 343 344#if __cpp_rtti 345 /// The @c typeid of the contained object, or @c typeid(void) if empty. 346 const type_info& type() const noexcept 347 { 348 if (!has_value()) 349 return typeid(void); 350 _Arg __arg; 351 _M_manager(_Op_get_type_info, this, &__arg); 352 return *__arg._M_typeinfo; 353 } 354#endif 355 356 template<typename _Tp> 357 static constexpr bool __is_valid_cast() 358 { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; } 359 360 private: 361 enum _Op { 362 _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer 363 }; 364 365 union _Arg 366 { 367 void* _M_obj; 368 const std::type_info* _M_typeinfo; 369 any* _M_any; 370 }; 371 372 void (*_M_manager)(_Op, const any*, _Arg*); 373 _Storage _M_storage; 374 375 template<typename _Tp> 376 friend void* __any_caster(const any* __any); 377 378 // Manage in-place contained object. 379 template<typename _Tp> 380 struct _Manager_internal 381 { 382 static void 383 _S_manage(_Op __which, const any* __anyp, _Arg* __arg); 384 385 template<typename _Up> 386 static void 387 _S_create(_Storage& __storage, _Up&& __value) 388 { 389 void* __addr = &__storage._M_buffer; 390 ::new (__addr) _Tp(std::forward<_Up>(__value)); 391 } 392 393 template<typename... _Args> 394 static void 395 _S_create(_Storage& __storage, _Args&&... __args) 396 { 397 void* __addr = &__storage._M_buffer; 398 ::new (__addr) _Tp(std::forward<_Args>(__args)...); 399 } 400 }; 401 402 // Manage external contained object. 403 template<typename _Tp> 404 struct _Manager_external 405 { 406 static void 407 _S_manage(_Op __which, const any* __anyp, _Arg* __arg); 408 409 template<typename _Up> 410 static void 411 _S_create(_Storage& __storage, _Up&& __value) 412 { 413 __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); 414 } 415 template<typename... _Args> 416 static void 417 _S_create(_Storage& __storage, _Args&&... __args) 418 { 419 __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); 420 } 421 }; 422 }; 423 424 /// Exchange the states of two @c any objects. 425 inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } 426 427 /// Create an any holding a @c _Tp constructed from @c __args. 428 template <typename _Tp, typename... _Args> 429 any make_any(_Args&&... __args) 430 { 431 return any(in_place_type<_Tp>, std::forward<_Args>(__args)...); 432 } 433 434 /// Create an any holding a @c _Tp constructed from @c __il and @c __args. 435 template <typename _Tp, typename _Up, typename... _Args> 436 any make_any(initializer_list<_Up> __il, _Args&&... __args) 437 { 438 return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); 439 } 440 441 template <typename _Tp> 442 using _AnyCast = remove_cv_t<remove_reference_t<_Tp>>; 443 /** 444 * @brief Access the contained object. 445 * 446 * @tparam _ValueType A const-reference or CopyConstructible type. 447 * @param __any The object to access. 448 * @return The contained object. 449 * @throw bad_any_cast If <code> 450 * __any.type() != typeid(remove_reference_t<_ValueType>) 451 * </code> 452 */ 453 template<typename _ValueType> 454 inline _ValueType any_cast(const any& __any) 455 { 456 static_assert(any::__is_valid_cast<_ValueType>(), 457 "Template argument must be a reference or CopyConstructible type"); 458 auto __p = any_cast<_AnyCast<_ValueType>>(&__any); 459 if (__p) 460 return static_cast<_ValueType>(*__p); 461 __throw_bad_any_cast(); 462 } 463 464 /** 465 * @brief Access the contained object. 466 * 467 * @tparam _ValueType A reference or CopyConstructible type. 468 * @param __any The object to access. 469 * @return The contained object. 470 * @throw bad_any_cast If <code> 471 * __any.type() != typeid(remove_reference_t<_ValueType>) 472 * </code> 473 * 474 * @{ 475 */ 476 template<typename _ValueType> 477 inline _ValueType any_cast(any& __any) 478 { 479 static_assert(any::__is_valid_cast<_ValueType>(), 480 "Template argument must be a reference or CopyConstructible type"); 481 auto __p = any_cast<_AnyCast<_ValueType>>(&__any); 482 if (__p) 483 return static_cast<_ValueType>(*__p); 484 __throw_bad_any_cast(); 485 } 486 487 template<typename _ValueType, 488 typename enable_if<!is_move_constructible<_ValueType>::value 489 || is_lvalue_reference<_ValueType>::value, 490 bool>::type = true> 491 inline _ValueType any_cast(any&& __any) 492 { 493 static_assert(any::__is_valid_cast<_ValueType>(), 494 "Template argument must be a reference or CopyConstructible type"); 495 auto __p = any_cast<_AnyCast<_ValueType>>(&__any); 496 if (__p) 497 return static_cast<_ValueType>(*__p); 498 __throw_bad_any_cast(); 499 } 500 501 template<typename _ValueType, 502 typename enable_if<is_move_constructible<_ValueType>::value 503 && !is_lvalue_reference<_ValueType>::value, 504 bool>::type = false> 505 inline _ValueType any_cast(any&& __any) 506 { 507 static_assert(any::__is_valid_cast<_ValueType>(), 508 "Template argument must be a reference or CopyConstructible type"); 509 auto __p = any_cast<_AnyCast<_ValueType>>(&__any); 510 if (__p) 511 return static_cast<_ValueType>(std::move(*__p)); 512 __throw_bad_any_cast(); 513 } 514 // @} 515 516 template<typename _Tp> 517 void* __any_caster(const any* __any) 518 { 519 if constexpr (is_copy_constructible_v<decay_t<_Tp>>) 520 { 521 if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage) 522 { 523 any::_Arg __arg; 524 __any->_M_manager(any::_Op_access, __any, &__arg); 525 return __arg._M_obj; 526 } 527 } 528 return nullptr; 529 } 530 531 /** 532 * @brief Access the contained object. 533 * 534 * @tparam _ValueType The type of the contained object. 535 * @param __any A pointer to the object to access. 536 * @return The address of the contained object if <code> 537 * __any != nullptr && __any.type() == typeid(_ValueType) 538 * </code>, otherwise a null pointer. 539 * 540 * @{ 541 */ 542 template<typename _ValueType> 543 inline const _ValueType* any_cast(const any* __any) noexcept 544 { 545 if (__any) 546 return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); 547 return nullptr; 548 } 549 550 template<typename _ValueType> 551 inline _ValueType* any_cast(any* __any) noexcept 552 { 553 if (__any) 554 return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); 555 return nullptr; 556 } 557 // @} 558 559 template<typename _Tp> 560 void 561 any::_Manager_internal<_Tp>:: 562 _S_manage(_Op __which, const any* __any, _Arg* __arg) 563 { 564 // The contained object is in _M_storage._M_buffer 565 auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer); 566 switch (__which) 567 { 568 case _Op_access: 569 __arg->_M_obj = const_cast<_Tp*>(__ptr); 570 break; 571 case _Op_get_type_info: 572#if __cpp_rtti 573 __arg->_M_typeinfo = &typeid(_Tp); 574#endif 575 break; 576 case _Op_clone: 577 ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); 578 __arg->_M_any->_M_manager = __any->_M_manager; 579 break; 580 case _Op_destroy: 581 __ptr->~_Tp(); 582 break; 583 case _Op_xfer: 584 ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp 585 (std::move(*const_cast<_Tp*>(__ptr))); 586 __ptr->~_Tp(); 587 __arg->_M_any->_M_manager = __any->_M_manager; 588 const_cast<any*>(__any)->_M_manager = nullptr; 589 break; 590 } 591 } 592 593 template<typename _Tp> 594 void 595 any::_Manager_external<_Tp>:: 596 _S_manage(_Op __which, const any* __any, _Arg* __arg) 597 { 598 // The contained object is *_M_storage._M_ptr 599 auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr); 600 switch (__which) 601 { 602 case _Op_access: 603 __arg->_M_obj = const_cast<_Tp*>(__ptr); 604 break; 605 case _Op_get_type_info: 606#if __cpp_rtti 607 __arg->_M_typeinfo = &typeid(_Tp); 608#endif 609 break; 610 case _Op_clone: 611 __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); 612 __arg->_M_any->_M_manager = __any->_M_manager; 613 break; 614 case _Op_destroy: 615 delete __ptr; 616 break; 617 case _Op_xfer: 618 __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; 619 __arg->_M_any->_M_manager = __any->_M_manager; 620 const_cast<any*>(__any)->_M_manager = nullptr; 621 break; 622 } 623 } 624 625 /// @} 626 627_GLIBCXX_END_NAMESPACE_VERSION 628} // namespace std 629 630#endif // C++14 631 632#endif // _GLIBCXX_ANY 633