[libcxx-commits] [libcxx] 9410fc6 - [libc++][pstl] Implementation of parallel uninitialized_default_construct, uninitialized_value_construct and uninitialized_fill (#214580)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 13 04:13:57 PDT 2026


Author: Michael G. Kazakov
Date: 2026-08-13T12:13:52+01:00
New Revision: 9410fc68c61057a493abd33c43fbcb8bae1f98e0

URL: https://github.com/llvm/llvm-project/commit/9410fc68c61057a493abd33c43fbcb8bae1f98e0
DIFF: https://github.com/llvm/llvm-project/commit/9410fc68c61057a493abd33c43fbcb8bae1f98e0.diff

LOG: [libc++][pstl] Implementation of parallel uninitialized_default_construct, uninitialized_value_construct and uninitialized_fill (#214580)

This PR adds parallel versions of these functions:
- `std::uninitialized_default_construct`
- `std::uninitialized_default_construct_n`
- `std::uninitialized_value_construct`
- `std::uninitialized_value_construct_n`
- `std::uninitialized_fill`
- `std::uninitialized_fill_n`

They use parallel `for_each` under the hood and are effectively
one-liners, e.g.:
```c++
return ForEach()(policy, std::move(first), std::move(last), [&value](Ref element) {
    ::new (static_cast<void*>(std::addressof(element))) ValueType(value);
});
```

Fixes #134590.
Fixes #134591.
Fixes #134594.
Fixes #134595.

Part of #99938.

Added: 
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct.pass.cpp
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct.pass.cpp
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp
    libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/pstl.uninitialized_fill.pass.cpp

Modified: 
    libcxx/include/__memory/pstl.h
    libcxx/include/__pstl/backend_fwd.h
    libcxx/include/__pstl/backends/default.h
    libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
    libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__memory/pstl.h b/libcxx/include/__memory/pstl.h
index a4fc727f3bf72..c06f53bed7206 100644
--- a/libcxx/include/__memory/pstl.h
+++ b/libcxx/include/__memory/pstl.h
@@ -55,6 +55,87 @@ _LIBCPP_HIDE_FROM_ABI void destroy_n(_ExecutionPolicy&& __policy, _ForwardIterat
   __pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
 }
 
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+uninitialized_default_construct(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_default_construct requires ForwardIterators");
+  using _Implementation =
+      __pstl::__dispatch<__pstl::__uninitialized_default_construct, __pstl::__current_configuration, _RawPolicy>;
+  __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last));
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _Size,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+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);
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+uninitialized_value_construct(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_value_construct requires ForwardIterators");
+  using _Implementation =
+      __pstl::__dispatch<__pstl::__uninitialized_value_construct, __pstl::__current_configuration, _RawPolicy>;
+  __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last));
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _Size,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+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);
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _Tp,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+uninitialized_fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_fill requires ForwardIterators");
+  using _Implementation = __pstl::__dispatch<__pstl::__uninitialized_fill, __pstl::__current_configuration, _RawPolicy>;
+  __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value);
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _Size,
+          class _Tp,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI void
+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>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n, __value);
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17

diff  --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index eb0c8123507d8..221b1b8cb7316 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -384,6 +384,42 @@ struct __destroy_n;
 // optional<__empty>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
 
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_default_construct;
+// template <class _Policy, class _ForwardIterator>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_default_construct_n;
+// template <class _Policy, class _ForwardIterator, class _Size>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_value_construct;
+// template <class _Policy, class _ForwardIterator>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_value_construct_n;
+// template <class _Policy, class _ForwardIterator, class _Size>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_fill;
+// template <class _Policy, class _ForwardIterator, class _Tp>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp &__value) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_fill_n;
+// template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
+// optional<__empty>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, const _Tp &__value) const noexcept;
+
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 443fd5a35eb02..f9a2da0a8f826 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -89,6 +89,12 @@ namespace __pstl {
 // - replace_if
 // - generate
 // - generate_n
+// - uninitialized_default_construct
+// - uninitialized_default_construct_n
+// - uninitialized_value_construct
+// - uninitialized_value_construct_n
+// - uninitialized_fill
+// - uninitialized_fill_n
 //
 // merge family
 // ------------
@@ -496,6 +502,90 @@ struct __generate_n<__default_backend_tag, _ExecutionPolicy> {
   }
 };
 
