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-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_ANY
11#define _LIBCPP_ANY
12
13/*
14 any synopsis
15
16#include <initializer_list>
17#include <typeinfo>
18
19namespace std {
20
21 class bad_any_cast : public bad_cast
22 {
23 public:
24 virtual const char* what() const noexcept;
25 };
26
27 class any
28 {
29 public:
30
31 // 6.3.1 any construct/destruct
32 any() noexcept;
33
34 any(const any& other);
35 any(any&& other) noexcept;
36
37 template <class ValueType>
38 any(ValueType&& value);
39
40 ~any();
41
42 // 6.3.2 any assignments
43 any& operator=(const any& rhs);
44 any& operator=(any&& rhs) noexcept;
45
46 template <class ValueType>
47 any& operator=(ValueType&& rhs);
48
49 // 6.3.3 any modifiers
50 template <class ValueType, class... Args>
51 decay_t<ValueType>& emplace(Args&&... args);
52 template <class ValueType, class U, class... Args>
53 decay_t<ValueType>& emplace(initializer_list<U>, Args&&...);
54 void reset() noexcept;
55 void swap(any& rhs) noexcept;
56
57 // 6.3.4 any observers
58 bool has_value() const noexcept;
59 const type_info& type() const noexcept;
60 };
61
62 // 6.4 Non-member functions
63 void swap(any& x, any& y) noexcept;
64
65 template <class T, class ...Args>
66 any make_any(Args&& ...args);
67 template <class T, class U, class ...Args>
68 any make_any(initializer_list<U>, Args&& ...args);
69
70 template<class ValueType>
71 ValueType any_cast(const any& operand);
72 template<class ValueType>
73 ValueType any_cast(any& operand);
74 template<class ValueType>
75 ValueType any_cast(any&& operand);
76
77 template<class ValueType>
78 const ValueType* any_cast(const any* operand) noexcept;
79 template<class ValueType>
80 ValueType* any_cast(any* operand) noexcept;
81
82} // namespace std
83
84*/
85
86#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
87# include <__cxx03/__config>
88#else
89# include <__config>
90# include <__memory/construct_at.h>
91# include <__type_traits/add_cv_quals.h>
92# include <__type_traits/add_pointer.h>
93# include <__type_traits/conditional.h>
94# include <__type_traits/conjunction.h>
95# include <__type_traits/decay.h>
96# include <__type_traits/enable_if.h>
97# include <__type_traits/is_constructible.h>
98# include <__type_traits/is_function.h>
99# include <__type_traits/is_nothrow_constructible.h>
100# include <__type_traits/is_reference.h>
101# include <__type_traits/is_same.h>
102# include <__type_traits/is_void.h>
103# include <__type_traits/negation.h>
104# include <__type_traits/remove_cv.h>
105# include <__type_traits/remove_cvref.h>
106# include <__type_traits/remove_reference.h>
107# include <__utility/forward.h>
108# include <__utility/in_place.h>
109# include <__utility/move.h>
110# include <__utility/unreachable.h>
111# include <__verbose_abort>
112# include <version>
113
114// standard-mandated includes
115
116// [any.synop]
117# include <initializer_list>
118# include <typeinfo>
119
120# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
121# pragma GCC system_header
122# endif
123
124_LIBCPP_PUSH_MACROS
125# include <__undef_macros>
126
127_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
128_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
129
130class _LIBCPP_EXPORTED_FROM_ABI bad_any_cast : public bad_cast {
131public:
132 const char* what() const _NOEXCEPT override;
133};
134
135_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
136_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
137
138# if _LIBCPP_STD_VER >= 17
139
140_LIBCPP_BEGIN_NAMESPACE_STD
141
142[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_any_cast() {
143# if _LIBCPP_HAS_EXCEPTIONS
144 throw bad_any_cast();
145# else
146 _LIBCPP_VERBOSE_ABORT("bad_any_cast was thrown in -fno-exceptions mode");
147# endif
148}
149
150// Forward declarations
151class any;
152
153template <class _ValueType>
154_LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const*) noexcept;
155
156template <class _ValueType>
157_LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any*) noexcept;
158
159namespace __any_imp {
160inline constexpr size_t __small_buffer_size = 3 * sizeof(void*);
161inline constexpr size_t __small_buffer_alignment = alignof(void*);
162
163template <class _Tp>
164using _IsSmallObject _LIBCPP_NODEBUG =
165 integral_constant<bool,
166 sizeof(_Tp) <= __small_buffer_size && alignof(_Tp) <= __small_buffer_alignment &&
167 is_nothrow_move_constructible_v<_Tp>>;
168
169enum class _Action { _Destroy, _Copy, _Move, _Get, _TypeInfo };
170
171template <class _Tp>
172struct _SmallHandler;
173template <class _Tp>
174struct _LargeHandler;
175
176template <class _Tp>
177struct __unique_typeinfo {
178 static constexpr int __id = 0;
179};
180
181template <class _Tp>
182inline _LIBCPP_HIDE_FROM_ABI constexpr const void* __get_fallback_typeid() {
183 return &__unique_typeinfo<remove_cv_t<remove_reference_t<_Tp>>>::__id;
184}
185
186template <class _Tp>
187inline _LIBCPP_HIDE_FROM_ABI bool __compare_typeid(type_info const* __id, const void* __fallback_id) {
188# if _LIBCPP_HAS_RTTI
189 if (__id && *__id == typeid(_Tp))
190 return true;
191# endif
192 return !__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>();
193}
194
195template <class _Tp>
196using _Handler _LIBCPP_NODEBUG = conditional_t< _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;
197
198} // namespace __any_imp
199
200class any {
201public:
202 // construct/destruct
203 _LIBCPP_HIDE_FROM_ABI constexpr any() noexcept : __h_(nullptr) {}
204
205 _LIBCPP_HIDE_FROM_ABI any(any const& __other) : __h_(nullptr) {
206 if (__other.__h_)
207 __other.__call(a: _Action::_Copy, other: this);
208 }
209
210 _LIBCPP_HIDE_FROM_ABI any(any&& __other) noexcept : __h_(nullptr) {
211 if (__other.__h_)
212 __other.__call(a: _Action::_Move, other: this);
213 }
214
215 template <
216 class _ValueType,
217 class _Tp = decay_t<_ValueType>,
218 enable_if_t<_And<_Not<is_same<_Tp, any>>, _Not<__is_inplace_type<_ValueType>>, is_copy_constructible<_Tp>>::value,
219 int> = 0>
220 _LIBCPP_HIDE_FROM_ABI any(_ValueType&& __value) : __h_(nullptr) {
221 __any_imp::_Handler<_Tp>::__create(*this, std::forward<_ValueType>(__value));
222 }
223
224 template <class _ValueType,
225 class... _Args,
226 class _Tp = decay_t<_ValueType>,
227 enable_if_t<is_constructible_v<_Tp, _Args...> && is_copy_constructible_v<_Tp>, int> = 0>
228 _LIBCPP_HIDE_FROM_ABI explicit any(in_place_type_t<_ValueType>, _Args&&... __args) {
229 __any_imp::_Handler<_Tp>::__create(*this, std::forward<_Args>(__args)...);
230 }
231
232 template <
233 class _ValueType,
234 class _Up,
235 class... _Args,
236 class _Tp = decay_t<_ValueType>,
237 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> && is_copy_constructible_v<_Tp>, int> = 0>
238 _LIBCPP_HIDE_FROM_ABI explicit any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {
239 __any_imp::_Handler<_Tp>::__create(*this, __il, std::forward<_Args>(__args)...);
240 }
241
242 _LIBCPP_HIDE_FROM_ABI ~any() { this->reset(); }
243
244 // assignments
245 _LIBCPP_HIDE_FROM_ABI any& operator=(any const& __rhs) {
246 any(__rhs).swap(rhs&: *this);
247 return *this;
248 }
249
250 _LIBCPP_HIDE_FROM_ABI any& operator=(any&& __rhs) noexcept {
251 any(std::move(__rhs)).swap(rhs&: *this);
252 return *this;
253 }
254
255 template <class _ValueType,
256 class _Tp = decay_t<_ValueType>,
257 enable_if_t<!is_same_v<_Tp, any> && is_copy_constructible_v<_Tp>, int> = 0>
258 _LIBCPP_HIDE_FROM_ABI any& operator=(_ValueType&& __rhs) {
259 any(std::forward<_ValueType>(__rhs)).swap(rhs&: *this);
260 return *this;
261 }
262
263 template <class _ValueType,
264 class... _Args,
265 class _Tp = decay_t<_ValueType>,
266 enable_if_t<is_constructible_v<_Tp, _Args...> && is_copy_constructible_v<_Tp>, int> = 0>
267 _LIBCPP_HIDE_FROM_ABI _Tp& emplace(_Args&&... __args) {
268 reset();
269 return __any_imp::_Handler<_Tp>::__create(*this, std::forward<_Args>(__args)...);
270 }
271
272 template <
273 class _ValueType,
274 class _Up,
275 class... _Args,
276 class _Tp = decay_t<_ValueType>,
277 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> && is_copy_constructible_v<_Tp>, int> = 0>
278 _LIBCPP_HIDE_FROM_ABI _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
279 reset();
280 return __any_imp::_Handler<_Tp>::__create(*this, __il, std::forward<_Args>(__args)...);
281 }
282
283 // 6.3.3 any modifiers
284 _LIBCPP_HIDE_FROM_ABI void reset() noexcept {
285 if (__h_)
286 this->__call(a: _Action::_Destroy);
287 }
288
289 _LIBCPP_HIDE_FROM_ABI void swap(any& __rhs) noexcept {
290 if (this == &__rhs)
291 return;
292 if (__h_ && __rhs.__h_) {
293 any __tmp;
294 __rhs.__call(a: _Action::_Move, other: &__tmp);
295 this->__call(a: _Action::_Move, other: &__rhs);
296 __tmp.__call(a: _Action::_Move, other: this);
297 } else if (__h_) {
298 this->__call(a: _Action::_Move, other: &__rhs);
299 } else if (__rhs.__h_) {
300 __rhs.__call(a: _Action::_Move, other: this);
301 }
302 }
303
304 // 6.3.4 any observers
305 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool has_value() const noexcept { return __h_ != nullptr; }
306
307# if _LIBCPP_HAS_RTTI
308 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const type_info& type() const noexcept {
309 if (__h_) {
310 return *static_cast<type_info const*>(this->__call(a: _Action::_TypeInfo));
311 } else {
312 return typeid(void);
313 }
314 }
315# endif
316
317private:
318 using _Action _LIBCPP_NODEBUG = __any_imp::_Action;
319 using _HandleFuncPtr
320 _LIBCPP_NODEBUG = void* (*)(_Action, any const*, any*, const type_info*, const void* __fallback_info);
321
322 union _Storage {
323 _LIBCPP_HIDE_FROM_ABI constexpr _Storage() : __ptr(nullptr) {}
324 void* __ptr;
325 alignas(__any_imp::__small_buffer_alignment) char __buf[__any_imp::__small_buffer_size];
326 };
327
328 _LIBCPP_HIDE_FROM_ABI void*
329 __call(_Action __a, any* __other = nullptr, type_info const* __info = nullptr, const void* __fallback_info = nullptr)
330 const {
331 return __h_(__a, this, __other, __info, __fallback_info);
332 }
333
334 _LIBCPP_HIDE_FROM_ABI void* __call(
335 _Action __a, any* __other = nullptr, type_info const* __info = nullptr, const void* __fallback_info = nullptr) {
336 return __h_(__a, this, __other, __info, __fallback_info);
337 }
338
339 template <class>
340 friend struct __any_imp::_SmallHandler;
341 template <class>
342 friend struct __any_imp::_LargeHandler;
343
344 template <class _ValueType>
345 friend add_pointer_t<add_const_t<_ValueType>> any_cast(any const*) noexcept;
346
347 template <class _ValueType>
348 friend add_pointer_t<_ValueType> any_cast(any*) noexcept;
349
350 _HandleFuncPtr __h_ = nullptr;
351 _Storage __s_;
352};
353
354namespace __any_imp {
355template <class _Tp>
356struct _SmallHandler {
357 _LIBCPP_HIDE_FROM_ABI static void*
358 __handle(_Action __act, any const* __this, any* __other, type_info const* __info, const void* __fallback_info) {
359 switch (__act) {
360 case _Action::_Destroy:
361 __destroy(this&: const_cast<any&>(*__this));
362 return nullptr;
363 case _Action::_Copy:
364 __copy(this: *__this, dest&: *__other);
365 return nullptr;
366 case _Action::_Move:
367 __move(this&: const_cast<any&>(*__this), dest&: *__other);
368 return nullptr;
369 case _Action::_Get:
370 return __get(this&: const_cast<any&>(*__this), __info, fallback_id: __fallback_info);
371 case _Action::_TypeInfo:
372 return __type_info();
373 }
374 __libcpp_unreachable();
375 }
376
377 template <class... _Args>
378 _LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {
379 auto __ret = std::__construct_at(reinterpret_cast<_Tp*>(&__dest.__s_.__buf), std::forward<_Args>(__args)...);
380 __dest.__h_ = &_SmallHandler::__handle;
381 return *__ret;
382 }
383
384private:
385 _LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {
386 std::__destroy_at(reinterpret_cast<_Tp*>(&__this.__s_.__buf));
387 __this.__h_ = nullptr;
388 }
389
390 _LIBCPP_HIDE_FROM_ABI static void __copy(any const& __this, any& __dest) {
391 _SmallHandler::__create(__dest, *static_cast<_Tp const*>(static_cast<void const*>(&__this.__s_.__buf)));
392 }
393
394 _LIBCPP_HIDE_FROM_ABI static void __move(any& __this, any& __dest) {
395 _SmallHandler::__create(__dest, std::move(*static_cast<_Tp*>(static_cast<void*>(&__this.__s_.__buf))));
396 __destroy(__this);
397 }
398
399 _LIBCPP_HIDE_FROM_ABI static void* __get(any& __this, type_info const* __info, const void* __fallback_id) {
400 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
401 return static_cast<void*>(&__this.__s_.__buf);
402 return nullptr;
403 }
404
405 _LIBCPP_HIDE_FROM_ABI static void* __type_info() {
406# if _LIBCPP_HAS_RTTI
407 return const_cast<void*>(static_cast<void const*>(&typeid(_Tp)));
408# else
409 return nullptr;
410# endif
411 }
412};
413
414template <class _Tp>
415struct _LargeHandler {
416 _LIBCPP_HIDE_FROM_ABI static void*
417 __handle(_Action __act, any const* __this, any* __other, type_info const* __info, void const* __fallback_info) {
418 switch (__act) {
419 case _Action::_Destroy:
420 __destroy(this&: const_cast<any&>(*__this));
421 return nullptr;
422 case _Action::_Copy:
423 __copy(this: *__this, dest&: *__other);
424 return nullptr;
425 case _Action::_Move:
426 __move(this&: const_cast<any&>(*__this), dest&: *__other);
427 return nullptr;
428 case _Action::_Get:
429 return __get(this&: const_cast<any&>(*__this), __info, __fallback_info);
430 case _Action::_TypeInfo:
431 return __type_info();
432 }
433 __libcpp_unreachable();
434 }
435
436 template <class... _Args>
437 _LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {
438 _Tp* __ptr = ::new _Tp(std::forward<_Args>(__args)...);
439 __dest.__s_.__ptr = __ptr;
440 __dest.__h_ = &_LargeHandler::__handle;
441 return *__ptr;
442 }
443
444private:
445 _LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {
446 ::delete static_cast<_Tp*>(__this.__s_.__ptr);
447 __this.__h_ = nullptr;
448 }
449
450 _LIBCPP_HIDE_FROM_ABI static void __copy(any const& __this, any& __dest) {
451 _LargeHandler::__create(__dest, *static_cast<_Tp const*>(__this.__s_.__ptr));
452 }
453
454 _LIBCPP_HIDE_FROM_ABI static void __move(any& __this, any& __dest) {
455 __dest.__s_.__ptr = __this.__s_.__ptr;
456 __dest.__h_ = &_LargeHandler::__handle;
457 __this.__h_ = nullptr;
458 }
459
460 _LIBCPP_HIDE_FROM_ABI static void* __get(any& __this, type_info const* __info, void const* __fallback_info) {
461 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
462 return static_cast<void*>(__this.__s_.__ptr);
463 return nullptr;
464 }
465
466 _LIBCPP_HIDE_FROM_ABI static void* __type_info() {
467# if _LIBCPP_HAS_RTTI
468 return const_cast<void*>(static_cast<void const*>(&typeid(_Tp)));
469# else
470 return nullptr;
471# endif
472 }
473};
474
475} // namespace __any_imp
476
477// 6.4 Non-member functions
478
479inline _LIBCPP_HIDE_FROM_ABI void swap(any& __lhs, any& __rhs) noexcept { __lhs.swap(__rhs); }
480
481template <class _Tp, class... _Args>
482[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(_Args&&... __args) {
483 return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
484}
485
486template <class _Tp, class _Up, class... _Args>
487[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(initializer_list<_Up> __il, _Args&&... __args) {
488 return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
489}
490
491template <class _ValueType>
492[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any const& __v) {
493 using _RawValueType = __remove_cvref_t<_ValueType>;
494 static_assert(is_constructible_v<_ValueType, _RawValueType const&>,
495 "ValueType is required to be a const lvalue reference "
496 "or a CopyConstructible type");
497 auto __tmp = std::any_cast<add_const_t<_RawValueType>>(&__v);
498 if (__tmp == nullptr)
499 std::__throw_bad_any_cast();
500 return static_cast<_ValueType>(*__tmp);
501}
502
503template <class _ValueType>
504[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any& __v) {
505 using _RawValueType = __remove_cvref_t<_ValueType>;
506 static_assert(is_constructible_v<_ValueType, _RawValueType&>,
507 "ValueType is required to be an lvalue reference "
508 "or a CopyConstructible type");
509 auto __tmp = std::any_cast<_RawValueType>(&__v);
510 if (__tmp == nullptr)
511 std::__throw_bad_any_cast();
512 return static_cast<_ValueType>(*__tmp);
513}
514
515template <class _ValueType>
516[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any&& __v) {
517 using _RawValueType = __remove_cvref_t<_ValueType>;
518 static_assert(is_constructible_v<_ValueType, _RawValueType>,
519 "ValueType is required to be an rvalue reference "
520 "or a CopyConstructible type");
521 auto __tmp = std::any_cast<_RawValueType>(&__v);
522 if (__tmp == nullptr)
523 std::__throw_bad_any_cast();
524 return static_cast<_ValueType>(std::move(*__tmp));
525}
526
527template <class _ValueType>
528[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const* __any) noexcept {
529 return std::any_cast<_ValueType>(const_cast<any*>(__any));
530}
531
532template <class _ValueType>
533[[nodiscard]] _LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any* __any) noexcept {
534 using __any_imp::_Action;
535 static_assert(!is_void_v<_ValueType>, "_ValueType may not be void.");
536 static_assert(!is_reference_v<_ValueType>, "_ValueType may not be a reference.");
537 if constexpr (!is_function_v<_ValueType>) {
538 using _ReturnType = add_pointer_t<_ValueType>;
539 if (__any && __any->__h_) {
540 void* __p = __any->__call(
541 _Action::_Get,
542 nullptr,
543# if _LIBCPP_HAS_RTTI
544 &typeid(_ValueType),
545# else
546 nullptr,
547# endif
548 __any_imp::__get_fallback_typeid<_ValueType>());
549 return static_cast<_ReturnType>(__p);
550 }
551 }
552 return nullptr;
553}
554
555_LIBCPP_END_NAMESPACE_STD
556
557# endif // _LIBCPP_STD_VER >= 17
558
559_LIBCPP_POP_MACROS
560
561#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
562
563#endif // _LIBCPP_ANY
564