Skip to content

Commit 6721bcf

Browse files
authored
[libc++] Accept iterators instead of raw pointers in __uninitialized_allocator_relocate (#114552)
This generalizes the algorithm a bit. Unfortunately, we can't make the call sites cleaner inside std::vector because the arguments being passed can all be fancy pointers, which may not be contiguous iterators.
1 parent d686e5c commit 6721bcf

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

libcxx/include/__memory/uninitialized_algorithms.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -612,20 +612,22 @@ struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {};
612612
// [__first, __last) doesn't contain any objects
613613
//
614614
// The strong exception guarantee is provided if any of the following are true:
615-
// - is_nothrow_move_constructible<_Tp>
616-
// - is_copy_constructible<_Tp>
617-
// - __libcpp_is_trivially_relocatable<_Tp>
618-
template <class _Alloc, class _Tp>
619-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
620-
__uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) {
615+
// - is_nothrow_move_constructible<_ValueType>
616+
// - is_copy_constructible<_ValueType>
617+
// - __libcpp_is_trivially_relocatable<_ValueType>
618+
template <class _Alloc, class _ContiguousIterator>
619+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __uninitialized_allocator_relocate(
620+
_Alloc& __alloc, _ContiguousIterator __first, _ContiguousIterator __last, _ContiguousIterator __result) {
621+
static_assert(__libcpp_is_contiguous_iterator<_ContiguousIterator>::value, "");
622+
using _ValueType = typename iterator_traits<_ContiguousIterator>::value_type;
621623
static_assert(__is_cpp17_move_insertable<_Alloc>::value,
622624
"The specified type does not meet the requirements of Cpp17MoveInsertable");
623-
if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value ||
624-
!__allocator_has_trivial_move_construct<_Alloc, _Tp>::value ||
625-
!__allocator_has_trivial_destroy<_Alloc, _Tp>::value) {
625+
if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_ValueType>::value ||
626+
!__allocator_has_trivial_move_construct<_Alloc, _ValueType>::value ||
627+
!__allocator_has_trivial_destroy<_Alloc, _ValueType>::value) {
626628
auto __destruct_first = __result;
627-
auto __guard =
628-
std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result));
629+
auto __guard = std::__make_exception_guard(
630+
_AllocatorDestroyRangeReverse<_Alloc, _ContiguousIterator>(__alloc, __destruct_first, __result));
629631
auto __iter = __first;
630632
while (__iter != __last) {
631633
#if _LIBCPP_HAS_EXCEPTIONS
@@ -640,7 +642,9 @@ __uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _
640642
std::__allocator_destroy(__alloc, __first, __last);
641643
} else {
642644
// Casting to void* to suppress clang complaining that this is technically UB.
643-
__builtin_memcpy(static_cast<void*>(__result), __first, sizeof(_Tp) * (__last - __first));
645+
__builtin_memcpy(static_cast<void*>(std::__to_address(__result)),
646+
std::__to_address(__first),
647+
sizeof(_ValueType) * (__last - __first));
644648
}
645649
}
646650

0 commit comments

Comments
 (0)