+template <class _ExecutionPolicy>
+struct __uninitialized_default_construct<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy, class _ForwardIterator>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last) const noexcept {
+    using _ForEach   = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>;
+    using _ValueType = __iterator_value_type<_ForwardIterator>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEach()(__policy, std::move(__first), std::move(__last), [](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType;
+    });
+  }
+};
+
+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>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
+    using _ForEachN  = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
+    using _ValueType = __iterator_value_type<_ForwardIterator>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEachN()(__policy, std::move(__first), __n, [](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType;
+    });
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __uninitialized_value_construct<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy, class _ForwardIterator>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last) const noexcept {
+    using _ForEach   = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>;
+    using _ValueType = __iterator_value_type<_ForwardIterator>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEach()(__policy, std::move(__first), std::move(__last), [](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType();
+    });
+  }
+};
+
+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>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept {
+    using _ForEachN  = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>;
+    using _ValueType = __iterator_value_type<_ForwardIterator>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEachN()(__policy, std::move(__first), __n, [](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType();
+    });
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __uninitialized_fill<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy, class _ForwardIterator, class _Tp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept {
+    using _ForEach   = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>;
+    using _ValueType = __iterator_value_type<_ForwardIterator>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEach()(__policy, std::move(__first), std::move(__last), [&__value](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType(__value);
+    });
+  }
+};
+
+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>
+  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>;
+    using _Ref       = __iterator_reference<_ForwardIterator>;
+    return _ForEachN()(__policy, std::move(__first), __n, [&__value](_Ref __element) {
+      ::new (static_cast<void*>(std::addressof(__element))) _ValueType(__value);
+    });
+  }
+};
+
 //////////////////////////////////////////////////////////////
 // stable_sort family
 //////////////////////////////////////////////////////////////

diff  --git a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
index 84996de9d9298..89dfbea3a0365 100644
--- a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
@@ -282,4 +282,19 @@ void f(non_forward_iterator non_fwd,
     (void)std::adjacent_
diff erence(
         pol, non_fwd, non_fwd, it, func); // expected-error@*:* {{static assertion failed: adjacent_
diff erence}}
   }
+
+  {
+    std::uninitialized_default_construct(
+        pol, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: uninitialized_default_construct}}
+    std::uninitialized_default_construct_n(
+        pol, non_fwd, n); // expected-error@*:* {{static assertion failed: uninitialized_default_construct_n}}
+    std::uninitialized_value_construct(
+        pol, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: uninitialized_value_construct}}
+    std::uninitialized_value_construct_n(
+        pol, non_fwd, n); // expected-error@*:* {{static assertion failed: uninitialized_value_construct_n}}
+    std::uninitialized_fill(
+        pol, non_fwd, non_fwd, val); // expected-error@*:* {{static assertion failed: uninitialized_fill}}
+    std::uninitialized_fill_n(
+        pol, non_fwd, n, val); // expected-error@*:* {{static assertion failed: uninitialized_fill_n}}
+  }
 }

diff  --git a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
index c63f65572832f..c7e6148ed4822 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -466,6 +466,32 @@ int main(int, char**) {
           (void)std::adjacent_
diff erence(policy, std::move(first1), std::move(last1), std::move(dest), op);
         });
       }
