|
29 | 29 | #include <__type_traits/is_trivially_copy_constructible.h> |
30 | 30 | #include <__type_traits/is_trivially_move_assignable.h> |
31 | 31 | #include <__type_traits/is_trivially_move_constructible.h> |
32 | | -#include <__type_traits/is_trivially_relocatable.h> |
33 | 32 | #include <__type_traits/is_unbounded_array.h> |
34 | 33 | #include <__type_traits/negation.h> |
35 | 34 | #include <__type_traits/remove_const.h> |
@@ -595,56 +594,60 @@ __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, |
595 | 594 | return std::__rewrap_iter(__first2, __result); |
596 | 595 | } |
597 | 596 |
|
598 | | -template <class _Alloc, class _Type> |
599 | | -struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {}; |
600 | | - |
601 | | -template <class _Type> |
602 | | -struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {}; |
603 | | - |
604 | | -template <class _Alloc, class _Tp> |
605 | | -struct __allocator_has_trivial_destroy : _Not<__has_destroy<_Alloc, _Tp*> > {}; |
606 | | - |
607 | | -template <class _Tp, class _Up> |
608 | | -struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {}; |
609 | | - |
610 | | -// __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result. |
611 | | -// Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy, |
612 | | -// except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy. |
613 | | -// |
614 | | -// Preconditions: __result doesn't contain any objects and [__first, __last) contains objects |
615 | | -// Postconditions: __result contains the objects from [__first, __last) and |
616 | | -// [__first, __last) doesn't contain any objects |
| 597 | +// Move-construct the elements [__first1, __last1) into [__first2, __first2 + N) |
| 598 | +// if the move constructor is noexcept, where N is distance(__first1, __last1). |
617 | 599 | // |
618 | | -// The strong exception guarantee is provided if any of the following are true: |
619 | | -// - is_nothrow_move_constructible<_Tp> |
620 | | -// - is_copy_constructible<_Tp> |
621 | | -// - __libcpp_is_trivially_relocatable<_Tp> |
622 | | -template <class _Alloc, class _Tp> |
623 | | -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void |
624 | | -__uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) { |
| 600 | +// Otherwise try to copy all elements. If an exception is thrown the already copied |
| 601 | +// elements are destroyed in reverse order of their construction. |
| 602 | +template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> |
| 603 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 |
| 604 | +__uninitialized_allocator_move_if_noexcept(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { |
625 | 605 | static_assert(__is_cpp17_move_insertable<_Alloc>::value, |
626 | 606 | "The specified type does not meet the requirements of Cpp17MoveInsertable"); |
627 | | - if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value || |
628 | | - !__allocator_has_trivial_move_construct<_Alloc, _Tp>::value || |
629 | | - !__allocator_has_trivial_destroy<_Alloc, _Tp>::value) { |
630 | | - auto __destruct_first = __result; |
631 | | - auto __guard = |
632 | | - std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result)); |
633 | | - while (__first != __last) { |
| 607 | + auto __destruct_first = __first2; |
| 608 | + auto __guard = |
| 609 | + std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); |
| 610 | + while (__first1 != __last1) { |
634 | 611 | #ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
635 | | - allocator_traits<_Alloc>::construct(__alloc, __result, std::move_if_noexcept(*__first)); |
| 612 | + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); |
636 | 613 | #else |
637 | | - allocator_traits<_Alloc>::construct(__alloc, __result, std::move(*__first)); |
| 614 | + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1)); |
638 | 615 | #endif |
639 | | - ++__first; |
640 | | - ++__result; |
| 616 | + ++__first1; |
| 617 | + ++__first2; |
| 618 | + } |
| 619 | + __guard.__complete(); |
| 620 | + return __first2; |
| 621 | +} |
| 622 | + |
| 623 | +template <class _Alloc, class _Type> |
| 624 | +struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {}; |
| 625 | + |
| 626 | +template <class _Type> |
| 627 | +struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {}; |
| 628 | + |
| 629 | +#ifndef _LIBCPP_COMPILER_GCC |
| 630 | +template < |
| 631 | + class _Alloc, |
| 632 | + class _Iter1, |
| 633 | + class _Iter2, |
| 634 | + class _Type = typename iterator_traits<_Iter1>::value_type, |
| 635 | + class = __enable_if_t<is_trivially_move_constructible<_Type>::value && is_trivially_move_assignable<_Type>::value && |
| 636 | + __allocator_has_trivial_move_construct<_Alloc, _Type>::value> > |
| 637 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 |
| 638 | +__uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) { |
| 639 | + if (__libcpp_is_constant_evaluated()) { |
| 640 | + while (__first1 != __last1) { |
| 641 | + std::__construct_at(std::__to_address(__first2), std::move(*__first1)); |
| 642 | + ++__first1; |
| 643 | + ++__first2; |
641 | 644 | } |
642 | | - __guard.__complete(); |
643 | | - std::__allocator_destroy(__alloc, __first, __last); |
| 645 | + return __first2; |
644 | 646 | } else { |
645 | | - __builtin_memcpy(__result, __first, sizeof(_Tp) * (__last - __first)); |
| 647 | + return std::move(__first1, __last1, __first2); |
646 | 648 | } |
647 | 649 | } |
| 650 | +#endif // _LIBCPP_COMPILER_GCC |
648 | 651 |
|
649 | 652 | _LIBCPP_END_NAMESPACE_STD |
650 | 653 |
|
|
0 commit comments