30#ifndef _GLIBCXX_INDIRECT_H
31#define _GLIBCXX_INDIRECT_H 1
33#pragma GCC system_header
37#if __glibcxx_indirect || __glibcxx_polymorphic
43#include <bits/uses_allocator.h>
48namespace std _GLIBCXX_VISIBILITY(default)
50_GLIBCXX_BEGIN_NAMESPACE_VERSION
53 template<
typename _Tp,
typename _Alloc = allocator<_Tp>>
56 template<
typename _Tp>
57 constexpr bool __is_indirect =
false;
58 template<
typename _Tp,
typename _Alloc>
59 constexpr bool __is_indirect<indirect<_Tp, _Alloc>> =
true;
64 template<
typename _Tp>
65 using indirect = indirect<_Tp, polymorphic_allocator<_Tp>>;
70 template<
typename _Tp,
typename _Alloc>
73 static_assert(is_object_v<_Tp>);
74 static_assert(!is_array_v<_Tp>);
75 static_assert(!is_same_v<_Tp, in_place_t>);
76 static_assert(!__is_in_place_type_v<_Tp>);
77 static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
79 using _ATraits = allocator_traits<_Alloc>;
80 static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
83 using value_type = _Tp;
84 using allocator_type = _Alloc;
85 using pointer =
typename allocator_traits<_Alloc>::pointer;
86 using const_pointer =
typename allocator_traits<_Alloc>::const_pointer;
89 indirect()
requires is_default_constructible_v<_Alloc>
90 : _M_objp(_M_make_obj_chk())
94 indirect(allocator_arg_t,
const _Alloc& __a)
95 : _M_alloc(__a), _M_objp(_M_make_obj_chk())
99 indirect(
const indirect& __o)
100 : indirect(allocator_arg,
101 _ATraits::select_on_container_copy_construction(__o._M_alloc),
106 indirect(allocator_arg_t,
const _Alloc& __a,
const indirect& __other)
110 _M_objp = _M_make_obj_chk(__other.__get());
116 indirect(indirect&& __other) noexcept
118 _M_objp(std::__exchange(__other._M_objp,
nullptr))
122 indirect(allocator_arg_t,
const _Alloc& __a,
123 indirect&& __other)
noexcept(_ATraits::is_always_equal::value)
125 _M_objp(std::__exchange(__other._M_objp, nullptr))
127 if constexpr (!_ATraits::is_always_equal::value)
128 if (_M_objp && _M_alloc != __other._M_alloc)
130 static_assert(sizeof(_Tp) != 0,
"must be a complete type");
133 __other._M_objp = std::__exchange(_M_objp, nullptr);
135 _M_objp = _M_make_obj(std::move(*__other._M_objp));
139 template<
typename _Up = _Tp>
140 requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
141 && (!is_same_v<remove_cvref_t<_Up>, indirect>)
142 && is_constructible_v<_Tp, _Up>
143 && is_default_constructible_v<_Alloc>
146 : _M_objp(_M_make_obj(std::
forward<_Up>(__u)))
149 template<
typename _Up = _Tp>
150 requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
151 && (!is_same_v<remove_cvref_t<_Up>, indirect>)
152 && is_constructible_v<_Tp, _Up>
154 indirect(allocator_arg_t,
const _Alloc& __a, _Up&& __u)
155 : _M_alloc(__a), _M_objp(_M_make_obj(std::
forward<_Up>(__u)))
158 template<
typename... _Us>
159 requires is_constructible_v<_Tp, _Us...>
160 && is_default_constructible_v<_Alloc>
162 indirect(in_place_t, _Us&&... __us)
163 : _M_objp(_M_make_obj(std::
forward<_Us>(__us)...))
166 template<
typename... _Us>
167 requires is_constructible_v<_Tp, _Us...>
169 indirect(allocator_arg_t,
const _Alloc& __a, in_place_t, _Us&&... __us)
171 _M_objp(_M_make_obj(std::
forward<_Us>(__us)...))
174 template<
typename _Ip,
typename... _Us>
175 requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...>
176 && is_default_constructible_v<_Alloc>
178 indirect(in_place_t, initializer_list<_Ip> __il, _Us&&... __us)
179 : _M_objp(_M_make_obj(__il, std::
forward<_Us>(__us)...))
182 template<
typename _Ip,
typename... _Us>
183 requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...>
185 indirect(allocator_arg_t,
const _Alloc& __a,
186 in_place_t, initializer_list<_Ip> __il, _Us&&... __us)
188 _M_objp(_M_make_obj(__il, std::
forward<_Us>(__us)...))
191 constexpr ~indirect()
193 static_assert(
sizeof(_Tp) != 0,
"must be a complete type");
198 operator=(
const indirect& __other)
200 static_assert(is_copy_assignable_v<_Tp>);
201 static_assert(is_copy_constructible_v<_Tp>);
203 if (__builtin_addressof(__other) ==
this) [[unlikely]]
206 constexpr bool __pocca
207 = _ATraits::propagate_on_container_copy_assignment::value;
209 pointer __ptr =
nullptr;
212 if (_ATraits::is_always_equal::value
213 || _M_alloc == __other._M_alloc)
217 *_M_objp = __other.__get();
218 if constexpr (__pocca)
219 _M_alloc = __other._M_alloc;
223 const indirect& __x = __pocca ? __other : *
this;
224 __ptr = __x._M_make_obj(__other.__get());
229 if constexpr (__pocca)
230 _M_alloc = __other._M_alloc;
236 operator=(indirect&& __other)
237 noexcept(_ATraits::propagate_on_container_move_assignment::value
238 || _ATraits::is_always_equal::value)
243 if (__builtin_addressof(__other) ==
this) [[unlikely]]
246 constexpr bool __pocma
247 = _ATraits::propagate_on_container_move_assignment::value;
249 pointer __ptr =
nullptr;
253 if constexpr (_ATraits::is_always_equal::value || __pocma)
254 __ptr = std::__exchange(__other._M_objp,
nullptr);
255 else if (_M_alloc == __other._M_alloc)
256 __ptr = std::__exchange(__other._M_objp,
nullptr);
257 else if (__other._M_objp)
259 static_assert(is_move_constructible_v<_Tp>);
260 __ptr = _M_make_obj(
std::move(*__other._M_objp));
265 if constexpr (__pocma)
266 _M_alloc = __other._M_alloc;
271 template<
typename _Up = _Tp>
272 requires (!is_same_v<remove_cvref_t<_Up>, indirect>)
273 && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
277 if (_M_objp ==
nullptr)
285 template<
typename _Self>
291 const indirect& __iself = (
const indirect&)__self;
292 __glibcxx_assert(__iself._M_objp !=
nullptr);
293 return std::forward_like<_Self>(*__iself._M_objp);
296 constexpr const_pointer
297 operator->() const noexcept
304 operator->() noexcept
311 valueless_after_move() const noexcept {
return _M_objp ==
nullptr; }
313 constexpr allocator_type
314 get_allocator() const noexcept {
return _M_alloc; }
317 swap(indirect& __other)
318 noexcept(_ATraits::propagate_on_container_swap::value
319 || _ATraits::is_always_equal::value)
322 swap(_M_objp, __other._M_objp);
323 if constexpr (_ATraits::propagate_on_container_swap::value)
324 swap(_M_alloc, __other._M_alloc);
325 else if constexpr (!_ATraits::is_always_equal::value)
326 __glibcxx_assert(_M_alloc == __other._M_alloc);
329 friend constexpr void
330 swap(indirect& __lhs, indirect& __rhs)
331 noexcept(_ATraits::propagate_on_container_swap::value
332 || _ATraits::is_always_equal::value)
333 { __lhs.swap(__rhs); }
335 template<
typename _Up,
typename _Alloc2>
336 requires requires (
const _Tp& __t,
const _Up& __u) { __t == __u; }
337 friend constexpr bool
338 operator==(
const indirect& __lhs,
const indirect<_Up, _Alloc2>& __rhs)
339 noexcept(
noexcept(*__lhs == *__rhs))
341 if (!__lhs._M_objp || !__rhs._M_objp)
342 return bool(__lhs._M_objp) == bool(__rhs._M_objp);
344 return __lhs.__get() == __rhs.__get();
347 template<
typename _Up>
348 requires (!__is_indirect<_Up>)
349 &&
requires (
const _Tp& __t,
const _Up& __u) { __t == __u; }
350 friend constexpr bool
351 operator==(
const indirect& __lhs,
const _Up& __rhs)
352 noexcept(
noexcept(*__lhs == __rhs))
357 return __lhs.__get() == __rhs;
360 template<
typename _Up,
typename _Alloc2>
361 friend constexpr __detail::__synth3way_t<_Tp, _Up>
362 operator<=>(
const indirect& __lhs,
const indirect<_Up, _Alloc2>& __rhs)
363 noexcept(
noexcept(__detail::__synth3way(*__lhs, *__rhs)))
365 if (!__lhs._M_objp || !__rhs._M_objp)
366 return bool(__lhs._M_objp) <=> bool(__rhs._M_objp);
368 return __detail::__synth3way(__lhs.__get(), __rhs.__get());
371 template<
typename _Up>
372 requires (!__is_indirect<_Up>)
373 friend constexpr __detail::__synth3way_t<_Tp, _Up>
374 operator<=>(
const indirect& __lhs,
const _Up& __rhs)
375 noexcept(
noexcept(__detail::__synth3way(*__lhs, __rhs)))
378 return strong_ordering::less;
380 return __detail::__synth3way(__lhs.__get(), __rhs);
384 template<
typename,
typename>
friend class indirect;
387 _M_reset(pointer __ptr)
noexcept
392 _ATraits::deallocate(_M_alloc, _M_objp, 1);
397 template<
typename... _Args>
399 _M_make_obj(_Args&&... __args)
const
401 _Scoped_allocation __sa(_M_alloc, in_place,
403 return __sa.release();
407 template<
typename... _Args>
408 [[__gnu__::__always_inline__]]
410 _M_make_obj_chk(_Args&&... __args)
const
412 static_assert(is_constructible_v<_Tp, _Args...>);
419 [[__gnu__::__always_inline__]]
421 __get() const noexcept
424 [[no_unique_address]] _Alloc _M_alloc = _Alloc();
428 template<
typename _Value>
429 indirect(_Value) -> indirect<_Value>;
431 template<
typename _Alloc,
typename _Value>
432 indirect(allocator_arg_t, _Alloc, _Value)
433 -> indirect<_Value, __alloc_rebind<_Alloc, _Value>>;
436 template<
typename _Tp,
typename _Alloc>
437 requires is_default_constructible_v<hash<_Tp>>
438 struct hash<indirect<_Tp, _Alloc>>
441 operator()(
const indirect<_Tp, _Alloc>& __t)
const
442 noexcept(
noexcept(hash<_Tp>{}(*__t)))
446 if (__t.valueless_after_move())
448 return hash<_Tp>{}(*__t);
452 template<
typename _Tp,
typename _Alloc>
458#if __glibcxx_polymorphic
459 template<
typename _Tp,
typename _Alloc = allocator<_Tp>>
464 template<
typename _Tp>
465 using polymorphic = polymorphic<_Tp, polymorphic_allocator<_Tp>>;
469 template<
typename _Tp,
typename _Alloc>
472 static_assert(is_object_v<_Tp>);
473 static_assert(!is_array_v<_Tp>);
474 static_assert(!is_same_v<_Tp, in_place_t>);
475 static_assert(!__is_in_place_type_v<_Tp>);
476 static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
478 using _ATraits = allocator_traits<_Alloc>;
479 static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
485 typename _ATraits::pointer _M_objp{};
489 =
typename _ATraits::template rebind_traits<_Obj>::pointer;
491 enum class _Op { _Dispose = 1, _Copy = 2, _Move = 3 };
493 constexpr virtual pointer
494 _M_manage(
const _Alloc&, _Op,
void* =
nullptr) = 0;
497 template<
typename _Up>
498 struct _Obj_impl : _Obj
501 =
typename _ATraits::template rebind_traits<_Obj_impl>;
503 using _Op = _Obj::_Op;
505 union _Uninitialized {
506 constexpr _Uninitialized() { }
507 constexpr ~_Uninitialized() { }
512 template<
typename... _Args>
514 _Obj_impl(
typename _MyTraits::allocator_type& __a,
517 using _PtrTr = pointer_traits<typename _ATraits::pointer>;
518 _MyTraits::construct(__a, __builtin_addressof(_M_u._M_objp),
520 this->_M_objp = _PtrTr::pointer_to(_M_u._M_objp);
523 constexpr virtual typename _Obj::pointer
524 _M_manage(
const _Alloc& __a, _Op __op,
void*)
override
530 return _S_make_obj<_Up>(__a,
std::move(_M_u._M_objp));
532 return _S_make_obj<_Up>(__a,
533 const_cast<const _Up&
>(_M_u._M_objp));
536 using _PtrTr = pointer_traits<typename _MyTraits::pointer>;
537 typename _MyTraits::allocator_type __a2(__a);
539 _MyTraits::deallocate(__a2, _PtrTr::pointer_to(*
this), 1);
543 __builtin_unreachable();
552 using value_type = _Tp;
553 using allocator_type = _Alloc;
554 using pointer =
typename allocator_traits<_Alloc>::pointer;
555 using const_pointer =
typename allocator_traits<_Alloc>::const_pointer;
558 polymorphic()
requires is_default_constructible_v<_Alloc>
559 : polymorphic(in_place_type<_Tp>)
563 polymorphic(allocator_arg_t,
const _Alloc& __a)
564 : polymorphic(allocator_arg, __a, in_place_type<_Tp>)
568 polymorphic(
const polymorphic& __other)
569 : polymorphic(allocator_arg,
570 _ATraits::select_on_container_copy_construction(
576 polymorphic(allocator_arg_t,
const _Alloc& __a,
577 const polymorphic& __other)
581 _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
587 polymorphic(polymorphic&& __other) noexcept
589 _M_objp(std::__exchange(__other._M_objp,
nullptr))
593 polymorphic(allocator_arg_t,
const _Alloc& __a, polymorphic&& __other)
594 noexcept(_ATraits::is_always_equal::value)
596 _M_objp(std::__exchange(__other._M_objp, nullptr))
598 if constexpr (!_ATraits::is_always_equal::value)
599 if (_M_objp && _M_alloc != __other._M_alloc)
602 __other._M_objp = std::__exchange(_M_objp, nullptr);
604 _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Move);
608 template<
typename _Up = _Tp,
typename _UUp = remove_cvref_t<_Up>>
609 requires (!is_same_v<_UUp, polymorphic>)
610 && (!__is_in_place_type_v<_UUp>)
611 && derived_from<_UUp, _Tp>
612 && is_constructible_v<_UUp, _Up>
613 && is_copy_constructible_v<_UUp>
614 && is_default_constructible_v<_Alloc>
616 polymorphic(_Up&& __u)
617 : _M_objp(_M_make_obj<_UUp>(std::
forward<_Up>(__u)))
620 template<
typename _Up = _Tp,
typename _UUp = remove_cvref_t<_Up>>
621 requires (!is_same_v<_UUp, polymorphic>)
622 && (!__is_in_place_type_v<_UUp>)
623 && derived_from<_UUp, _Tp>
624 && is_constructible_v<_UUp, _Up>
625 && is_copy_constructible_v<_UUp>
627 polymorphic(allocator_arg_t,
const _Alloc& __a, _Up&& __u)
628 : _M_alloc(__a), _M_objp(_M_make_obj<_UUp>(std::
forward<_Up>(__u)))
631 template<
typename _Up,
typename... _Ts>
632 requires is_same_v<remove_cvref_t<_Up>, _Up>
633 && derived_from<_Up, _Tp>
634 && is_constructible_v<_Up, _Ts...>
635 && is_copy_constructible_v<_Up>
636 && is_default_constructible_v<_Alloc>
638 polymorphic(in_place_type_t<_Up> __t, _Ts&&... __ts)
639 : _M_objp(_M_make_obj<_Up>(std::
forward<_Ts>(__ts)...))
642 template<
typename _Up,
typename... _Ts>
643 requires is_same_v<remove_cvref_t<_Up>, _Up>
644 && derived_from<_Up, _Tp>
645 && is_constructible_v<_Up, _Ts...>
646 && is_copy_constructible_v<_Up>
648 polymorphic(allocator_arg_t,
const _Alloc& __a,
649 in_place_type_t<_Up>, _Ts&&... __ts)
651 _M_objp(_M_make_obj<_Up>(std::
forward<_Ts>(__ts)...))
654 template<
typename _Up,
typename _Ip,
typename... _Us>
655 requires is_same_v<remove_cvref_t<_Up>, _Up>
656 && derived_from<_Up, _Tp>
657 && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
658 && is_copy_constructible_v<_Up>
659 && is_default_constructible_v<_Alloc>
661 polymorphic(in_place_type_t<_Up>, initializer_list<_Ip> __il,
663 : _M_objp(_M_make_obj<_Up>(__il, std::
forward<_Us>(__us)...))
666 template<
typename _Up,
typename _Ip,
typename... _Us>
667 requires is_same_v<remove_cvref_t<_Up>, _Up>
668 && derived_from<_Up, _Tp>
669 && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
670 && is_copy_constructible_v<_Up>
672 polymorphic(allocator_arg_t,
const _Alloc& __a,
673 in_place_type_t<_Up>, initializer_list<_Ip> __il,
676 _M_objp(_M_make_obj<_Up>(__il, std::
forward<_Us>(__us)...))
679 constexpr ~polymorphic()
681 static_assert(
sizeof(_Tp) != 0,
"must be a complete type");
685 constexpr polymorphic&
686 operator=(
const polymorphic& __other)
688 static_assert(
sizeof(_Tp) != 0,
"must be a complete type");
690 if (__builtin_addressof(__other) ==
this) [[unlikely]]
693 constexpr bool __pocca
694 = _ATraits::propagate_on_container_copy_assignment::value;
696 typename _Obj::pointer __ptr =
nullptr;
699 auto& __a = __pocca ? __other._M_alloc : _M_alloc;
700 __ptr = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
705 if constexpr (__pocca)
706 _M_alloc = __other._M_alloc;
711 constexpr polymorphic&
712 operator=(polymorphic&& __other)
713 noexcept(_ATraits::propagate_on_container_move_assignment::value
714 || _ATraits::is_always_equal::value)
716 if (__builtin_addressof(__other) ==
this) [[unlikely]]
719 constexpr bool __pocma
720 = _ATraits::propagate_on_container_move_assignment::value;
722 typename _Obj::pointer __ptr =
nullptr;
726 if constexpr (_ATraits::is_always_equal::value || __pocma)
727 __ptr = std::__exchange(__other._M_objp,
nullptr);
728 else if (_M_alloc == __other._M_alloc)
729 __ptr = std::__exchange(__other._M_objp,
nullptr);
730 else if (__other._M_objp)
732 static_assert(
sizeof(_Tp) != 0,
"must be a complete type");
733 __ptr = __other._M_objp->_M_manage(_M_alloc, _Obj::_Op::_Move);
738 if constexpr (__pocma)
739 _M_alloc = __other._M_alloc;
747 __glibcxx_assert(_M_objp !=
nullptr);
748 return *_M_objp->_M_objp;
754 __glibcxx_assert(_M_objp !=
nullptr);
755 return *_M_objp->_M_objp;
758 constexpr const_pointer
759 operator->() const noexcept
761 __glibcxx_assert(_M_objp !=
nullptr);
762 return _M_objp ? _M_objp->_M_objp : const_pointer{};
766 operator->() noexcept
768 __glibcxx_assert(_M_objp !=
nullptr);
769 return _M_objp ? _M_objp->_M_objp : pointer{};
773 valueless_after_move() const noexcept {
return _M_objp ==
nullptr; }
775 constexpr allocator_type
776 get_allocator() const noexcept {
return _M_alloc; }
779 swap(polymorphic& __other)
780 noexcept(_ATraits::propagate_on_container_swap::value
781 || _ATraits::is_always_equal::value)
784 swap(_M_objp, __other._M_objp);
785 if constexpr (_ATraits::propagate_on_container_swap::value)
786 swap(_M_alloc, __other._M_alloc);
787 else if constexpr (!_ATraits::is_always_equal::value)
788 __glibcxx_assert(_M_alloc == __other._M_alloc);
791 friend constexpr void
792 swap(polymorphic& __lhs, polymorphic& __rhs)
793 noexcept(_ATraits::propagate_on_container_swap::value
794 || _ATraits::is_always_equal::value)
795 { __lhs.swap(__rhs); }
798 template<
typename _Up,
typename... _Args>
799 static constexpr typename _Obj::pointer
800 _S_make_obj(
const _Alloc& __a, _Args&&... __args)
802 __alloc_rebind<_Alloc, _Obj_impl<_Up>> __objalloc(__a);
803 _Scoped_allocation __sa(__objalloc, in_place, __objalloc,
805 auto __obj = __sa.release();
808 if constexpr (is_pointer_v<typename _Obj::pointer>)
811 return pointer_traits<typename _Obj::pointer>::pointer_to(*__obj);
814 template<
typename _Up,
typename... _Args>
815 constexpr typename _Obj::pointer
816 _M_make_obj(_Args&&... __args)
const
820 _M_reset(
typename _Obj::pointer __ptr)
noexcept
823 _M_objp->_M_manage(_M_alloc, _Obj::_Op::_Dispose);
827 [[no_unique_address]] _Alloc _M_alloc = _Alloc();
828 typename _Obj::pointer _M_objp;
832_GLIBCXX_END_NAMESPACE_VERSION
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
constexpr _Tp * to_address(_Tp *__ptr) noexcept
Obtain address referenced by a pointer to an object.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
ISO C++ entities toplevel namespace is std.
Primary class template hash.