+
+      {
+        // uninitialized_default_construct(first, last)
+        assert_non_throwing([=, &policy] {
+          std::uninitialized_default_construct(policy, std::move(first1), std::move(last1));
+        });
+
+        // uninitialized_default_construct_n(first, n)
+        assert_non_throwing([=, &policy] { std::uninitialized_default_construct_n(policy, std::move(first1), n); });
+
+        // uninitialized_value_construct(first, last)
+        assert_non_throwing([=, &policy] {
+          std::uninitialized_value_construct(policy, std::move(first1), std::move(last1));
+        });
+
+        // uninitialized_value_construct_n(first, n)
+        assert_non_throwing([=, &policy] { std::uninitialized_value_construct_n(policy, std::move(first1), n); });
+
+        // uninitialized_fill(first, last, val)
+        assert_non_throwing([=, &policy] {
+          std::uninitialized_fill(policy, std::move(first1), std::move(last1), val);
+        });
+
+        // uninitialized_fill_n(first, n, val)
+        assert_non_throwing([=, &policy] { std::uninitialized_fill_n(policy, std::move(first1), n, val); });
+      }
     }
   });
 

diff  --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct.pass.cpp
new file mode 100644
index 0000000000000..3d91cd13f1fc7
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator>
+//   void uninitialized_default_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_default_construct);
+
+static_assert(sfinae_test_uninitialized_default_construct<int, int*, int*>);
+static_assert(!sfinae_test_uninitialized_default_construct<std::execution::parallel_policy, int*, int*>);
+
+// Each Counted object has a dedicated external atomic counter.
+// To be able to connect with that counter, each Counted object knows that it is located inside a single pool.
+struct Counted {
+  static std::atomic_int counters[1073];
+  static Counted* pool;
+  std::atomic_int* counter;
+  Counted() : counter(counters + (this - pool)) { counter->fetch_add(1); }
+  Counted(Counted const& other) : counter(other.counter) { counter->fetch_add(1); }
+  ~Counted() { counter->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+std::atomic_int Counted::counters[1073];
+Counted* Counted::pool = nullptr;
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      // Alias the static member variables
+      auto& counters = Counted::counters;
+      Counted*& pool = Counted::pool;
+
+      // Initialize all Counted counters to 0
+      std::fill_n(std::begin(counters), std::size(counters), 0);
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      runway_sample(std::size(counters) + 1, [&](size_t size) {
+        // Default-construct the Counted objects in range [0, size).
+        std::uninitialized_default_construct(policy, Iter(pool), Iter(pool + size));
+        ASSERT_SAME_TYPE(decltype(std::uninitialized_default_construct(policy, Iter(pool), Iter(pool + size))), void);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(pool, pool + size);
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+
+      std::uninitialized_default_construct(policy, Iter(data), Iter(last));
+      // There's nothing we can meaningfully test here, since default-constructing an int is only observable in constexpr contexts,
+      // but still run the algorithm to excercise the runtime.
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}

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
new file mode 100644
index 0000000000000..a6e9c851f8ed5
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/pstl.uninitialized_default_construct_n.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator,
+//           class Size>
+//   void uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_default_construct_n);
+
+static_assert(sfinae_test_uninitialized_default_construct_n<int, int*, int>);
+static_assert(!sfinae_test_uninitialized_default_construct_n<std::execution::parallel_policy, int*, int>);
+
+// Each Counted object has a dedicated external atomic counter.
+// To be able to connect with that counter, each Counted object knows that it is located inside a single pool.
+struct Counted {
+  static std::atomic_int counters[1073];
+  static Counted* pool;
+  std::atomic_int* counter;
+  Counted() : counter(counters + (this - pool)) { counter->fetch_add(1); }
+  Counted(Counted const& other) : counter(other.counter) { counter->fetch_add(1); }
+  ~Counted() { counter->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+std::atomic_int Counted::counters[1073];
+Counted* Counted::pool = nullptr;
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      // Alias the static member variables
+      auto& counters = Counted::counters;
+      Counted*& pool = Counted::pool;
+
+      // Initialize all Counted counters to 0
+      std::fill_n(std::begin(counters), std::size(counters), 0);
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      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);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(pool, pool + size);
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+
+      std::uninitialized_default_construct_n(policy, Iter(data), n);
+      // There's nothing we can meaningfully test here, since default-constructing an int is only observable in constexpr contexts,
+      // but still run the algorithm to excercise the runtime.
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct.pass.cpp
new file mode 100644
index 0000000000000..b8390e6884a92
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct.pass.cpp
@@ -0,0 +1,112 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator>
+//   void uninitialized_value_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_value_construct);
+
+static_assert(sfinae_test_uninitialized_value_construct<int, int*, int*>);
+static_assert(!sfinae_test_uninitialized_value_construct<std::execution::parallel_policy, int*, int*>);
+
+// Each Counted object has a dedicated external atomic counter.
+// To be able to connect with that counter, each Counted object knows that it is located inside a single pool.
+struct Counted {
+  static std::atomic_int counters[1073];
+  static Counted* pool;
+  std::atomic_int* counter;
+  Counted() : counter(counters + (this - pool)) { counter->fetch_add(1); }
+  Counted(Counted const& other) : counter(other.counter) { counter->fetch_add(1); }
+  ~Counted() { counter->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+std::atomic_int Counted::counters[1073];
+Counted* Counted::pool = nullptr;
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      std::atomic_int(&counters)[1073] = Counted::counters;
+      Counted*& pool                   = Counted::pool;
+
+      // initialize all Counted counters to 0
+      std::fill_n(std::begin(counters), std::size(counters), 0);
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      runway_sample(std::size(counters) + 1, [&](size_t size) {
+        // Default-construct the Counted objects in range [0, size).
+        std::uninitialized_value_construct(policy, Iter(pool), Iter(pool + size));
+        ASSERT_SAME_TYPE(decltype(std::uninitialized_value_construct(policy, Iter(pool), Iter(pool + size))), void);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(pool, pool + size);
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+      std::memset(data, 0xFF, n * sizeof(int));
+
+      std::uninitialized_value_construct(policy, Iter(data), Iter(last));
+      for (int i = 0; i != n; ++i) {
+        assert(data[i] == 0);
+      }
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}

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
new file mode 100644
index 0000000000000..859e922c4bfa4
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/pstl.uninitialized_value_construct_n.pass.cpp
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator,
+//           class Size>
+//   void uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_value_construct_n);
+
+static_assert(sfinae_test_uninitialized_value_construct_n<int, int*, int>);
+static_assert(!sfinae_test_uninitialized_value_construct_n<std::execution::parallel_policy, int*, int>);
+
+// Each Counted object has a dedicated external atomic counter.
+// To be able to connect with that counter, each Counted object knows that it is located inside a single pool.
+struct Counted {
+  static std::atomic_int counters[1073];
+  static Counted* pool;
+  std::atomic_int* counter;
+  Counted() : counter(counters + (this - pool)) { counter->fetch_add(1); }
+  Counted(Counted const& other) : counter(other.counter) { counter->fetch_add(1); }
+  ~Counted() { counter->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+std::atomic_int Counted::counters[1073];
+Counted* Counted::pool = nullptr;
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      std::atomic_int(&counters)[1073] = Counted::counters;
+      Counted*& pool                   = Counted::pool;
+
+      // initialize all Counted counters to 0
+      std::fill_n(std::begin(counters), std::size(counters), 0);
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      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);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(pool, pool + size);
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+      std::memset(data, 0xFF, n * sizeof(int));
+
+      std::uninitialized_value_construct_n(policy, Iter(data), n);
+      for (int i = 0; i != n; ++i) {
+        assert(data[i] == 0);
+      }
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}

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
new file mode 100644
index 0000000000000..b25d2a7769c5b
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/pstl.uninitialized_fill_n.pass.cpp
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator,
+//           class Size,
+//           class T>
+//   void uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_fill_n);
+
+static_assert(sfinae_test_uninitialized_fill_n<int, int*, int, int>);
+static_assert(!sfinae_test_uninitialized_fill_n<std::execution::parallel_policy, int*, int, int>);
+
+// Init payload to initialize each Counted object with a pointer to its dedicated counter
+struct CountedInit {
+  struct Counted* first_;
+  std::atomic_int* counters_;
+};
+
+// Each Counted object has a dedicated external atomic counter
+struct Counted {
+  std::atomic_int* counter_;
+  explicit Counted(CountedInit init) : counter_(init.counters_ + (this - init.first_)) { counter_->fetch_add(1); }
+  Counted(Counted const& other) : counter_(other.counter_) { counter_->fetch_add(1); }
+  ~Counted() { counter_->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      // Test uninitialized_fill_n() with a range of Counted objects.
+      // Ranges vary in size from 0 to 1073.
+      // Each object has its own counter.
+      std::atomic_int counters[1073];
+      std::fill_n(std::begin(counters), std::size(counters), 0); // initialize all counters to 0
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      Counted* pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      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);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(Iter(pool), Iter(pool + size));
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+
+      std::uninitialized_fill_n(policy, Iter(data), n, 42);
+      for (int i = 0; i != n; ++i) {
+        assert(data[i] == 42);
+      }
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/pstl.uninitialized_fill.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/pstl.uninitialized_fill.pass.cpp
new file mode 100644
index 0000000000000..ce20e02dc3e5f
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/pstl.uninitialized_fill.pass.cpp
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class ForwardIterator,
+//           class T>
+//   void uninitialized_fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value);
+
+#include <atomic>
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(uninitialized_fill);
+
+static_assert(sfinae_test_uninitialized_fill<int, int*, int*, int>);
+static_assert(!sfinae_test_uninitialized_fill<std::execution::parallel_policy, int*, int*, int>);
+
+// Init payload to initialize each Counted object with a pointer to its dedicated counter
+struct CountedInit {
+  struct Counted* first_;
+  std::atomic_int* counters_;
+};
+
+// Each Counted object has a dedicated external atomic counter
+struct Counted {
+  std::atomic_int* counter_;
+  explicit Counted(CountedInit init) : counter_(init.counters_ + (this - init.first_)) { counter_->fetch_add(1); }
+  Counted(Counted const& other) : counter_(other.counter_) { counter_->fetch_add(1); }
+  ~Counted() { counter_->fetch_sub(1); }
+  friend void operator&(Counted) = delete;
+};
+
+template <class Iter>
+struct TestCounted {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      // Test uninitialized_fill() with a range of Counted objects.
+      // Ranges vary in size from 0 to 1073.
+      // Each object has its own counter.
+      std::atomic_int counters[1073];
+      std::fill_n(std::begin(counters), std::size(counters), 0); // initialize all counters to 0
+
+      // Allocate memory for the Counted objects
+      using Alloc = std::allocator<Counted>;
+      Alloc alloc;
+      Counted* pool = std::allocator_traits<Alloc>::allocate(alloc, std::size(counters));
+
+      runway_sample(std::size(counters) + 1, [&](size_t size) {
+        // Construct the Counted object in range [0, size).
+        std::uninitialized_fill(policy, Iter(pool), Iter(pool + size), CountedInit{pool, counters});
+        ASSERT_SAME_TYPE(
+            decltype(std::uninitialized_fill(policy, Iter(pool), Iter(pool + size), CountedInit{pool, counters})),
+            void);
+
+        // 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; }));
+        assert(std::all_of(std::begin(counters) + size, std::end(counters), [](auto& x) { return x == 0; }));
+
+        // Destroy the constructed objects and verify that all counters are 0.
+        std::destroy(Iter(pool), Iter(pool + size));
+        assert(std::all_of(std::begin(counters), std::end(counters), [](auto& x) { return x == 0; }));
+      });
+
+      std::allocator_traits<Alloc>::deallocate(alloc, pool, std::size(counters));
+    }
+  }
+};
+
+template <class Iter>
+struct TestInt {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      constexpr int n = 1073;
+      std::allocator<int> alloc;
+      int* data = alloc.allocate(n);
+      int* last = data + n;
+
+      std::uninitialized_fill(policy, Iter(data), Iter(last), 42);
+      for (int i = 0; i != n; ++i) {
+        assert(data[i] == 42);
+      }
+
+      std::destroy(data, last);
+      alloc.deallocate(data, n);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<Counted*>{}, TestIteratorWithPolicies<TestCounted>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestInt>{});
+  return 0;
+}


        


More information about the libcxx-commits mailing list