[libcxx-commits] [libcxx] [libc++][pstl] Corrected the return types of some parallel algorithms that were returning "void" (PR #230586)

Michael G. Kazakov via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 12 03:54:08 PDT 2026


https://github.com/mikekazakov updated https://github.com/llvm/llvm-project/pull/230586

>From a26bc40c5af0082d48e9bb4d93984edd0c8d2eb9 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Fri, 9 Oct 2026 17:38:10 +0100
Subject: [PATCH] Corrected the return types of some parallel algorithms

---
 libcxx/include/__algorithm/pstl.h             | 12 +++----
 libcxx/include/__memory/pstl.h                | 16 +++++-----
 libcxx/include/__pstl/backend_fwd.h           | 14 ++++----
 libcxx/include/__pstl/backends/default.h      | 32 ++++++++++---------
 .../alg.fill/pstl.fill_n.pass.cpp             |  8 ++++-
 .../alg.generate/pstl.generate_n.pass.cpp     |  8 ++++-
 .../alg.foreach/pstl.for_each_n.pass.cpp      | 27 ++++++++++------
 .../pstl.destroy_n.pass.cpp                   | 17 ++++++----
 ...uninitialized_default_construct_n.pass.cpp |  7 ++--
 ...l.uninitialized_value_construct_n.pass.cpp |  7 ++--
 .../pstl.uninitialized_fill_n.pass.cpp        |  8 ++---
 11 files changed, 92 insertions(+), 64 deletions(-)

diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 492dd3f3c5d5a..88286df94b0a9 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -486,11 +486,11 @@ template <class _ExecutionPolicy,
           class _Tp,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, const _Tp& __value) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "fill_n requires a ForwardIterator");
   using _Implementation = __pstl::__dispatch<__pstl::__fill_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(
+  return __pstl::__handle_exception<_Implementation>(
       std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__n), __value);
 }
 
@@ -648,11 +648,11 @@ template <class _ExecutionPolicy,
           class _Function,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "for_each_n requires a ForwardIterator");
   using _Implementation = __pstl::__dispatch<__pstl::__for_each_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(
+  return __pstl::__handle_exception<_Implementation>(
       std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__size), std::move(__func));
 }
 
@@ -675,11 +675,11 @@ template <class _ExecutionPolicy,
           class _Generator,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "generate_n requires a ForwardIterator");
   using _Implementation = __pstl::__dispatch<__pstl::__generate_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(
+  return __pstl::__handle_exception<_Implementation>(
       std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__n), std::move(__gen));
 }
 
diff --git a/libcxx/include/__memory/pstl.h b/libcxx/include/__memory/pstl.h
index 7dbc9fdcb51d4..4f3024c8b90f6 100644
--- a/libcxx/include/__memory/pstl.h
+++ b/libcxx/include/__memory/pstl.h
@@ -50,10 +50,10 @@ template <class _ExecutionPolicy,
           class _Size,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void destroy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n) {
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator destroy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "destroy_n requires ForwardIterators");
   using _Implementation = __pstl::__dispatch<__pstl::__destroy_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
+  return __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
 }
 
 template <class _ExecutionPolicy,
@@ -74,13 +74,13 @@ template <class _ExecutionPolicy,
           class _Size,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 uninitialized_default_construct_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(
       _ForwardIterator, "uninitialized_default_construct_n requires ForwardIterators");
   using _Implementation =
       __pstl::__dispatch<__pstl::__uninitialized_default_construct_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
+  return __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
 }
 
 template <class _ExecutionPolicy,
@@ -131,12 +131,12 @@ template <class _ExecutionPolicy,
           class _Size,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 uninitialized_value_construct_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_value_construct_n requires ForwardIterators");
   using _Implementation =
       __pstl::__dispatch<__pstl::__uninitialized_value_construct_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
+  return __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
 }
 
 template <class _ExecutionPolicy,
