By generalizing std::__uninitialized_default to work with non-common ranges (i.e. iterator/sentinel pair) we can reuse it for the ranges::uninitialized_value_construct function. Doing that ensures that whatever optimizations we have for std::uninitialized_value_construct are automatically used for the ranges version too.
Tested x86_64-linux. -- >8 -- This reuses the memset optimization in __uninitialized_default for the ranges equivalent, and similarly for uninitialized_value_construct_n. libstdc++-v3/ChangeLog: * include/bits/ranges_uninitialized.h (uninitialized_value_construct): Use __uninitialized_default. (uninitialized_value_construct_n): Use __uninitialized_default_n. * include/bits/stl_uninitialized.h (__uninitialized_default): Allow first and last to be different types, to support arbitrary sentinels. Return the end of the initialized range. (uninitialized_value_construct): Discard return value from __uninitialized_default. --- .../include/bits/ranges_uninitialized.h | 27 +++---------------- libstdc++-v3/include/bits/stl_uninitialized.h | 13 +++++---- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h index f16f2ef39f5..d84c8502eb9 100644 --- a/libstdc++-v3/include/bits/ranges_uninitialized.h +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h @@ -201,18 +201,8 @@ namespace ranges _Iter operator()(_Iter __first, _Sent __last) const { - using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill(__first, __last, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } + return std::__uninitialized_default(std::move(__first), + std::move(__last)); } template<__detail::__nothrow_forward_range _Range> @@ -234,18 +224,7 @@ namespace ranges _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n) const { - using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill_n(__first, __n, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(__first); - for (; __n > 0; ++__first, (void) --__n) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } + return std::__uninitialized_default_n(std::move(__first), __n); } }; diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 1216b319f66..b13562992de 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -634,9 +634,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default // Fills [first, last) with value-initialized value_types. - template<typename _ForwardIterator> - inline void - __uninitialized_default(_ForwardIterator __first, _ForwardIterator __last) + template<typename _ForwardIterator, typename _Sentinel> + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_default(_ForwardIterator __first, _Sentinel __last) { if constexpr (__is_random_access_iter<_ForwardIterator>::__value) if (void* __ptr = std::__ptr_for_trivial_zero_init(__first)) @@ -649,14 +650,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const size_t __n = __dist; __glibcxx_assert(__n < __SIZE_MAX__ / sizeof(_ValueType)); __builtin_memset(__ptr, 0, __n * sizeof(_ValueType)); + return __first + __dist; } - return; + return __first; } _UninitDestroyGuard<_ForwardIterator> __guard(__first); for (; __first != __last; ++__first) std::_Construct(std::__addressof(*__first)); __guard.release(); + return __first; } // __uninitialized_default_n @@ -939,7 +942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { - return std::__uninitialized_default(__first, __last); + std::__uninitialized_default(__first, __last); } /** -- 2.45.2