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

Reply via email to