607 lines · plain
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP_ANY11#define _LIBCPP_ANY12 13/*14 any synopsis15 16namespace std {17 18 class bad_any_cast : public bad_cast19 {20 public:21 virtual const char* what() const noexcept;22 };23 24 class any25 {26 public:27 28 // 6.3.1 any construct/destruct29 any() noexcept;30 31 any(const any& other);32 any(any&& other) noexcept;33 34 template <class ValueType>35 any(ValueType&& value);36 37 ~any();38 39 // 6.3.2 any assignments40 any& operator=(const any& rhs);41 any& operator=(any&& rhs) noexcept;42 43 template <class ValueType>44 any& operator=(ValueType&& rhs);45 46 // 6.3.3 any modifiers47 template <class ValueType, class... Args>48 decay_t<ValueType>& emplace(Args&&... args);49 template <class ValueType, class U, class... Args>50 decay_t<ValueType>& emplace(initializer_list<U>, Args&&...);51 void reset() noexcept;52 void swap(any& rhs) noexcept;53 54 // 6.3.4 any observers55 bool has_value() const noexcept;56 const type_info& type() const noexcept;57 };58 59 // 6.4 Non-member functions60 void swap(any& x, any& y) noexcept;61 62 template <class T, class ...Args>63 any make_any(Args&& ...args);64 template <class T, class U, class ...Args>65 any make_any(initializer_list<U>, Args&& ...args);66 67 template<class ValueType>68 ValueType any_cast(const any& operand);69 template<class ValueType>70 ValueType any_cast(any& operand);71 template<class ValueType>72 ValueType any_cast(any&& operand);73 74 template<class ValueType>75 const ValueType* any_cast(const any* operand) noexcept;76 template<class ValueType>77 ValueType* any_cast(any* operand) noexcept;78 79} // namespace std80 81*/82 83#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)84# include <__cxx03/__config>85#else86# include <__config>87# include <__memory/construct_at.h>88# include <__new/allocate.h>89# include <__type_traits/add_cv_quals.h>90# include <__type_traits/add_pointer.h>91# include <__type_traits/conditional.h>92# include <__type_traits/decay.h>93# include <__type_traits/enable_if.h>94# include <__type_traits/is_constructible.h>95# include <__type_traits/is_function.h>96# include <__type_traits/is_nothrow_constructible.h>97# include <__type_traits/is_reference.h>98# include <__type_traits/is_same.h>99# include <__type_traits/is_void.h>100# include <__type_traits/remove_cv.h>101# include <__type_traits/remove_cvref.h>102# include <__type_traits/remove_reference.h>103# include <__utility/exception_guard.h>104# include <__utility/forward.h>105# include <__utility/in_place.h>106# include <__utility/move.h>107# include <__utility/unreachable.h>108# include <__verbose_abort>109# include <initializer_list>110# include <typeinfo>111# include <version>112 113# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)114# pragma GCC system_header115# endif116 117_LIBCPP_PUSH_MACROS118# include <__undef_macros>119 120_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD121class _LIBCPP_EXPORTED_FROM_ABI bad_any_cast : public bad_cast {122public:123 const char* what() const _NOEXCEPT override;124};125_LIBCPP_END_UNVERSIONED_NAMESPACE_STD126 127_LIBCPP_BEGIN_NAMESPACE_STD128 129# if _LIBCPP_STD_VER >= 17130 131[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_any_cast() {132# if _LIBCPP_HAS_EXCEPTIONS133 throw bad_any_cast();134# else135 _LIBCPP_VERBOSE_ABORT("bad_any_cast was thrown in -fno-exceptions mode");136# endif137}138 139// Forward declarations140class any;141 142template <class _ValueType>143_LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const*) _NOEXCEPT;144 145template <class _ValueType>146_LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any*) _NOEXCEPT;147 148namespace __any_imp {149inline constexpr size_t __small_buffer_size = 3 * sizeof(void*);150inline constexpr size_t __small_buffer_alignment = alignof(void*);151 152template <class _Tp>153using _IsSmallObject _LIBCPP_NODEBUG =154 integral_constant<bool,155 sizeof(_Tp) <= __small_buffer_size && alignof(_Tp) <= __small_buffer_alignment &&156 is_nothrow_move_constructible<_Tp>::value >;157 158enum class _Action { _Destroy, _Copy, _Move, _Get, _TypeInfo };159 160template <class _Tp>161struct _SmallHandler;162template <class _Tp>163struct _LargeHandler;164 165template <class _Tp>166struct __unique_typeinfo {167 static constexpr int __id = 0;168};169 170template <class _Tp>171inline _LIBCPP_HIDE_FROM_ABI constexpr const void* __get_fallback_typeid() {172 return &__unique_typeinfo<remove_cv_t<remove_reference_t<_Tp>>>::__id;173}174 175template <class _Tp>176inline _LIBCPP_HIDE_FROM_ABI bool __compare_typeid(type_info const* __id, const void* __fallback_id) {177# if _LIBCPP_HAS_RTTI178 if (__id && *__id == typeid(_Tp))179 return true;180# endif181 return !__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>();182}183 184template <class _Tp>185using _Handler _LIBCPP_NODEBUG = conditional_t< _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;186 187} // namespace __any_imp188 189class any {190public:191 // construct/destruct192 _LIBCPP_HIDE_FROM_ABI constexpr any() _NOEXCEPT : __h_(nullptr) {}193 194 _LIBCPP_HIDE_FROM_ABI any(any const& __other) : __h_(nullptr) {195 if (__other.__h_)196 __other.__call(_Action::_Copy, this);197 }198 199 _LIBCPP_HIDE_FROM_ABI any(any&& __other) _NOEXCEPT : __h_(nullptr) {200 if (__other.__h_)201 __other.__call(_Action::_Move, this);202 }203 204 template < class _ValueType,205 class _Tp = decay_t<_ValueType>,206 class = enable_if_t< !is_same<_Tp, any>::value && !__is_inplace_type<_ValueType>::value &&207 is_copy_constructible<_Tp>::value> >208 _LIBCPP_HIDE_FROM_ABI any(_ValueType&& __value);209 210 template <class _ValueType,211 class... _Args,212 class _Tp = decay_t<_ValueType>,213 class = enable_if_t< is_constructible<_Tp, _Args...>::value && is_copy_constructible<_Tp>::value > >214 _LIBCPP_HIDE_FROM_ABI explicit any(in_place_type_t<_ValueType>, _Args&&... __args);215 216 template <class _ValueType,217 class _Up,218 class... _Args,219 class _Tp = decay_t<_ValueType>,220 class = enable_if_t< is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&221 is_copy_constructible<_Tp>::value> >222 _LIBCPP_HIDE_FROM_ABI explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args);223 224 _LIBCPP_HIDE_FROM_ABI ~any() { this->reset(); }225 226 // assignments227 _LIBCPP_HIDE_FROM_ABI any& operator=(any const& __rhs) {228 any(__rhs).swap(*this);229 return *this;230 }231 232 _LIBCPP_HIDE_FROM_ABI any& operator=(any&& __rhs) _NOEXCEPT {233 any(std::move(__rhs)).swap(*this);234 return *this;235 }236 237 template < class _ValueType,238 class _Tp = decay_t<_ValueType>,239 class = enable_if_t< !is_same<_Tp, any>::value && is_copy_constructible<_Tp>::value> >240 _LIBCPP_HIDE_FROM_ABI any& operator=(_ValueType&& __rhs);241 242 template <class _ValueType,243 class... _Args,244 class _Tp = decay_t<_ValueType>,245 class = enable_if_t< is_constructible<_Tp, _Args...>::value && is_copy_constructible<_Tp>::value> >246 _LIBCPP_HIDE_FROM_ABI _Tp& emplace(_Args&&...);247 248 template <class _ValueType,249 class _Up,250 class... _Args,251 class _Tp = decay_t<_ValueType>,252 class = enable_if_t< is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&253 is_copy_constructible<_Tp>::value> >254 _LIBCPP_HIDE_FROM_ABI _Tp& emplace(initializer_list<_Up>, _Args&&...);255 256 // 6.3.3 any modifiers257 _LIBCPP_HIDE_FROM_ABI void reset() _NOEXCEPT {258 if (__h_)259 this->__call(_Action::_Destroy);260 }261 262 _LIBCPP_HIDE_FROM_ABI void swap(any& __rhs) _NOEXCEPT;263 264 // 6.3.4 any observers265 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool has_value() const _NOEXCEPT { return __h_ != nullptr; }266 267# if _LIBCPP_HAS_RTTI268 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const type_info& type() const _NOEXCEPT {269 if (__h_) {270 return *static_cast<type_info const*>(this->__call(_Action::_TypeInfo));271 } else {272 return typeid(void);273 }274 }275# endif276 277private:278 using _Action _LIBCPP_NODEBUG = __any_imp::_Action;279 using _HandleFuncPtr280 _LIBCPP_NODEBUG = void* (*)(_Action, any const*, any*, const type_info*, const void* __fallback_info);281 282 union _Storage {283 _LIBCPP_HIDE_FROM_ABI constexpr _Storage() : __ptr(nullptr) {}284 void* __ptr;285 alignas(__any_imp::__small_buffer_alignment) char __buf[__any_imp::__small_buffer_size];286 };287 288 _LIBCPP_HIDE_FROM_ABI void*289 __call(_Action __a, any* __other = nullptr, type_info const* __info = nullptr, const void* __fallback_info = nullptr)290 const {291 return __h_(__a, this, __other, __info, __fallback_info);292 }293 294 _LIBCPP_HIDE_FROM_ABI void* __call(295 _Action __a, any* __other = nullptr, type_info const* __info = nullptr, const void* __fallback_info = nullptr) {296 return __h_(__a, this, __other, __info, __fallback_info);297 }298 299 template <class>300 friend struct __any_imp::_SmallHandler;301 template <class>302 friend struct __any_imp::_LargeHandler;303 304 template <class _ValueType>305 friend add_pointer_t<add_const_t<_ValueType>> any_cast(any const*) _NOEXCEPT;306 307 template <class _ValueType>308 friend add_pointer_t<_ValueType> any_cast(any*) _NOEXCEPT;309 310 _HandleFuncPtr __h_ = nullptr;311 _Storage __s_;312};313 314namespace __any_imp {315template <class _Tp>316struct _SmallHandler {317 _LIBCPP_HIDE_FROM_ABI static void*318 __handle(_Action __act, any const* __this, any* __other, type_info const* __info, const void* __fallback_info) {319 switch (__act) {320 case _Action::_Destroy:321 __destroy(const_cast<any&>(*__this));322 return nullptr;323 case _Action::_Copy:324 __copy(*__this, *__other);325 return nullptr;326 case _Action::_Move:327 __move(const_cast<any&>(*__this), *__other);328 return nullptr;329 case _Action::_Get:330 return __get(const_cast<any&>(*__this), __info, __fallback_info);331 case _Action::_TypeInfo:332 return __type_info();333 }334 __libcpp_unreachable();335 }336 337 template <class... _Args>338 _LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {339 auto __ret = std::__construct_at(reinterpret_cast<_Tp*>(&__dest.__s_.__buf), std::forward<_Args>(__args)...);340 __dest.__h_ = &_SmallHandler::__handle;341 return *__ret;342 }343 344private:345 _LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {346 std::__destroy_at(reinterpret_cast<_Tp*>(&__this.__s_.__buf));347 __this.__h_ = nullptr;348 }349 350 _LIBCPP_HIDE_FROM_ABI static void __copy(any const& __this, any& __dest) {351 _SmallHandler::__create(__dest, *static_cast<_Tp const*>(static_cast<void const*>(&__this.__s_.__buf)));352 }353 354 _LIBCPP_HIDE_FROM_ABI static void __move(any& __this, any& __dest) {355 _SmallHandler::__create(__dest, std::move(*static_cast<_Tp*>(static_cast<void*>(&__this.__s_.__buf))));356 __destroy(__this);357 }358 359 _LIBCPP_HIDE_FROM_ABI static void* __get(any& __this, type_info const* __info, const void* __fallback_id) {360 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))361 return static_cast<void*>(&__this.__s_.__buf);362 return nullptr;363 }364 365 _LIBCPP_HIDE_FROM_ABI static void* __type_info() {366# if _LIBCPP_HAS_RTTI367 return const_cast<void*>(static_cast<void const*>(&typeid(_Tp)));368# else369 return nullptr;370# endif371 }372};373 374template <class _Tp>375struct _LargeHandler {376 _LIBCPP_HIDE_FROM_ABI static void*377 __handle(_Action __act, any const* __this, any* __other, type_info const* __info, void const* __fallback_info) {378 switch (__act) {379 case _Action::_Destroy:380 __destroy(const_cast<any&>(*__this));381 return nullptr;382 case _Action::_Copy:383 __copy(*__this, *__other);384 return nullptr;385 case _Action::_Move:386 __move(const_cast<any&>(*__this), *__other);387 return nullptr;388 case _Action::_Get:389 return __get(const_cast<any&>(*__this), __info, __fallback_info);390 case _Action::_TypeInfo:391 return __type_info();392 }393 __libcpp_unreachable();394 }395 396 template <class... _Args>397 _LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {398 _Tp* __ptr = static_cast<_Tp*>(std::__libcpp_allocate<_Tp>(__element_count(1)));399 std::__exception_guard __guard([&] { std::__libcpp_deallocate<_Tp>(__ptr, __element_count(1)); });400 std::__construct_at(__ptr, std::forward<_Args>(__args)...);401 __guard.__complete();402 __dest.__s_.__ptr = __ptr;403 __dest.__h_ = &_LargeHandler::__handle;404 return *__ptr;405 }406 407private:408 _LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {409 _Tp* __p = static_cast<_Tp*>(__this.__s_.__ptr);410 std::__destroy_at(__p);411 std::__libcpp_deallocate<_Tp>(__p, __element_count(1));412 __this.__h_ = nullptr;413 }414 415 _LIBCPP_HIDE_FROM_ABI static void __copy(any const& __this, any& __dest) {416 _LargeHandler::__create(__dest, *static_cast<_Tp const*>(__this.__s_.__ptr));417 }418 419 _LIBCPP_HIDE_FROM_ABI static void __move(any& __this, any& __dest) {420 __dest.__s_.__ptr = __this.__s_.__ptr;421 __dest.__h_ = &_LargeHandler::__handle;422 __this.__h_ = nullptr;423 }424 425 _LIBCPP_HIDE_FROM_ABI static void* __get(any& __this, type_info const* __info, void const* __fallback_info) {426 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))427 return static_cast<void*>(__this.__s_.__ptr);428 return nullptr;429 }430 431 _LIBCPP_HIDE_FROM_ABI static void* __type_info() {432# if _LIBCPP_HAS_RTTI433 return const_cast<void*>(static_cast<void const*>(&typeid(_Tp)));434# else435 return nullptr;436# endif437 }438};439 440} // namespace __any_imp441 442template <class _ValueType, class _Tp, class>443any::any(_ValueType&& __v) : __h_(nullptr) {444 __any_imp::_Handler<_Tp>::__create(*this, std::forward<_ValueType>(__v));445}446 447template <class _ValueType, class... _Args, class _Tp, class>448any::any(in_place_type_t<_ValueType>, _Args&&... __args) {449 __any_imp::_Handler<_Tp>::__create(*this, std::forward<_Args>(__args)...);450}451 452template <class _ValueType, class _Up, class... _Args, class _Tp, class>453any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {454 __any_imp::_Handler<_Tp>::__create(*this, __il, std::forward<_Args>(__args)...);455}456 457template <class _ValueType, class, class>458inline _LIBCPP_HIDE_FROM_ABI any& any::operator=(_ValueType&& __v) {459 any(std::forward<_ValueType>(__v)).swap(*this);460 return *this;461}462 463template <class _ValueType, class... _Args, class _Tp, class>464inline _LIBCPP_HIDE_FROM_ABI _Tp& any::emplace(_Args&&... __args) {465 reset();466 return __any_imp::_Handler<_Tp>::__create(*this, std::forward<_Args>(__args)...);467}468 469template <class _ValueType, class _Up, class... _Args, class _Tp, class>470inline _LIBCPP_HIDE_FROM_ABI _Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) {471 reset();472 return __any_imp::_Handler<_Tp>::__create(*this, __il, std::forward<_Args>(__args)...);473}474 475inline _LIBCPP_HIDE_FROM_ABI void any::swap(any& __rhs) _NOEXCEPT {476 if (this == &__rhs)477 return;478 if (__h_ && __rhs.__h_) {479 any __tmp;480 __rhs.__call(_Action::_Move, &__tmp);481 this->__call(_Action::_Move, &__rhs);482 __tmp.__call(_Action::_Move, this);483 } else if (__h_) {484 this->__call(_Action::_Move, &__rhs);485 } else if (__rhs.__h_) {486 __rhs.__call(_Action::_Move, this);487 }488}489 490// 6.4 Non-member functions491 492inline _LIBCPP_HIDE_FROM_ABI void swap(any& __lhs, any& __rhs) _NOEXCEPT { __lhs.swap(__rhs); }493 494template <class _Tp, class... _Args>495[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(_Args&&... __args) {496 return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);497}498 499template <class _Tp, class _Up, class... _Args>500[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(initializer_list<_Up> __il, _Args&&... __args) {501 return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);502}503 504template <class _ValueType>505[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any const& __v) {506 using _RawValueType = __remove_cvref_t<_ValueType>;507 static_assert(is_constructible<_ValueType, _RawValueType const&>::value,508 "ValueType is required to be a const lvalue reference "509 "or a CopyConstructible type");510 auto __tmp = std::any_cast<add_const_t<_RawValueType>>(&__v);511 if (__tmp == nullptr)512 std::__throw_bad_any_cast();513 return static_cast<_ValueType>(*__tmp);514}515 516template <class _ValueType>517[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any& __v) {518 using _RawValueType = __remove_cvref_t<_ValueType>;519 static_assert(is_constructible<_ValueType, _RawValueType&>::value,520 "ValueType is required to be an lvalue reference "521 "or a CopyConstructible type");522 auto __tmp = std::any_cast<_RawValueType>(&__v);523 if (__tmp == nullptr)524 std::__throw_bad_any_cast();525 return static_cast<_ValueType>(*__tmp);526}527 528template <class _ValueType>529[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any&& __v) {530 using _RawValueType = __remove_cvref_t<_ValueType>;531 static_assert(is_constructible<_ValueType, _RawValueType>::value,532 "ValueType is required to be an rvalue reference "533 "or a CopyConstructible type");534 auto __tmp = std::any_cast<_RawValueType>(&__v);535 if (__tmp == nullptr)536 std::__throw_bad_any_cast();537 return static_cast<_ValueType>(std::move(*__tmp));538}539 540template <class _ValueType>541[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const* __any) _NOEXCEPT {542 static_assert(!is_void_v<_ValueType>, "_ValueType may not be void.");543 static_assert(!is_reference<_ValueType>::value, "_ValueType may not be a reference.");544 return std::any_cast<_ValueType>(const_cast<any*>(__any));545}546 547template <class _RetType>548inline _LIBCPP_HIDE_FROM_ABI _RetType __pointer_or_func_cast(void* __p, /*IsFunction*/ false_type) noexcept {549 return static_cast<_RetType>(__p);550}551 552template <class _RetType>553inline _LIBCPP_HIDE_FROM_ABI _RetType __pointer_or_func_cast(void*, /*IsFunction*/ true_type) noexcept {554 return nullptr;555}556 557template <class _ValueType>558[[nodiscard]] _LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any* __any) _NOEXCEPT {559 using __any_imp::_Action;560 static_assert(!is_void_v<_ValueType>, "_ValueType may not be void.");561 static_assert(!is_reference<_ValueType>::value, "_ValueType may not be a reference.");562 typedef add_pointer_t<_ValueType> _ReturnType;563 if (__any && __any->__h_) {564 void* __p = __any->__call(565 _Action::_Get,566 nullptr,567# if _LIBCPP_HAS_RTTI568 &typeid(_ValueType),569# else570 nullptr,571# endif572 __any_imp::__get_fallback_typeid<_ValueType>());573 return std::__pointer_or_func_cast<_ReturnType>(__p, is_function<_ValueType>{});574 }575 return nullptr;576}577 578# endif // _LIBCPP_STD_VER >= 17579 580_LIBCPP_END_NAMESPACE_STD581 582_LIBCPP_POP_MACROS583 584# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17585# include <chrono>586# endif587 588# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20589# include <atomic>590# include <concepts>591# include <cstdlib>592# include <iosfwd>593# include <iterator>594# include <memory>595# include <stdexcept>596# include <type_traits>597# include <variant>598# endif599 600# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23601# include <cstring>602# include <limits>603# endif604#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)605 606#endif // _LIBCPP_ANY607