1 | // <any> -*- C++ -*- |
2 | |
3 | // Copyright (C) 2014-2018 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 | |
41 | namespace 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 | /** |
442 | * @brief Access the contained object. |
443 | * |
444 | * @tparam _ValueType A const-reference or CopyConstructible type. |
445 | * @param __any The object to access. |
446 | * @return The contained object. |
447 | * @throw bad_any_cast If <code> |
448 | * __any.type() != typeid(remove_reference_t<_ValueType>) |
449 | * </code> |
450 | */ |
451 | template<typename _ValueType> |
452 | inline _ValueType any_cast(const any& __any) |
453 | { |
454 | using _Up = remove_cv_t<remove_reference_t<_ValueType>>; |
455 | static_assert(any::__is_valid_cast<_ValueType>(), |
456 | "Template argument must be a reference or CopyConstructible type" ); |
457 | static_assert(is_constructible_v<_ValueType, const _Up&>, |
458 | "Template argument must be constructible from a const value." ); |
459 | auto __p = any_cast<_Up>(&__any); |
460 | if (__p) |
461 | return static_cast<_ValueType>(*__p); |
462 | __throw_bad_any_cast(); |
463 | } |
464 | |
465 | /** |
466 | * @brief Access the contained object. |
467 | * |
468 | * @tparam _ValueType A reference or CopyConstructible type. |
469 | * @param __any The object to access. |
470 | * @return The contained object. |
471 | * @throw bad_any_cast If <code> |
472 | * __any.type() != typeid(remove_reference_t<_ValueType>) |
473 | * </code> |
474 | * |
475 | * @{ |
476 | */ |
477 | template<typename _ValueType> |
478 | inline _ValueType any_cast(any& __any) |
479 | { |
480 | using _Up = remove_cv_t<remove_reference_t<_ValueType>>; |
481 | static_assert(any::__is_valid_cast<_ValueType>(), |
482 | "Template argument must be a reference or CopyConstructible type" ); |
483 | static_assert(is_constructible_v<_ValueType, _Up&>, |
484 | "Template argument must be constructible from an lvalue." ); |
485 | auto __p = any_cast<_Up>(&__any); |
486 | if (__p) |
487 | return static_cast<_ValueType>(*__p); |
488 | __throw_bad_any_cast(); |
489 | } |
490 | |
491 | template<typename _ValueType> |
492 | inline _ValueType any_cast(any&& __any) |
493 | { |
494 | using _Up = remove_cv_t<remove_reference_t<_ValueType>>; |
495 | static_assert(any::__is_valid_cast<_ValueType>(), |
496 | "Template argument must be a reference or CopyConstructible type" ); |
497 | static_assert(is_constructible_v<_ValueType, _Up>, |
498 | "Template argument must be constructible from an rvalue." ); |
499 | auto __p = any_cast<_Up>(&__any); |
500 | if (__p) |
501 | return static_cast<_ValueType>(std::move(*__p)); |
502 | __throw_bad_any_cast(); |
503 | } |
504 | // @} |
505 | |
506 | template<typename _Tp> |
507 | void* __any_caster(const any* __any) |
508 | { |
509 | if constexpr (is_copy_constructible_v<decay_t<_Tp>>) |
510 | { |
511 | if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage) |
512 | { |
513 | any::_Arg __arg; |
514 | __any->_M_manager(any::_Op_access, __any, &__arg); |
515 | return __arg._M_obj; |
516 | } |
517 | } |
518 | return nullptr; |
519 | } |
520 | |
521 | /** |
522 | * @brief Access the contained object. |
523 | * |
524 | * @tparam _ValueType The type of the contained object. |
525 | * @param __any A pointer to the object to access. |
526 | * @return The address of the contained object if <code> |
527 | * __any != nullptr && __any.type() == typeid(_ValueType) |
528 | * </code>, otherwise a null pointer. |
529 | * |
530 | * @{ |
531 | */ |
532 | template<typename _ValueType> |
533 | inline const _ValueType* any_cast(const any* __any) noexcept |
534 | { |
535 | if (__any) |
536 | return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); |
537 | return nullptr; |
538 | } |
539 | |
540 | template<typename _ValueType> |
541 | inline _ValueType* any_cast(any* __any) noexcept |
542 | { |
543 | if (__any) |
544 | return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); |
545 | return nullptr; |
546 | } |
547 | // @} |
548 | |
549 | template<typename _Tp> |
550 | void |
551 | any::_Manager_internal<_Tp>:: |
552 | _S_manage(_Op __which, const any* __any, _Arg* __arg) |
553 | { |
554 | // The contained object is in _M_storage._M_buffer |
555 | auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer); |
556 | switch (__which) |
557 | { |
558 | case _Op_access: |
559 | __arg->_M_obj = const_cast<_Tp*>(__ptr); |
560 | break; |
561 | case _Op_get_type_info: |
562 | #if __cpp_rtti |
563 | __arg->_M_typeinfo = &typeid(_Tp); |
564 | #endif |
565 | break; |
566 | case _Op_clone: |
567 | ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); |
568 | __arg->_M_any->_M_manager = __any->_M_manager; |
569 | break; |
570 | case _Op_destroy: |
571 | __ptr->~_Tp(); |
572 | break; |
573 | case _Op_xfer: |
574 | ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp |
575 | (std::move(*const_cast<_Tp*>(__ptr))); |
576 | __ptr->~_Tp(); |
577 | __arg->_M_any->_M_manager = __any->_M_manager; |
578 | const_cast<any*>(__any)->_M_manager = nullptr; |
579 | break; |
580 | } |
581 | } |
582 | |
583 | template<typename _Tp> |
584 | void |
585 | any::_Manager_external<_Tp>:: |
586 | _S_manage(_Op __which, const any* __any, _Arg* __arg) |
587 | { |
588 | // The contained object is *_M_storage._M_ptr |
589 | auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr); |
590 | switch (__which) |
591 | { |
592 | case _Op_access: |
593 | __arg->_M_obj = const_cast<_Tp*>(__ptr); |
594 | break; |
595 | case _Op_get_type_info: |
596 | #if __cpp_rtti |
597 | __arg->_M_typeinfo = &typeid(_Tp); |
598 | #endif |
599 | break; |
600 | case _Op_clone: |
601 | __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); |
602 | __arg->_M_any->_M_manager = __any->_M_manager; |
603 | break; |
604 | case _Op_destroy: |
605 | delete __ptr; |
606 | break; |
607 | case _Op_xfer: |
608 | __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; |
609 | __arg->_M_any->_M_manager = __any->_M_manager; |
610 | const_cast<any*>(__any)->_M_manager = nullptr; |
611 | break; |
612 | } |
613 | } |
614 | |
615 | /// @} |
616 | |
617 | _GLIBCXX_END_NAMESPACE_VERSION |
618 | } // namespace std |
619 | |
620 | #endif // C++14 |
621 | |
622 | #endif // _GLIBCXX_ANY |
623 | |