@@ -158,12 +158,12 @@ template <class _ExecutionPolicy,
           class _Tp,
           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
 uninitialized_fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, const _Tp& __value) {
   _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_fill_n requires ForwardIterators");
   using _Implementation =
       __pstl::__dispatch<__pstl::__uninitialized_fill_n, __pstl::__current_configuration, _RawPolicy>;
-  __pstl::__handle_exception<_Implementation>(
+  return __pstl::__handle_exception<_Implementation>(
       std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n, __value);
 }
 
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 2665209887944..e45943954bed9 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -132,7 +132,7 @@ struct __for_each;
 template <class _Backend, class _ExecutionPolicy>
 struct __for_each_n;
 // template <class _Policy, class _ForwardIterator, class _Size, class _Function>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&&, _ForwardIterator __first, _Size __size, _Function __func) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -144,7 +144,7 @@ struct __fill;
 template <class _Backend, class _ExecutionPolicy>
 struct __fill_n;
 // template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -184,7 +184,7 @@ struct __generate;
 template <class _Backend, class _ExecutionPolicy>
 struct __generate_n;
 // template <class _Policy, class _ForwardIterator, class _Size, class _Generator>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Generator __gen) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -434,7 +434,7 @@ struct __destroy;
 template <class _Backend, class _ExecutionPolicy>
 struct __destroy_n;
 // template <class _Policy, class _ForwardIterator, class _Size>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -460,7 +460,7 @@ struct __uninitialized_default_construct;
 template <class _Backend, class _ExecutionPolicy>
 struct __uninitialized_default_construct_n;
 // template <class _Policy, class _ForwardIterator, class _Size>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -486,7 +486,7 @@ struct __uninitialized_value_construct;
 template <class _Backend, class _ExecutionPolicy>
 struct __uninitialized_value_construct_n;
 // template <class _Policy, class _ForwardIterator, class _Size>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
 
 template <class _Backend, class _ExecutionPolicy>
@@ -498,7 +498,7 @@ struct __uninitialized_fill;
 template <class _Backend, class _ExecutionPolicy>
 struct __uninitialized_fill_n;
 // template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
-// optional<__empty>
+// optional<_ForwardIterator>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, const _Tp &__value) const noexcept;
 
 } // namespace __pstl
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 61f5b0c342baa..769344f34249f 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -465,7 +465,7 @@ struct __destroy<__default_backend_tag, _ExecutionPolicy> {
 template <class _ExecutionPolicy>
 struct __destroy_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size>
-  optional<__empty> operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
+  optional<_ForwardIterator> operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
     using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
     using _Ref      = __iterator_reference<_ForwardIterator>;
     return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) {
@@ -477,16 +477,19 @@ struct __destroy_n<__default_backend_tag, _ExecutionPolicy> {
 template <class _ExecutionPolicy>
 struct __for_each_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size, class _Function>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) const noexcept {
     if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
       using _ForEach          = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>;
       _ForwardIterator __last = __first + __size;
-      return _ForEach()(__policy, std::move(__first), std::move(__last), std::move(__func));
+      auto __res              = _ForEach()(__policy, std::move(__first), __last, std::move(__func));
+      if (!__res) {
+        return nullopt; // Failed to run the algorithm, propagate the error.
+      }
+      return __last;
     } else {
       // Otherwise, use the serial algorithm to avoid doing two passes over the input
-      std::for_each_n(std::move(__first), __size, std::move(__func));
-      return __empty{};
+      return std::for_each_n(std::move(__first), __size, std::move(__func));
     }
   }
 };
@@ -505,16 +508,15 @@ struct __fill<__default_backend_tag, _ExecutionPolicy> {
 template <class _ExecutionPolicy>
 struct __fill_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept {
     if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
-      using _Fill             = __dispatch<__fill, __current_configuration, _ExecutionPolicy>;
-      _ForwardIterator __last = __first + __n;
-      return _Fill()(__policy, std::move(__first), std::move(__last), __value);
+      using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
+      using _Ref      = __iterator_reference<_ForwardIterator>;
+      return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) { __element = __value; });
     } else {
       // Otherwise, use the serial algorithm to avoid doing two passes over the input
-      std::fill_n(std::move(__first), __n, __value);
-      return optional<__empty>{__empty{}};
+      return std::fill_n(std::move(__first), __n, __value);
     }
   }
 };
