1 | // <any> -*- C++ -*- |
2 | |
3 | // Copyright (C) 2014-2022 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 <initializer_list> |
37 | #include <typeinfo> |
38 | #include <new> |
39 | #include <type_traits> |
40 | #include <bits/utility.h> // in_place_type_t |
41 | |
42 | namespace std _GLIBCXX_VISIBILITY(default) |
43 | { |
44 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
45 | |
46 | /** |
47 | * @addtogroup utilities |
48 | * @{ |
49 | */ |
50 | |
51 | /** |
52 | * @brief Exception class thrown by a failed @c any_cast |
53 | * @ingroup exceptions |
54 | */ |
55 | class bad_any_cast : public bad_cast |
56 | { |
57 | public: |
58 | virtual const char* what() const noexcept { return "bad any_cast" ; } |
59 | }; |
60 | |
61 | [[gnu::noreturn]] inline void __throw_bad_any_cast() |
62 | { |
63 | #if __cpp_exceptions |
64 | throw bad_any_cast{}; |
65 | #else |
66 | __builtin_abort(); |
67 | #endif |
68 | } |
69 | |
70 | #define __cpp_lib_any 201606L |
71 | |
72 | /** |
73 | * @brief A type-safe container of any type. |
74 | * |
75 | * An `any` object's state is either empty or it stores a contained object |
76 | * of CopyConstructible type. |
77 | * |
78 | * @since C++17 |
79 | */ |
80 | class any |
81 | { |
82 | // Holds either pointer to a heap object or the contained object itself. |
83 | union _Storage |
84 | { |
85 | constexpr _Storage() : _M_ptr{nullptr} {} |
86 | |
87 | // Prevent trivial copies of this type, buffer might hold a non-POD. |
88 | _Storage(const _Storage&) = delete; |
89 | _Storage& operator=(const _Storage&) = delete; |
90 | |
91 | void* _M_ptr; |
92 | aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer; |
93 | }; |
94 | |
95 | template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>, |
96 | bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) |
97 | && (alignof(_Tp) <= alignof(_Storage))> |
98 | using _Internal = std::integral_constant<bool, _Safe::value && _Fits>; |
99 | |
100 | template<typename _Tp> |
101 | struct _Manager_internal; // uses small-object optimization |
102 | |
103 | template<typename _Tp> |
104 | struct _Manager_external; // creates contained object on the heap |
105 | |
106 | template<typename _Tp> |
107 | using _Manager = __conditional_t<_Internal<_Tp>::value, |
108 | _Manager_internal<_Tp>, |
109 | _Manager_external<_Tp>>; |
110 | |
111 | template<typename _Tp, typename _VTp = decay_t<_Tp>> |
112 | using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>; |
113 | |
114 | /// Emplace with an object created from @p __args as the contained object. |
115 | template <typename _Tp, typename... _Args, |
116 | typename _Mgr = _Manager<_Tp>> |
117 | void __do_emplace(_Args&&... __args) |
118 | { |
119 | reset(); |
120 | _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); |
121 | _M_manager = &_Mgr::_S_manage; |
122 | } |
123 | |
124 | /// Emplace with an object created from @p __il and @p __args as |
125 | /// the contained object. |
126 | template <typename _Tp, typename _Up, typename... _Args, |
127 | typename _Mgr = _Manager<_Tp>> |
128 | void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) |
129 | { |
130 | reset(); |
131 | _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); |
132 | _M_manager = &_Mgr::_S_manage; |
133 | } |
134 | |
135 | template <typename _Res, typename _Tp, typename... _Args> |
136 | using __any_constructible |
137 | = enable_if<__and_<is_copy_constructible<_Tp>, |
138 | is_constructible<_Tp, _Args...>>::value, |
139 | _Res>; |
140 | |
141 | template <typename _Tp, typename... _Args> |
142 | using __any_constructible_t |
143 | = typename __any_constructible<bool, _Tp, _Args...>::type; |
144 | |
145 | template<typename _VTp, typename... _Args> |
146 | using __emplace_t |
147 | = typename __any_constructible<_VTp&, _VTp, _Args...>::type; |
148 | |
149 | public: |
150 | // construct/destruct |
151 | |
152 | /// Default constructor, creates an empty object. |
153 | constexpr any() noexcept : _M_manager(nullptr) { } |
154 | |
155 | /// Copy constructor, copies the state of @p __other |
156 | any(const any& __other) |
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_clone, &__other, &__arg); |
165 | } |
166 | } |
167 | |
168 | /** |
169 | * @brief Move constructor, transfer the state from @p __other |
170 | * |
171 | * @post @c !__other.has_value() (this postcondition is a GNU extension) |
172 | */ |
173 | any(any&& __other) noexcept |
174 | { |
175 | if (!__other.has_value()) |
176 | _M_manager = nullptr; |
177 | else |
178 | { |
179 | _Arg __arg; |
180 | __arg._M_any = this; |
181 | __other._M_manager(_Op_xfer, &__other, &__arg); |
182 | } |
183 | } |
184 | |
185 | /// Construct with a copy of @p __value as the contained object. |
186 | template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>, |
187 | typename _Mgr = _Manager<_VTp>, |
188 | enable_if_t<is_copy_constructible_v<_VTp> |
189 | && !__is_in_place_type_v<_VTp>, bool> = true> |
190 | any(_Tp&& __value) |
191 | : _M_manager(&_Mgr::_S_manage) |
192 | { |
193 | _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); |
194 | } |
195 | |
196 | /// Construct with an object created from @p __args as the contained object. |
197 | template <typename _Tp, typename... _Args, typename _VTp = decay_t<_Tp>, |
198 | typename _Mgr = _Manager<_VTp>, |
199 | __any_constructible_t<_VTp, _Args&&...> = false> |
200 | explicit |
201 | any(in_place_type_t<_Tp>, _Args&&... __args) |
202 | : _M_manager(&_Mgr::_S_manage) |
203 | { |
204 | _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); |
205 | } |
206 | |
207 | /// Construct with an object created from @p __il and @p __args as |
208 | /// the contained object. |
209 | template <typename _Tp, typename _Up, typename... _Args, |
210 | typename _VTp = decay_t<_Tp>, typename _Mgr = _Manager<_VTp>, |
211 | __any_constructible_t<_VTp, initializer_list<_Up>&, |
212 | _Args&&...> = false> |
213 | explicit |
214 | any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) |
215 | : _M_manager(&_Mgr::_S_manage) |
216 | { |
217 | _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); |
218 | } |
219 | |
220 | /// Destructor, calls @c reset() |
221 | ~any() { reset(); } |
222 | |
223 | // assignments |
224 | |
225 | /// Copy the state of another object. |
226 | any& |
227 | operator=(const any& __rhs) |
228 | { |
229 | *this = any(__rhs); |
230 | return *this; |
231 | } |
232 | |
233 | /** |
234 | * @brief Move assignment operator |
235 | * |
236 | * @post @c !__rhs.has_value() (not guaranteed for other implementations) |
237 | */ |
238 | any& |
239 | operator=(any&& __rhs) noexcept |
240 | { |
241 | if (!__rhs.has_value()) |
242 | reset(); |
243 | else if (this != &__rhs) |
244 | { |
245 | reset(); |
246 | _Arg __arg; |
247 | __arg._M_any = this; |
248 | __rhs._M_manager(_Op_xfer, &__rhs, &__arg); |
249 | } |
250 | return *this; |
251 | } |
252 | |
253 | /// Store a copy of @p __rhs as the contained object. |
254 | template<typename _Tp> |
255 | enable_if_t<is_copy_constructible<_Decay_if_not_any<_Tp>>::value, any&> |
256 | operator=(_Tp&& __rhs) |
257 | { |
258 | *this = any(std::forward<_Tp>(__rhs)); |
259 | return *this; |
260 | } |
261 | |
262 | /// Emplace with an object created from @p __args as the contained object. |
263 | template <typename _Tp, typename... _Args> |
264 | __emplace_t<decay_t<_Tp>, _Args...> |
265 | emplace(_Args&&... __args) |
266 | { |
267 | using _VTp = decay_t<_Tp>; |
268 | __do_emplace<_VTp>(std::forward<_Args>(__args)...); |
269 | return *any::_Manager<_VTp>::_S_access(_M_storage); |
270 | } |
271 | |
272 | /// Emplace with an object created from @p __il and @p __args as |
273 | /// the contained object. |
274 | template <typename _Tp, typename _Up, typename... _Args> |
275 | __emplace_t<decay_t<_Tp>, initializer_list<_Up>&, _Args&&...> |
276 | emplace(initializer_list<_Up> __il, _Args&&... __args) |
277 | { |
278 | using _VTp = decay_t<_Tp>; |
279 | __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); |
280 | return *any::_Manager<_VTp>::_S_access(_M_storage); |
281 | } |
282 | |
283 | // modifiers |
284 | |
285 | /// If not empty, destroy the contained object. |
286 | void reset() noexcept |
287 | { |
288 | if (has_value()) |
289 | { |
290 | _M_manager(_Op_destroy, this, nullptr); |
291 | _M_manager = nullptr; |
292 | } |
293 | } |
294 | |
295 | /// Exchange state with another object. |
296 | void swap(any& __rhs) noexcept |
297 | { |
298 | if (!has_value() && !__rhs.has_value()) |
299 | return; |
300 | |
301 | if (has_value() && __rhs.has_value()) |
302 | { |
303 | if (this == &__rhs) |
304 | return; |
305 | |
306 | any __tmp; |
307 | _Arg __arg; |
308 | __arg._M_any = &__tmp; |
309 | __rhs._M_manager(_Op_xfer, &__rhs, &__arg); |
310 | __arg._M_any = &__rhs; |
311 | _M_manager(_Op_xfer, this, &__arg); |
312 | __arg._M_any = this; |
313 | __tmp._M_manager(_Op_xfer, &__tmp, &__arg); |
314 | } |
315 | else |
316 | { |
317 | any* __empty = !has_value() ? this : &__rhs; |
318 | any* __full = !has_value() ? &__rhs : this; |
319 | _Arg __arg; |
320 | __arg._M_any = __empty; |
321 | __full->_M_manager(_Op_xfer, __full, &__arg); |
322 | } |
323 | } |
324 | |
325 | // observers |
326 | |
327 | /// Reports whether there is a contained object or not. |
328 | bool has_value() const noexcept { return _M_manager != nullptr; } |
329 | |
330 | #if __cpp_rtti |
331 | /// The @c typeid of the contained object, or @c typeid(void) if empty. |
332 | const type_info& type() const noexcept |
333 | { |
334 | if (!has_value()) |
335 | return typeid(void); |
336 | _Arg __arg; |
337 | _M_manager(_Op_get_type_info, this, &__arg); |
338 | return *__arg._M_typeinfo; |
339 | } |
340 | #endif |
341 | |
342 | /// @cond undocumented |
343 | template<typename _Tp> |
344 | static constexpr bool __is_valid_cast() |
345 | { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; } |
346 | /// @endcond |
347 | |
348 | private: |
349 | enum _Op { |
350 | _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer |
351 | }; |
352 | |
353 | union _Arg |
354 | { |
355 | void* _M_obj; |
356 | const std::type_info* _M_typeinfo; |
357 | any* _M_any; |
358 | }; |
359 | |
360 | void (*_M_manager)(_Op, const any*, _Arg*); |
361 | _Storage _M_storage; |
362 | |
363 | /// @cond undocumented |
364 | template<typename _Tp> |
365 | friend void* __any_caster(const any* __any); |
366 | /// @endcond |
367 | |
368 | // Manage in-place contained object. |
369 | template<typename _Tp> |
370 | struct _Manager_internal |
371 | { |
372 | static void |
373 | _S_manage(_Op __which, const any* __anyp, _Arg* __arg); |
374 | |
375 | template<typename _Up> |
376 | static void |
377 | _S_create(_Storage& __storage, _Up&& __value) |
378 | { |
379 | void* __addr = &__storage._M_buffer; |
380 | ::new (__addr) _Tp(std::forward<_Up>(__value)); |
381 | } |
382 | |
383 | template<typename... _Args> |
384 | static void |
385 | _S_create(_Storage& __storage, _Args&&... __args) |
386 | { |
387 | void* __addr = &__storage._M_buffer; |
388 | ::new (__addr) _Tp(std::forward<_Args>(__args)...); |
389 | } |
390 | |
391 | static _Tp* |
392 | _S_access(const _Storage& __storage) |
393 | { |
394 | // The contained object is in __storage._M_buffer |
395 | const void* __addr = &__storage._M_buffer; |
396 | return static_cast<_Tp*>(const_cast<void*>(__addr)); |
397 | } |
398 | }; |
399 | |
400 | // Manage external contained object. |
401 | template<typename _Tp> |
402 | struct _Manager_external |
403 | { |
404 | static void |
405 | _S_manage(_Op __which, const any* __anyp, _Arg* __arg); |
406 | |
407 | template<typename _Up> |
408 | static void |
409 | _S_create(_Storage& __storage, _Up&& __value) |
410 | { |
411 | __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); |
412 | } |
413 | template<typename... _Args> |
414 | static void |
415 | _S_create(_Storage& __storage, _Args&&... __args) |
416 | { |
417 | __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); |
418 | } |
419 | static _Tp* |
420 | _S_access(const _Storage& __storage) |
421 | { |
422 | // The contained object is in *__storage._M_ptr |
423 | return static_cast<_Tp*>(__storage._M_ptr); |
424 | } |
425 | }; |
426 | }; |
427 | |
428 | /// Exchange the states of two @c any objects. |
429 | inline void swap(any& __x, any& __y) noexcept { __x.swap(rhs&: __y); } |
430 | |
431 | /// Create an `any` holding a `_Tp` constructed from `__args...`. |
432 | template <typename _Tp, typename... _Args> |
433 | inline |
434 | enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>, _Args...>, any> |
435 | make_any(_Args&&... __args) |
436 | { |
437 | return any(in_place_type<_Tp>, std::forward<_Args>(__args)...); |
438 | } |
439 | |
440 | /// Create an `any` holding a `_Tp` constructed from `__il` and `__args...`. |
441 | template <typename _Tp, typename _Up, typename... _Args> |
442 | inline |
443 | enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>, |
444 | initializer_list<_Up>&, _Args...>, any> |
445 | make_any(initializer_list<_Up> __il, _Args&&... __args) |
446 | { |
447 | return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); |
448 | } |
449 | |
450 | /** |
451 | * @brief Access the contained object. |
452 | * |
453 | * @tparam _ValueType A const-reference or CopyConstructible type. |
454 | * @param __any The object to access. |
455 | * @return The contained object. |
456 | * @throw bad_any_cast If <code> |
457 | * __any.type() != typeid(remove_reference_t<_ValueType>) |
458 | * </code> |
459 | */ |
460 | template<typename _ValueType> |
461 | inline _ValueType any_cast(const any& __any) |
462 | { |
463 | using _Up = __remove_cvref_t<_ValueType>; |
464 | static_assert(any::__is_valid_cast<_ValueType>(), |
465 | "Template argument must be a reference or CopyConstructible type" ); |
466 | static_assert(is_constructible_v<_ValueType, const _Up&>, |
467 | "Template argument must be constructible from a const value." ); |
468 | auto __p = any_cast<_Up>(&__any); |
469 | if (__p) |
470 | return static_cast<_ValueType>(*__p); |
471 | __throw_bad_any_cast(); |
472 | } |
473 | |
474 | /** |
475 | * @brief Access the contained object. |
476 | * |
477 | * @tparam _ValueType A reference or CopyConstructible type. |
478 | * @param __any The object to access. |
479 | * @return The contained object. |
480 | * @throw bad_any_cast If <code> |
481 | * __any.type() != typeid(remove_reference_t<_ValueType>) |
482 | * </code> |
483 | * |
484 | * @{ |
485 | */ |
486 | template<typename _ValueType> |
487 | inline _ValueType any_cast(any& __any) |
488 | { |
489 | using _Up = __remove_cvref_t<_ValueType>; |
490 | static_assert(any::__is_valid_cast<_ValueType>(), |
491 | "Template argument must be a reference or CopyConstructible type" ); |
492 | static_assert(is_constructible_v<_ValueType, _Up&>, |
493 | "Template argument must be constructible from an lvalue." ); |
494 | auto __p = any_cast<_Up>(&__any); |
495 | if (__p) |
496 | return static_cast<_ValueType>(*__p); |
497 | __throw_bad_any_cast(); |
498 | } |
499 | |
500 | template<typename _ValueType> |
501 | inline _ValueType any_cast(any&& __any) |
502 | { |
503 | using _Up = __remove_cvref_t<_ValueType>; |
504 | static_assert(any::__is_valid_cast<_ValueType>(), |
505 | "Template argument must be a reference or CopyConstructible type" ); |
506 | static_assert(is_constructible_v<_ValueType, _Up>, |
507 | "Template argument must be constructible from an rvalue." ); |
508 | auto __p = any_cast<_Up>(&__any); |
509 | if (__p) |
510 | return static_cast<_ValueType>(std::move(*__p)); |
511 | __throw_bad_any_cast(); |
512 | } |
513 | /// @} |
514 | |
515 | /// @cond undocumented |
516 | template<typename _Tp> |
517 | void* __any_caster(const any* __any) |
518 | { |
519 | // any_cast<T> returns non-null if __any->type() == typeid(T) and |
520 | // typeid(T) ignores cv-qualifiers so remove them: |
521 | using _Up = remove_cv_t<_Tp>; |
522 | // The contained value has a decayed type, so if decay_t<U> is not U, |
523 | // then it's not possible to have a contained value of type U: |
524 | if constexpr (!is_same_v<decay_t<_Up>, _Up>) |
525 | return nullptr; |
526 | // Only copy constructible types can be used for contained values: |
527 | else if constexpr (!is_copy_constructible_v<_Up>) |
528 | return nullptr; |
529 | // First try comparing function addresses, which works without RTTI |
530 | else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage |
531 | #if __cpp_rtti |
532 | || __any->type() == typeid(_Tp) |
533 | #endif |
534 | ) |
535 | { |
536 | return any::_Manager<_Up>::_S_access(__any->_M_storage); |
537 | } |
538 | return nullptr; |
539 | } |
540 | /// @endcond |
541 | |
542 | /** |
543 | * @brief Access the contained object. |
544 | * |
545 | * @tparam _ValueType The type of the contained object. |
546 | * @param __any A pointer to the object to access. |
547 | * @return The address of the contained object if <code> |
548 | * __any != nullptr && __any.type() == typeid(_ValueType) |
549 | * </code>, otherwise a null pointer. |
550 | * |
551 | * @{ |
552 | */ |
553 | template<typename _ValueType> |
554 | inline const _ValueType* any_cast(const any* __any) noexcept |
555 | { |
556 | if constexpr (is_object_v<_ValueType>) |
557 | if (__any) |
558 | return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); |
559 | return nullptr; |
560 | } |
561 | |
562 | template<typename _ValueType> |
563 | inline _ValueType* any_cast(any* __any) noexcept |
564 | { |
565 | if constexpr (is_object_v<_ValueType>) |
566 | if (__any) |
567 | return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); |
568 | return nullptr; |
569 | } |
570 | /// @} |
571 | |
572 | template<typename _Tp> |
573 | void |
574 | any::_Manager_internal<_Tp>:: |
575 | _S_manage(_Op __which, const any* __any, _Arg* __arg) |
576 | { |
577 | // The contained object is in _M_storage._M_buffer |
578 | auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer); |
579 | switch (__which) |
580 | { |
581 | case _Op_access: |
582 | __arg->_M_obj = const_cast<_Tp*>(__ptr); |
583 | break; |
584 | case _Op_get_type_info: |
585 | #if __cpp_rtti |
586 | __arg->_M_typeinfo = &typeid(_Tp); |
587 | #endif |
588 | break; |
589 | case _Op_clone: |
590 | ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); |
591 | __arg->_M_any->_M_manager = __any->_M_manager; |
592 | break; |
593 | case _Op_destroy: |
594 | __ptr->~_Tp(); |
595 | break; |
596 | case _Op_xfer: |
597 | ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp |
598 | (std::move(*const_cast<_Tp*>(__ptr))); |
599 | __ptr->~_Tp(); |
600 | __arg->_M_any->_M_manager = __any->_M_manager; |
601 | const_cast<any*>(__any)->_M_manager = nullptr; |
602 | break; |
603 | } |
604 | } |
605 | |
606 | template<typename _Tp> |
607 | void |
608 | any::_Manager_external<_Tp>:: |
609 | _S_manage(_Op __which, const any* __any, _Arg* __arg) |
610 | { |
611 | // The contained object is *_M_storage._M_ptr |
612 | auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr); |
613 | switch (__which) |
614 | { |
615 | case _Op_access: |
616 | __arg->_M_obj = const_cast<_Tp*>(__ptr); |
617 | break; |
618 | case _Op_get_type_info: |
619 | #if __cpp_rtti |
620 | __arg->_M_typeinfo = &typeid(_Tp); |
621 | #endif |
622 | break; |
623 | case _Op_clone: |
624 | __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); |
625 | __arg->_M_any->_M_manager = __any->_M_manager; |
626 | break; |
627 | case _Op_destroy: |
628 | delete __ptr; |
629 | break; |
630 | case _Op_xfer: |
631 | __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; |
632 | __arg->_M_any->_M_manager = __any->_M_manager; |
633 | const_cast<any*>(__any)->_M_manager = nullptr; |
634 | break; |
635 | } |
636 | } |
637 | |
638 | /// @} |
639 | |
640 | namespace __detail::__variant |
641 | { |
642 | template<typename> struct _Never_valueless_alt; // see <variant> |
643 | |
644 | // Provide the strong exception-safety guarantee when emplacing an |
645 | // any into a variant. |
646 | template<> |
647 | struct _Never_valueless_alt<std::any> |
648 | : std::true_type |
649 | { }; |
650 | } // namespace __detail::__variant |
651 | |
652 | _GLIBCXX_END_NAMESPACE_VERSION |
653 | } // namespace std |
654 | |
655 | #endif // C++17 |
656 | #endif // _GLIBCXX_ANY |
657 | |