@@ -561,7 +563,7 @@ struct __generate<__default_backend_tag, _ExecutionPolicy> {
 template <class _ExecutionPolicy>
 struct __generate_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size, class _Generator>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Generator&& __gen) const noexcept {
     using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
     using _Ref      = __iterator_reference<_ForwardIterator>;
@@ -586,7 +588,7 @@ struct __uninitialized_default_construct<__default_backend_tag, _ExecutionPolicy
 template <class _ExecutionPolicy>
 struct __uninitialized_default_construct_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
     using _ForEachN  = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
     using _ValueType = __iterator_value_type<_ForwardIterator>;
@@ -614,7 +616,7 @@ struct __uninitialized_value_construct<__default_backend_tag, _ExecutionPolicy>
 template <class _ExecutionPolicy>
 struct __uninitialized_value_construct_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
     using _ForEachN  = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
     using _ValueType = __iterator_value_type<_ForwardIterator>;
@@ -642,7 +644,7 @@ struct __uninitialized_fill<__default_backend_tag, _ExecutionPolicy> {
 template <class _ExecutionPolicy>
 struct __uninitialized_fill_n<__default_backend_tag, _ExecutionPolicy> {
   template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
   operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, const _Tp& __value) const noexcept {
     using _ForEachN  = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
     using _ValueType = __iterator_value_type<_ForwardIterator>;
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp
index 51232dfef1606..0151177f61759 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp
@@ -34,9 +34,15 @@ template <class Iter>
 struct Test {
   template <class Policy>
   void operator()(Policy&& policy) {
+    { // check the return type
+      int a[]  = {0};
+      auto res = std::fill_n(policy, Iter(std::begin(a)), 0, 0);
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
     { // simple test
       int a[4];
-      std::fill_n(policy, Iter(std::begin(a)), std::size(a), 33);
+      auto res = std::fill_n(policy, Iter(std::begin(a)), std::size(a), 33);
+      assert(res == Iter(std::end(a)));
       assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; }));
     }
     { // check that an empty range works
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/pstl.generate_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/pstl.generate_n.pass.cpp
index 9506044acdbc0..6001112094059 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/pstl.generate_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/pstl.generate_n.pass.cpp
@@ -26,9 +26,15 @@ template <class Iter>
 struct Test {
   template <class ExecutionPolicy>
   void operator()(ExecutionPolicy&& policy) {
+    { // check the return type
+      int a[]  = {0};
+      auto res = std::generate_n(policy, Iter(std::begin(a)), 0, []() { return 1; });
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
     { // simple test
       int a[10];
-      std::generate_n(policy, Iter(std::begin(a)), std::size(a), []() { return 1; });
+      auto res = std::generate_n(policy, Iter(std::begin(a)), std::size(a), []() { return 1; });
+      assert(res == Iter(std::end(a)));
       assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 1; }));
     }
     { // empty range works
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp
index 8769d1b4db554..d79a77719f1e9 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <atomic>
 #include <cassert>
+#include <type_traits>
 #include <vector>
 
 #include "test_macros.h"
@@ -35,15 +36,23 @@ template <class Iter>
 struct Test {
   template <class Policy>
   void operator()(Policy&& policy) {
-    int sizes[] = {0, 1, 2, 100};
-    for (auto size : sizes) {
-      std::vector<int> a(size);
-      std::vector<Bool> called(size);
-      std::for_each_n(policy, Iter(std::data(a)), std::size(a), [&](int& v) {
-        assert(!called[&v - a.data()]);
-        called[&v - a.data()] = true;
-      });
-      assert(std::all_of(std::begin(called), std::end(called), [](bool b) { return b; }));
+    { // Check the return type
+      int a[]  = {0};
+      auto res = std::for_each_n(policy, Iter(std::begin(a)), 0, [](int) {});
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
+    { // Check that every single element is visited
+      int sizes[] = {0, 1, 2, 100};
+      for (auto size : sizes) {
+        std::vector<int> a(size);
+        std::vector<Bool> called(size);
+        auto res = std::for_each_n(policy, Iter(std::data(a)), std::size(a), [&](int& v) {
+          assert(!called[&v - a.data()]);
+          called[&v - a.data()] = true;
+        });
+        assert(std::all_of(std::begin(called), std::end(called), [](bool b) { return b; }));
+        assert(res == Iter(std::data(a) + std::size(a)));
+      }
     }
   }
 };
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/pstl.destroy_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/pstl.destroy_n.pass.cpp
index bcbdb65bb0e2f..c95caf00394a3 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/pstl.destroy_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/pstl.destroy_n.pass.cpp
@@ -13,7 +13,7 @@
 // template <class ExecutionPolicy,
 //           class ForwardIterator,
 //           class Size>
-//   void destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
+//   ForwardIterator destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
 
 #include <atomic>
 #include <algorithm>
@@ -64,8 +64,9 @@ struct TestCounted {
         }
         assert(std::all_of(std::begin(counters), std::begin(counters) + size, [](auto& x) { return x == 1; }));
 
-        std::destroy_n(policy, Iter(pool), size);
-        ASSERT_SAME_TYPE(decltype(std::destroy_n(policy, Iter(pool), size)), void);
+        auto res = std::destroy_n(policy, Iter(pool), size);
+        static_assert(std::is_same_v<decltype(res), Iter>);
+        assert(res == Iter(pool + size));
         assert(std::all_of(std::begin(counters), std::begin(counters) + size, [](auto& x) { return x == 0; }));
       });
 
@@ -97,8 +98,9 @@ struct TestArrayCounted3 {
       }
       assert(counter == 5 * 3);
 
-      std::destroy_n(policy, Iter(pool), 5);
-      ASSERT_SAME_TYPE(decltype(std::destroy_n(policy, Iter(pool), 5)), void);
+      auto res = std::destroy_n(policy, Iter(pool), 5);
+      static_assert(std::is_same_v<decltype(res), Iter>);
+      assert(res == Iter(pool + 5));
       assert(counter == 0);
 
       std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
@@ -128,8 +130,9 @@ struct TestArrayCounted3x2 {
         }
       }
       assert(counter == 5 * 3 * 2);
-      std::destroy_n(policy, Iter(pool), 5);
-      ASSERT_SAME_TYPE(decltype(std::destroy_n(policy, Iter(pool), 5)), void);
+      auto res = std::destroy_n(policy, Iter(pool), 5);
+      static_assert(std::is_same_v<decltype(res), Iter>);
+      assert(res == Iter(pool + 5));
       assert(counter == 0);
 
       std::allocator_traits<Alloc>::deallocate(alloc, pool, 5);
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp
index a6e9c851f8ed5..0de1dc67affa2 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp
@@ -13,7 +13,7 @@
 // template <class ExecutionPolicy,
 //           class ForwardIterator,
 //           class Size>
-//   void uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
+//   ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
 
 #include <atomic>
 #include <algorithm>
@@ -67,8 +67,9 @@ struct TestCounted {
 
       runway_sample(std::size(counters) + 1, [&](size_t size) {
         // Default-construct the Counted objects in range [0, size).
-        std::uninitialized_default_construct_n(policy, Iter(pool), size);
-        ASSERT_SAME_TYPE(decltype(std::uninitialized_default_construct_n(policy, Iter(pool), size)), void);
+        auto res = std::uninitialized_default_construct_n(policy, Iter(pool), size);
+        static_assert(std::is_same_v<decltype(res), Iter>);
+        assert(res == Iter(pool + size));
 
         // Verify that inside this range the counters are all 1 and outside the range they are all 0.
         assert(std::all_of(std::begin(counters), std::begin(counters) + size, [](auto& x) { return x == 1; }));
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp
index 859e922c4bfa4..b50e631bf0c7a 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp
@@ -13,7 +13,7 @@
 // template <class ExecutionPolicy,
 //           class ForwardIterator,
 //           class Size>
-//   void uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
+//   ForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
 
 #include <atomic>
 #include <algorithm>
@@ -67,8 +67,9 @@ struct TestCounted {
 
       runway_sample(std::size(counters) + 1, [&](size_t size) {
         // Default-construct the Counted objects in range [0, size).
-        std::uninitialized_value_construct_n(policy, Iter(pool), size);
-        ASSERT_SAME_TYPE(decltype(std::uninitialized_value_construct_n(policy, Iter(pool), size)), void);
+        auto res = std::uninitialized_value_construct_n(policy, Iter(pool), size);
+        static_assert(std::is_same_v<decltype(res), Iter>);
+        assert(res == Iter(pool + size));
 
         // Verify that inside this range the counters are all 1 and outside the range they are all 0.
         assert(std::all_of(std::begin(counters), std::begin(counters) + size, [](auto& x) { return x == 1; }));
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp
index b25d2a7769c5b..6ed8ee303a2f3 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp
@@ -14,7 +14,7 @@
 //           class ForwardIterator,
 //           class Size,
 //           class T>
-//   void uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value);
+//   ForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value);
 
 #include <atomic>
 #include <algorithm>
@@ -69,9 +69,9 @@ struct TestCounted {
 
       runway_sample(std::size(counters) + 1, [&](size_t size) {
         // Construct the Counted object in range [0, size).
-        std::uninitialized_fill_n(policy, Iter(pool), size, CountedInit{pool, counters});
-        ASSERT_SAME_TYPE(
-            decltype(std::uninitialized_fill_n(policy, Iter(pool), size, CountedInit{pool, counters})), void);
+        auto res = std::uninitialized_fill_n(policy, Iter(pool), size, CountedInit{pool, counters});
+        static_assert(std::is_same_v<decltype(res), Iter>);
+        assert(res == Iter(pool + size));
 
         // Verify that inside this range the counters are all 1 and outside the range they are all 0.
         assert(std::all_of(std::begin(counters), std::begin(counters) + size, [](auto& x) { return x == 1; }));



More information about the libcxx-commits mailing list