[libcxx-commits] [libcxx] [libc++][test] Refactor tests for std::{copy, move, fill} algorithms (PR #120909)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Sun Feb 9 13:03:40 PST 2025


https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/120909

>From 319d569521ea3f68b2a268814fdea6f6854725a4 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 22 Dec 2024 10:51:48 -0500
Subject: [PATCH 1/2] Refactor tests for std::{copy, move, fill} algorithms

---
 .../alg.copy/common.h                         |  30 +++
 .../alg.copy/copy.pass.cpp                    |  53 +++--
 .../alg.copy/copy_backward.pass.cpp           |  67 +++---
 .../alg.copy/copy_if.pass.cpp                 |  83 +++-----
 .../alg.copy/copy_n.pass.cpp                  | 105 ++++------
 .../alg.copy/pstl.copy.pass.cpp               |   1 +
 .../alg.copy/pstl.copy_n.pass.cpp             |   3 +-
 .../alg.fill/fill.pass.cpp                    |   1 +
 .../alg.fill/fill_n.pass.cpp                  | 190 +++++++++---------
 .../alg.fill/pstl.fill.pass.cpp               |   1 +
 .../alg.fill/pstl.fill_n.pass.cpp             |   1 +
 .../alg.move/move.pass.cpp                    | 109 +++++-----
 .../alg.move/move_backward.pass.cpp           | 118 +++++------
 .../alg.move/pstl.move.pass.cpp               |   1 +
 14 files changed, 352 insertions(+), 411 deletions(-)
 create mode 100644 libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h

diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h
new file mode 100644
index 000000000000000..562ae5121e4287d
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_ALGORITHMS_ALG_MODIFYING_OPERATIONS_ALG_COPY_COMMON_H
+#define TEST_STD_ALGORITHMS_ALG_MODIFYING_OPERATIONS_ALG_COPY_COMMON_H
+
+#include <cstdint>
+#include "test_macros.h"
+
+class PaddedBase {
+public:
+  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
+
+  std::int16_t a_;
+  std::int8_t b_;
+};
+
+class Derived : public PaddedBase {
+public:
+  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+
+  std::int8_t c_;
+};
+
+#endif
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
index 1ca397c92a33436..20aa841e551d5a1 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
@@ -16,23 +16,30 @@
 #include <cassert>
 #include <vector>
 
+#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
-class PaddedBase {
-public:
-  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
-
-  std::int16_t a_;
-  std::int8_t b_;
-};
-
-class Derived : public PaddedBase {
-public:
-  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+TEST_CONSTEXPR_CXX20 void test_padding() {
+  { // Make sure that padding bits aren't copied
+    Derived src(1, 2, 3);
+    Derived dst(4, 5, 6);
+    std::copy(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
+    assert(dst.a_ == 1);
+    assert(dst.b_ == 2);
+    assert(dst.c_ == 6);
+  }
+}
 
-  std::int8_t c_;
-};
+TEST_CONSTEXPR_CXX20 void test_overlapping() {
+  { // Make sure that overlapping ranges can be copied
+    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    std::copy(a + 3, a + 10, a);
+    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
+    assert(std::equal(a, a + 10, expected));
+  }
+}
 
 template <class InIter>
 struct Test {
@@ -81,23 +88,9 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  types::for_each(types::cpp17_input_iterator_list<int*>(), TestInIters());
-
-  { // Make sure that padding bits aren't copied
-    Derived src(1, 2, 3);
-    Derived dst(4, 5, 6);
-    std::copy(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
-    assert(dst.a_ == 1);
-    assert(dst.b_ == 2);
-    assert(dst.c_ == 6);
-  }
-
-  { // Make sure that overlapping ranges can be copied
-    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    std::copy(a + 3, a + 10, a);
-    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
-    assert(std::equal(a, a + 10, expected));
-  }
+  types::for_each(types::cpp17_input_iterator_list<const int*>(), TestInIters());
+  test_padding();
+  test_overlapping();
 
   { // Test vector<bool>::iterator optimization
     assert(test_vector_bool(8));
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
index 445c7718e11115c..f608a1a9ca23e91 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
@@ -17,8 +17,10 @@
 #include <cassert>
 #include <vector>
 
+#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 #include "user_defined_integral.h"
 
 class PaddedBase {
@@ -36,21 +38,29 @@ class Derived : public PaddedBase {
   std::int8_t c_;
 };
 
-template <class InIter, class OutIter>
-TEST_CONSTEXPR_CXX20 void test_copy_backward() {
-  {
-    const unsigned N = 1000;
-    int ia[N]        = {};
-    for (unsigned i = 0; i < N; ++i)
-      ia[i] = i;
-    int ib[N] = {0};
-
-    OutIter r = std::copy_backward(InIter(ia), InIter(ia + N), OutIter(ib + N));
-    assert(base(r) == ib);
-    for (unsigned i = 0; i < N; ++i)
-      assert(ia[i] == ib[i]);
+struct TestIterators {
+  template <class InIter>
+  TEST_CONSTEXPR_CXX20 void operator()() {
+    types::for_each(types::bidirectional_iterator_list<int*>(), TestImpl<InIter>());
   }
-}
+
+  template <class InIter>
+  struct TestImpl {
+    template <class OutIter>
+    TEST_CONSTEXPR_CXX20 void operator()() {
+      const unsigned N = 1000;
+      int ia[N]        = {};
+      for (unsigned i = 0; i < N; ++i)
+        ia[i] = i;
+      int ib[N] = {0};
+
+      OutIter r = std::copy_backward(InIter(ia), InIter(ia + N), OutIter(ib + N));
+      assert(base(r) == ib);
+      for (unsigned i = 0; i < N; ++i)
+        assert(ia[i] == ib[i]);
+    }
+  };
+};
 
 TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
   std::vector<bool> in(N, false);
@@ -70,32 +80,11 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
   }
 
   return true;
-};
+} 
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  test_copy_backward<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_backward<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_backward<bidirectional_iterator<const int*>, int*>();
-
-  test_copy_backward<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_backward<random_access_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_backward<random_access_iterator<const int*>, int*>();
-
-  test_copy_backward<const int*, bidirectional_iterator<int*> >();
-  test_copy_backward<const int*, random_access_iterator<int*> >();
-  test_copy_backward<const int*, int*>();
-
-#if TEST_STD_VER > 17
-  test_copy_backward<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
-  test_copy_backward<contiguous_iterator<const int*>, random_access_iterator<int*>>();
-  test_copy_backward<contiguous_iterator<const int*>, int*>();
-
-  test_copy_backward<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
-  test_copy_backward<random_access_iterator<const int*>, contiguous_iterator<int*>>();
-  test_copy_backward<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
-  test_copy_backward<const int*, contiguous_iterator<int*>>();
-#endif
-
+  types::for_each(types::bidirectional_iterator_list<const int*>(), TestIterators());
+  
   { // Make sure that padding bits aren't copied
     Derived src(1, 2, 3);
     Derived dst(4, 5, 6);
@@ -105,7 +94,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(dst.b_ == 2);
     assert(dst.c_ == 6);
   }
-
+  
   { // Make sure that overlapping ranges can be copied
     int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     std::copy_backward(a, a + 7, a + 10);
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp
index 57214e65455b458..3bee77738e34236 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp
@@ -19,75 +19,48 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
-struct Pred
-{
-    TEST_CONSTEXPR_CXX14 bool operator()(int i) {return i % 3 == 0;}
+struct Pred {
+  TEST_CONSTEXPR_CXX14 bool operator()(int i) { return i % 3 == 0; }
 };
 
-template <class InIter, class OutIter>
-TEST_CONSTEXPR_CXX20 void
-test_copy_if()
-{
+template <class InIter>
+struct TestOutIters {
+  template <class OutIter>
+  TEST_CONSTEXPR_CXX20 void operator()() {
     const unsigned N = 1000;
-    int ia[N] = {};
+    int ia[N]        = {};
     for (unsigned i = 0; i < N; ++i)
-        ia[i] = i;
+      ia[i] = i;
     int ib[N] = {0};
 
-    OutIter r = std::copy_if(InIter(ia), InIter(ia+N), OutIter(ib), Pred());
-    assert(base(r) == ib+N/3+1);
-    for (unsigned i = 0; i < N/3+1; ++i)
-        assert(ib[i] % 3 == 0);
-}
-
-TEST_CONSTEXPR_CXX20 bool
-test()
-{
-    test_copy_if<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
-    test_copy_if<cpp17_input_iterator<const int*>, cpp17_input_iterator<int*> >();
-    test_copy_if<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
-    test_copy_if<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test_copy_if<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
-    test_copy_if<cpp17_input_iterator<const int*>, int*>();
-
-    test_copy_if<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
-    test_copy_if<forward_iterator<const int*>, cpp17_input_iterator<int*> >();
-    test_copy_if<forward_iterator<const int*>, forward_iterator<int*> >();
-    test_copy_if<forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test_copy_if<forward_iterator<const int*>, random_access_iterator<int*> >();
-    test_copy_if<forward_iterator<const int*>, int*>();
-
-    test_copy_if<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
-    test_copy_if<bidirectional_iterator<const int*>, cpp17_input_iterator<int*> >();
-    test_copy_if<bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test_copy_if<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test_copy_if<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test_copy_if<bidirectional_iterator<const int*>, int*>();
-
-    test_copy_if<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
-    test_copy_if<random_access_iterator<const int*>, cpp17_input_iterator<int*> >();
-    test_copy_if<random_access_iterator<const int*>, forward_iterator<int*> >();
-    test_copy_if<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test_copy_if<random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test_copy_if<random_access_iterator<const int*>, int*>();
+    OutIter r = std::copy_if(InIter(ia), InIter(ia + N), OutIter(ib), Pred());
+    assert(base(r) == ib + N / 3 + 1);
+    for (unsigned i = 0; i < N / 3 + 1; ++i)
+      assert(ib[i] % 3 == 0);
+  }
+};
 
-    test_copy_if<const int*, cpp17_output_iterator<int*> >();
-    test_copy_if<const int*, cpp17_input_iterator<int*> >();
-    test_copy_if<const int*, forward_iterator<int*> >();
-    test_copy_if<const int*, bidirectional_iterator<int*> >();
-    test_copy_if<const int*, random_access_iterator<int*> >();
-    test_copy_if<const int*, int*>();
+struct TestInIters {
+  template <class InIter>
+  TEST_CONSTEXPR_CXX20 void operator()() {
+    types::for_each(
+        types::concatenate_t<types::cpp17_input_iterator_list<int*>, types::type_list<cpp17_output_iterator<int*> > >(),
+        TestOutIters<InIter>());
+  }
+};
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  types::for_each(types::cpp17_input_iterator_list<const int*>(), TestInIters());
   return true;
 }
 
-int main(int, char**)
-{
-    test();
+int main(int, char**) {
+  test();
 
 #if TEST_STD_VER > 17
-    static_assert(test());
+  static_assert(test());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
index 889e71f4eceb9b9..2f57f8fe17307e8 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
@@ -16,8 +16,10 @@
 #include <cassert>
 #include <vector>
 
+#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 #include "user_defined_integral.h"
 
 typedef UserDefinedIntegral<unsigned> UDI;
@@ -37,37 +39,31 @@ class Derived : public PaddedBase {
   std::int8_t c_;
 };
 
-template <class InIter, class OutIter>
-TEST_CONSTEXPR_CXX20 void test_copy_n() {
-  {
-    const unsigned N = 1000;
-    int ia[N]        = {};
-    for (unsigned i = 0; i < N; ++i)
-      ia[i] = i;
-    int ib[N] = {0};
-
-    OutIter r = std::copy_n(InIter(ia), UDI(N / 2), OutIter(ib));
-    assert(base(r) == ib + N / 2);
-    for (unsigned i = 0; i < N / 2; ++i)
-      assert(ia[i] == ib[i]);
+struct TestIterators {
+  template <class InIter>
+  TEST_CONSTEXPR_CXX20 void operator()() {
+    types::for_each(
+        types::concatenate_t<types::cpp17_input_iterator_list<int*>, types::type_list<cpp17_output_iterator<int*> > >(),
+        TestImpl<InIter>());
   }
 
-  { // Make sure that padding bits aren't copied
-    Derived src(1, 2, 3);
-    Derived dst(4, 5, 6);
-    std::copy_n(static_cast<PaddedBase*>(&src), 1, static_cast<PaddedBase*>(&dst));
-    assert(dst.a_ == 1);
-    assert(dst.b_ == 2);
-    assert(dst.c_ == 6);
-  }
-
-  { // Make sure that overlapping ranges can be copied
-    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    std::copy_n(a + 3, 7, a);
-    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
-    assert(std::equal(a, a + 10, expected));
-  }
-}
+  template <class InIter>
+  struct TestImpl {
+    template <class OutIter>
+    TEST_CONSTEXPR_CXX20 void operator()() {
+      const unsigned N = 1000;
+      int ia[N]        = {};
+      for (unsigned i = 0; i < N; ++i)
+        ia[i] = i;
+      int ib[N] = {0};
+
+      OutIter r = std::copy_n(InIter(ia), UDI(N / 2), OutIter(ib));
+      assert(base(r) == ib + N / 2);
+      for (unsigned i = 0; i < N / 2; ++i)
+        assert(ia[i] == ib[i]);
+    }
+  };
+};
 
 TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
   std::vector<bool> in(N, false);
@@ -90,40 +86,23 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  test_copy_n<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test_copy_n<cpp17_input_iterator<const int*>, cpp17_input_iterator<int*> >();
-  test_copy_n<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
-  test_copy_n<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_n<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_n<cpp17_input_iterator<const int*>, int*>();
-
-  test_copy_n<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test_copy_n<forward_iterator<const int*>, cpp17_input_iterator<int*> >();
-  test_copy_n<forward_iterator<const int*>, forward_iterator<int*> >();
-  test_copy_n<forward_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_n<forward_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_n<forward_iterator<const int*>, int*>();
-
-  test_copy_n<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test_copy_n<bidirectional_iterator<const int*>, cpp17_input_iterator<int*> >();
-  test_copy_n<bidirectional_iterator<const int*>, forward_iterator<int*> >();
-  test_copy_n<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_n<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_n<bidirectional_iterator<const int*>, int*>();
-
-  test_copy_n<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test_copy_n<random_access_iterator<const int*>, cpp17_input_iterator<int*> >();
-  test_copy_n<random_access_iterator<const int*>, forward_iterator<int*> >();
-  test_copy_n<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-  test_copy_n<random_access_iterator<const int*>, random_access_iterator<int*> >();
-  test_copy_n<random_access_iterator<const int*>, int*>();
-
-  test_copy_n<const int*, cpp17_output_iterator<int*> >();
-  test_copy_n<const int*, cpp17_input_iterator<int*> >();
-  test_copy_n<const int*, forward_iterator<int*> >();
-  test_copy_n<const int*, bidirectional_iterator<int*> >();
-  test_copy_n<const int*, random_access_iterator<int*> >();
-  test_copy_n<const int*, int*>();
+  types::for_each(types::cpp17_input_iterator_list<const int*>(), TestIterators());
+
+  { // Make sure that padding bits aren't copied
+    Derived src(1, 2, 3);
+    Derived dst(4, 5, 6);
+    std::copy_n(static_cast<PaddedBase*>(&src), 1, static_cast<PaddedBase*>(&dst));
+    assert(dst.a_ == 1);
+    assert(dst.b_ == 2);
+    assert(dst.c_ == 6);
+  } 
+
+  { // Make sure that overlapping ranges can be copied
+    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    std::copy_n(a + 3, 7, a);
+    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
+    assert(std::equal(a, a + 10, expected));
+  }
 
   { // Test vector<bool>::iterator optimization
     assert(test_vector_bool(8));
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy.pass.cpp
index bee1ef9bcec3323..6229aac733a9c40 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 EXECUTION_POLICY_SFINAE_TEST(copy);
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy_n.pass.cpp
index 128108ac13811b7..7208be75c70d03e 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/pstl.copy_n.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 EXECUTION_POLICY_SFINAE_TEST(copy_n);
 
@@ -58,7 +59,7 @@ struct TestIteratorsInt {
 };
 
 struct CopiedToTester {
-  bool copied_to = false;
+  bool copied_to   = false;
   CopiedToTester() = default;
   CopiedToTester(const CopiedToTester&) {}
   CopiedToTester& operator=(const CopiedToTester&) {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp
index 7656be73c14c6d6..0e532ae834e7fcc 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp
@@ -22,6 +22,7 @@
 #include "sized_allocator.h"
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 template <class Iter, class Container>
 TEST_CONSTEXPR_CXX20 void
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
index 3b67101a8b29e78..011dfb2c3484eea 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
@@ -14,108 +14,95 @@
 //   fill_n(Iter first, Size n, const T& value);
 
 #include <algorithm>
+#include <array>
 #include <cassert>
+#include <cstddef>
 #include <vector>
 
 #include "sized_allocator.h"
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 #include "user_defined_integral.h"
-
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-  const std::size_t N = 5;
-  int ib[]            = {0, 0, 0, 0, 0, 0}; // one bigger than N
-
-  auto it = std::fill_n(std::begin(ib), N, 5);
-  return it == (std::begin(ib) + N) && std::all_of(std::begin(ib), it, [](int a) { return a == 5; }) &&
-       *it == 0 // don't overwrite the last value in the output array
-      ;
-}
-#endif
-
+ 
 typedef UserDefinedIntegral<unsigned> UDI;
 
-template <class Iter>
-void test_char() {
-  char a[4] = {};
-  Iter it   = std::fill_n(Iter(a), UDI(4), char(1));
-  assert(base(it) == a + 4);
-  assert(a[0] == 1);
-  assert(a[1] == 1);
-  assert(a[2] == 1);
-  assert(a[3] == 1);
+template <class Iter, class Container>
+TEST_CONSTEXPR_CXX20 void
+test(Container& in,
+     typename Container::iterator first,
+     size_t n,
+     typename Container::value_type value,
+     const Container& expected) {
+  Iter it = std::fill_n(Iter(first), UDI(n), value);
+  assert(base(it) == first + n);
+  assert(in == expected);
 }
 
-template <class Iter>
-void test_int() {
-  int a[4] = {};
-  Iter it  = std::fill_n(Iter(a), UDI(4), 1);
-  assert(base(it) == a + 4);
-  assert(a[0] == 1);
-  assert(a[1] == 1);
-  assert(a[2] == 1);
-  assert(a[3] == 1);
-}
+template <class T>
+struct Test {
+  template <class Iter>
+  TEST_CONSTEXPR_CXX20 void operator()() {
+    {
+      std::array<T, 4> in       = {1, 2, 3, 4};
+      std::array<T, 4> expected = {5, 5, 5, 5};
+      test<Iter>(in, in.begin(), 4, 5, expected);
+    }
+    {
+      std::array<T, 4> in       = {1, 2, 3, 4};
+      std::array<T, 4> expected = {1, 5, 5, 4};
+      test<Iter>(in, in.begin() + 1, 2, 5, expected);
+    }
+  }
+};
 
-void test_int_array() {
-  int a[4] = {};
-  assert(std::fill_n(a, UDI(4), static_cast<char>(1)) == a + 4);
-  assert(a[0] == 1);
-  assert(a[1] == 1);
-  assert(a[2] == 1);
-  assert(a[3] == 1);
+TEST_CONSTEXPR void test_int_array() {
+  {
+    int a[4] = {};
+    assert(std::fill_n(a, UDI(4), static_cast<char>(1)) == a + 4);
+    assert(a[0] == 1 && a[1] == 1 && a[2] == 1 && a[3] == 1);
+  }
+  {
+    const std::size_t N = 5;
+    int ib[]            = {0, 0, 0, 0, 0, 0}; // one bigger than N
+
+    auto it = std::fill_n(std::begin(ib), N, 5);
+    assert(it == (std::begin(ib) + N) && std::all_of(std::begin(ib), it, [](int a) { return a == 5; }) &&
+           *it == 0 // don't overwrite the last value in the output array
+    );
+  }
 }
 
 struct source {
-  source() : i(0) {}
-
-  operator int() const { return i++; }
-  mutable int i;
+  TEST_CONSTEXPR source() = default;
+  TEST_CONSTEXPR_CXX20 operator int() const { return 1; }
 };
 
-void test_int_array_struct_source() {
+TEST_CONSTEXPR_CXX20 void test_int_array_struct_source() {
   int a[4] = {};
   assert(std::fill_n(a, UDI(4), source()) == a + 4);
-  assert(a[0] == 0);
+  assert(a[0] == 1);
   assert(a[1] == 1);
-  assert(a[2] == 2);
-  assert(a[3] == 3);
-}
-
-struct test1 {
-  test1() : c(0) {}
-  test1(char xc) : c(xc + 1) {}
-  char c;
-};
-
-void test_struct_array() {
-  test1 test1a[4] = {};
-  assert(std::fill_n(test1a, UDI(4), static_cast<char>(10)) == test1a + 4);
-  assert(test1a[0].c == 11);
-  assert(test1a[1].c == 11);
-  assert(test1a[2].c == 11);
-  assert(test1a[3].c == 11);
+  assert(a[2] == 1);
+  assert(a[3] == 1);
 }
 
 class A {
   char a_;
 
 public:
-  A() {}
-  explicit A(char a) : a_(a) {}
-  operator unsigned char() const { return 'b'; }
+  TEST_CONSTEXPR A() : a_('a') {};
+  TEST_CONSTEXPR explicit A(char a) : a_(a) {}
+  TEST_CONSTEXPR operator unsigned char() const { return 'b'; }
 
-  friend bool operator==(const A& x, const A& y) { return x.a_ == y.a_; }
+  TEST_CONSTEXPR friend bool operator==(const A& x, const A& y) { return x.a_ == y.a_; }
 };
 
-void test5() {
-  A a[3];
-  assert(std::fill_n(&a[0], UDI(3), A('a')) == a + 3);
-  assert(a[0] == A('a'));
-  assert(a[1] == A('a'));
-  assert(a[2] == A('a'));
-}
+struct B {
+  TEST_CONSTEXPR B() : c(0) {}
+  TEST_CONSTEXPR B(char xc) : c(xc + 1) {}
+  char c;
+};
 
 struct Storage {
   union {
@@ -124,11 +111,6 @@ struct Storage {
   };
 };
 
-void test6() {
-  Storage foo[5];
-  std::fill_n(&foo[0], UDI(5), Storage());
-}
-
 // Make sure std::fill_n behaves properly with std::vector<bool> iterators with custom size types.
 // See https://github.com/llvm/llvm-project/pull/122410.
 TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
@@ -162,30 +144,44 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
   }
 }
 
-int main(int, char**) {
-  test_char<cpp17_output_iterator<char*> >();
-  test_char<forward_iterator<char*> >();
-  test_char<bidirectional_iterator<char*> >();
-  test_char<random_access_iterator<char*> >();
-  test_char<char*>();
-
-  test_int<cpp17_output_iterator<int*> >();
-  test_int<forward_iterator<int*> >();
-  test_int<bidirectional_iterator<int*> >();
-  test_int<random_access_iterator<int*> >();
-  test_int<int*>();
+TEST_CONSTEXPR_CXX20 void test_struct_array() {
+  {
+    A a[3];
+    assert(std::fill_n(&a[0], UDI(3), A('a')) == a + 3);
+    assert(a[0] == A('a'));
+    assert(a[1] == A('a'));
+    assert(a[2] == A('a'));
+  }
+  {
+    B test1a[4] = {};
+    assert(std::fill_n(test1a, UDI(4), static_cast<char>(10)) == test1a + 4);
+    assert(test1a[0].c == 11);
+    assert(test1a[1].c == 11);
+    assert(test1a[2].c == 11);
+    assert(test1a[3].c == 11);
+  }
+  {
+    Storage foo[5];
+    std::fill_n(&foo[0], UDI(5), Storage());
+  }
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  types::for_each(types::forward_iterator_list<char*>(), Test<char>());
+  types::for_each(types::forward_iterator_list<int*>(), Test<int>());
 
   test_int_array();
-  test_int_array_struct_source();
   test_struct_array();
-
-  test5();
-  test6();
-
+  test_int_array_struct_source();
   test_bititer_with_custom_sized_types();
 
-#if TEST_STD_VER > 17
-  static_assert(test_constexpr());
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp
index 556326fb0894cab..e456fa8986aad58 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 EXECUTION_POLICY_SFINAE_TEST(fill);
 
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 4abbd6f7a17c3d4..51232dfef160628 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
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 EXECUTION_POLICY_SFINAE_TEST(fill_n);
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
index b1ad6873bc5e5a8..1b85fbbfd7c6dac 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
@@ -22,38 +22,62 @@
 #include <memory>
 
 #include "MoveOnly.h"
+#include "../alg.copy/common.h"
 #include "test_iterators.h"
 #include "test_macros.h"
+#include "type_algorithms.h"
+
+TEST_CONSTEXPR_CXX20 void test_padding() { // Make sure that padding bits aren't copied
+  Derived src(1, 2, 3);
+  Derived dst(4, 5, 6);
+  std::move(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
+  assert(dst.a_ == 1);
+  assert(dst.b_ == 2);
+  assert(dst.c_ == 6);
+}
 
-class PaddedBase {
-public:
-  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
-
-  std::int16_t a_;
-  std::int8_t b_;
-};
-
-class Derived : public PaddedBase {
-public:
-  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+TEST_CONSTEXPR_CXX20 void test_overlapping() { // Make sure that overlapping ranges can be copied
+  int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+  std::move(a + 3, a + 10, a);
+  int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
+  assert(std::equal(a, a + 10, expected));
+}
 
-  std::int8_t c_;
-};
+TEST_CONSTEXPR_CXX20 void test_moveonly() { // Make sure that the algorithm works with move-only types
+  // When non-trivial
+  {
+    MoveOnly from[3] = {1, 2, 3};
+    MoveOnly to[3]   = {};
+    std::move(std::begin(from), std::end(from), std::begin(to));
+    assert(to[0] == MoveOnly(1));
+    assert(to[1] == MoveOnly(2));
+    assert(to[2] == MoveOnly(3));
+  }
+  // When trivial
+  {
+    TrivialMoveOnly from[3] = {1, 2, 3};
+    TrivialMoveOnly to[3]   = {};
+    std::move(std::begin(from), std::end(from), std::begin(to));
+    assert(to[0] == TrivialMoveOnly(1));
+    assert(to[1] == TrivialMoveOnly(2));
+    assert(to[2] == TrivialMoveOnly(3));
+  }
+}
 
 template <class InIter>
 struct Test {
   template <class OutIter>
   TEST_CONSTEXPR_CXX20 void operator()() {
     const unsigned N = 1000;
-    int ia[N] = {};
+    int ia[N]        = {};
     for (unsigned i = 0; i < N; ++i)
-        ia[i] = i;
+      ia[i] = i;
     int ib[N] = {0};
 
-    OutIter r = std::move(InIter(ia), InIter(ia+N), OutIter(ib));
-    assert(base(r) == ib+N);
+    OutIter r = std::move(InIter(ia), InIter(ia + N), OutIter(ib));
+    assert(base(r) == ib + N);
     for (unsigned i = 0; i < N; ++i)
-        assert(ia[i] == ib[i]);
+      assert(ia[i] == ib[i]);
   }
 };
 
@@ -73,13 +97,13 @@ struct Test1 {
     const unsigned N = 100;
     std::unique_ptr<int> ia[N];
     for (unsigned i = 0; i < N; ++i)
-        ia[i].reset(new int(i));
+      ia[i].reset(new int(i));
     std::unique_ptr<int> ib[N];
 
-    OutIter r = std::move(InIter(ia), InIter(ia+N), OutIter(ib));
-    assert(base(r) == ib+N);
+    OutIter r = std::move(InIter(ia), InIter(ia + N), OutIter(ib));
+    assert(base(r) == ib + N);
     for (unsigned i = 0; i < N; ++i)
-        assert(*ib[i] == static_cast<int>(i));
+      assert(*ib[i] == static_cast<int>(i));
   }
 };
 
@@ -96,44 +120,9 @@ TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::cpp17_input_iterator_list<int*>(), TestOutIters());
   if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)
     types::for_each(types::cpp17_input_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
-
-  { // Make sure that padding bits aren't copied
-    Derived src(1, 2, 3);
-    Derived dst(4, 5, 6);
-    std::move(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
-    assert(dst.a_ == 1);
-    assert(dst.b_ == 2);
-    assert(dst.c_ == 6);
-  }
-
-  { // Make sure that overlapping ranges can be copied
-    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    std::move(a + 3, a + 10, a);
-    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
-    assert(std::equal(a, a + 10, expected));
-  }
-
-  // Make sure that the algorithm works with move-only types
-  {
-    // When non-trivial
-    {
-      MoveOnly from[3] = {1, 2, 3};
-      MoveOnly to[3] = {};
-      std::move(std::begin(from), std::end(from), std::begin(to));
-      assert(to[0] == MoveOnly(1));
-      assert(to[1] == MoveOnly(2));
-      assert(to[2] == MoveOnly(3));
-    }
-    // When trivial
-    {
-      TrivialMoveOnly from[3] = {1, 2, 3};
-      TrivialMoveOnly to[3] = {};
-      std::move(std::begin(from), std::end(from), std::begin(to));
-      assert(to[0] == TrivialMoveOnly(1));
-      assert(to[1] == TrivialMoveOnly(2));
-      assert(to[2] == TrivialMoveOnly(3));
-    }
-  }
+  test_padding();
+  test_overlapping();
+  test_moveonly();
 
   return true;
 }
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
index 61dea47b510716b..2c64edb529f7bb9 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
@@ -21,47 +21,70 @@
 #include <memory>
 
 #include "MoveOnly.h"
+#include "../alg.copy/common.h"
 #include "test_iterators.h"
 #include "test_macros.h"
+#include "type_algorithms.h"
+
+TEST_CONSTEXPR_CXX20 void test_padding() { // Make sure that padding bits aren't copied
+  Derived src(1, 2, 3);
+  Derived dst(4, 5, 6);
+  std::move_backward(
+      static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
+  assert(dst.a_ == 1);
+  assert(dst.b_ == 2);
+  assert(dst.c_ == 6);
+}
 
-class PaddedBase {
-public:
-  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
-
-  std::int16_t a_;
-  std::int8_t b_;
-};
-
-class Derived : public PaddedBase {
-public:
-  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+TEST_CONSTEXPR_CXX20 void test_overlapping() { // Make sure that overlapping ranges can be copied
+  int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+  std::move_backward(a, a + 7, a + 10);
+  int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
+  assert(std::equal(a, a + 10, expected));
+}
 
-  std::int8_t c_;
-};
+TEST_CONSTEXPR_CXX20 void test_moveonly() { // Make sure that the algorithm works with move-only types
+  // When non-trivial
+  {
+    MoveOnly from[3] = {1, 2, 3};
+    MoveOnly to[3]   = {};
+    std::move_backward(std::begin(from), std::end(from), std::end(to));
+    assert(to[0] == MoveOnly(1));
+    assert(to[1] == MoveOnly(2));
+    assert(to[2] == MoveOnly(3));
+  }
+  // When trivial
+  {
+    TrivialMoveOnly from[3] = {1, 2, 3};
+    TrivialMoveOnly to[3]   = {};
+    std::move_backward(std::begin(from), std::end(from), std::end(to));
+    assert(to[0] == TrivialMoveOnly(1));
+    assert(to[1] == TrivialMoveOnly(2));
+    assert(to[2] == TrivialMoveOnly(3));
+  }
+}
 
 template <class InIter>
 struct Test {
   template <class OutIter>
   TEST_CONSTEXPR_CXX20 void operator()() {
     const unsigned N = 1000;
-    int ia[N] = {};
+    int ia[N]        = {};
     for (unsigned i = 0; i < N; ++i)
-        ia[i] = i;
+      ia[i] = i;
     int ib[N] = {0};
 
-    OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N));
+    OutIter r = std::move_backward(InIter(ia), InIter(ia + N), OutIter(ib + N));
     assert(base(r) == ib);
     for (unsigned i = 0; i < N; ++i)
-        assert(ia[i] == ib[i]);
+      assert(ia[i] == ib[i]);
   }
 };
 
 struct TestOutIters {
   template <class InIter>
   TEST_CONSTEXPR_CXX20 void operator()() {
-    types::for_each(
-        types::concatenate_t<types::bidirectional_iterator_list<int*> >(),
-        Test<InIter>());
+    types::for_each(types::concatenate_t<types::bidirectional_iterator_list<int*> >(), Test<InIter>());
   }
 };
 
@@ -72,21 +95,21 @@ struct Test1 {
     const unsigned N = 100;
     std::unique_ptr<int> ia[N];
     for (unsigned i = 0; i < N; ++i)
-        ia[i].reset(new int(i));
+      ia[i].reset(new int(i));
     std::unique_ptr<int> ib[N];
 
-    OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N));
+    OutIter r = std::move_backward(InIter(ia), InIter(ia + N), OutIter(ib + N));
     assert(base(r) == ib);
     for (unsigned i = 0; i < N; ++i)
-        assert(*ib[i] == static_cast<int>(i));
+      assert(*ib[i] == static_cast<int>(i));
   }
 };
 
 struct Test1OutIters {
   template <class InIter>
   TEST_CONSTEXPR_CXX23 void operator()() {
-    types::for_each(types::concatenate_t<types::bidirectional_iterator_list<std::unique_ptr<int>*> >(),
-                    Test1<InIter>());
+    types::for_each(
+        types::concatenate_t<types::bidirectional_iterator_list<std::unique_ptr<int>*> >(), Test1<InIter>());
   }
 };
 
@@ -94,51 +117,14 @@ TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::bidirectional_iterator_list<int*>(), TestOutIters());
   if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)
     types::for_each(types::bidirectional_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
-
-  { // Make sure that padding bits aren't copied
-    Derived src(1, 2, 3);
-    Derived dst(4, 5, 6);
-    std::move_backward(
-        static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
-    assert(dst.a_ == 1);
-    assert(dst.b_ == 2);
-    assert(dst.c_ == 6);
-  }
-
-  { // Make sure that overlapping ranges can be copied
-    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    std::move_backward(a, a + 7, a + 10);
-    int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
-    assert(std::equal(a, a + 10, expected));
-  }
-
-  // Make sure that the algorithm works with move-only types
-  {
-    // When non-trivial
-    {
-      MoveOnly from[3] = {1, 2, 3};
-      MoveOnly to[3] = {};
-      std::move_backward(std::begin(from), std::end(from), std::end(to));
-      assert(to[0] == MoveOnly(1));
-      assert(to[1] == MoveOnly(2));
-      assert(to[2] == MoveOnly(3));
-    }
-    // When trivial
-    {
-      TrivialMoveOnly from[3] = {1, 2, 3};
-      TrivialMoveOnly to[3] = {};
-      std::move_backward(std::begin(from), std::end(from), std::end(to));
-      assert(to[0] == TrivialMoveOnly(1));
-      assert(to[1] == TrivialMoveOnly(2));
-      assert(to[2] == TrivialMoveOnly(3));
-    }
-  }
+  test_padding();
+  test_overlapping();
+  test_moveonly();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER >= 20
   static_assert(test());
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/pstl.move.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/pstl.move.pass.cpp
index e4cc5649ce5d815..a82a068caf0319f 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/pstl.move.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/pstl.move.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 EXECUTION_POLICY_SFINAE_TEST(move);
 

>From b467191688efea48b2da8543f9b664e0870ada7c Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 22 Dec 2024 13:45:23 -0500
Subject: [PATCH 2/2] Apply philnik777's suggestions

---
 .../alg.copy/common.h                         | 30 -------
 .../alg.copy/copy.pass.cpp                    | 49 ++++++-----
 .../alg.copy/copy_backward.pass.cpp           |  7 +-
 .../alg.copy/copy_n.pass.cpp                  |  3 +-
 .../alg.copy/ranges.copy_n.pass.cpp           | 39 ++-------
 .../alg.fill/fill_n.pass.cpp                  | 32 ++++---
 .../alg.move/move.pass.cpp                    | 84 ++++++++++--------
 .../alg.move/move_backward.pass.cpp           | 86 ++++++++++---------
 8 files changed, 147 insertions(+), 183 deletions(-)
 delete mode 100644 libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h

diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h
deleted file mode 100644
index 562ae5121e4287d..000000000000000
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/common.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TEST_STD_ALGORITHMS_ALG_MODIFYING_OPERATIONS_ALG_COPY_COMMON_H
-#define TEST_STD_ALGORITHMS_ALG_MODIFYING_OPERATIONS_ALG_COPY_COMMON_H
-
-#include <cstdint>
-#include "test_macros.h"
-
-class PaddedBase {
-public:
-  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
-
-  std::int16_t a_;
-  std::int8_t b_;
-};
-
-class Derived : public PaddedBase {
-public:
-  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
-
-  std::int8_t c_;
-};
-
-#endif
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
index 20aa841e551d5a1..3d4ee23a5a7ffd7 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
@@ -16,30 +16,24 @@
 #include <cassert>
 #include <vector>
 
-#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "type_algorithms.h"
 
-TEST_CONSTEXPR_CXX20 void test_padding() {
-  { // Make sure that padding bits aren't copied
-    Derived src(1, 2, 3);
-    Derived dst(4, 5, 6);
-    std::copy(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
-    assert(dst.a_ == 1);
-    assert(dst.b_ == 2);
-    assert(dst.c_ == 6);
-  }
-}
+class PaddedBase {
+public:
+  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
 
-TEST_CONSTEXPR_CXX20 void test_overlapping() {
-  { // Make sure that overlapping ranges can be copied
-    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    std::copy(a + 3, a + 10, a);
-    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
-    assert(std::equal(a, a + 10, expected));
-  }
-}
+  std::int16_t a_;
+  std::int8_t b_;
+};
+
+class Derived : public PaddedBase {
+public:
+  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+
+  std::int8_t c_;
+};
 
 template <class InIter>
 struct Test {
@@ -89,8 +83,21 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
 
 TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::cpp17_input_iterator_list<const int*>(), TestInIters());
-  test_padding();
-  test_overlapping();
+
+  { // Make sure that padding bits aren't copied
+    Derived src(1, 2, 3);
+    Derived dst(4, 5, 6);
+    std::copy(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
+    assert(dst.a_ == 1);
+    assert(dst.b_ == 2);
+    assert(dst.c_ == 6);
+  }
+  { // Make sure that overlapping ranges can be copied
+    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    std::copy(a + 3, a + 10, a);
+    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
+    assert(std::equal(a, a + 10, expected));
+  }
 
   { // Test vector<bool>::iterator optimization
     assert(test_vector_bool(8));
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
index f608a1a9ca23e91..8a528a96f52942b 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
@@ -17,7 +17,6 @@
 #include <cassert>
 #include <vector>
 
-#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "type_algorithms.h"
@@ -80,11 +79,11 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
   }
 
   return true;
-} 
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::bidirectional_iterator_list<const int*>(), TestIterators());
-  
+
   { // Make sure that padding bits aren't copied
     Derived src(1, 2, 3);
     Derived dst(4, 5, 6);
@@ -94,7 +93,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(dst.b_ == 2);
     assert(dst.c_ == 6);
   }
-  
+
   { // Make sure that overlapping ranges can be copied
     int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     std::copy_backward(a, a + 7, a + 10);
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
index 2f57f8fe17307e8..2053134a01a2f52 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
@@ -16,7 +16,6 @@
 #include <cassert>
 #include <vector>
 
-#include "common.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "type_algorithms.h"
@@ -95,7 +94,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(dst.a_ == 1);
     assert(dst.b_ == 2);
     assert(dst.c_ == 6);
-  } 
+  }
 
   { // Make sure that overlapping ranges can be copied
     int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_n.pass.cpp
index c7031f63a02f6d4..577328d663d9fc0 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_n.pass.cpp
@@ -40,7 +40,7 @@ static_assert(!HasCopyNIt<int*, int*, SentinelForNotWeaklyEqualityComparableWith
 
 static_assert(std::is_same_v<std::ranges::copy_result<int, long>, std::ranges::in_out_result<int, long>>);
 
-template <class In, class Out, class Sent = In>
+template <class In, class Out>
 constexpr void test_iterators() {
   { // simple test
     std::array in{1, 2, 3, 4};
@@ -61,26 +61,6 @@ constexpr void test_iterators() {
   }
 }
 
-template <class Out>
-constexpr void test_in_iterators() {
-  test_iterators<cpp20_input_iterator<int*>, Out, sentinel_wrapper<cpp20_input_iterator<int*>>>();
-  test_iterators<forward_iterator<int*>, Out>();
-  test_iterators<bidirectional_iterator<int*>, Out>();
-  test_iterators<random_access_iterator<int*>, Out>();
-  test_iterators<contiguous_iterator<int*>, Out>();
-}
-
-template <class Out>
-constexpr void test_proxy_in_iterators() {
-  test_iterators<ProxyIterator<cpp20_input_iterator<int*>>,
-                 Out,
-                 sentinel_wrapper<ProxyIterator<cpp20_input_iterator<int*>>>>();
-  test_iterators<ProxyIterator<forward_iterator<int*>>, Out>();
-  test_iterators<ProxyIterator<bidirectional_iterator<int*>>, Out>();
-  test_iterators<ProxyIterator<random_access_iterator<int*>>, Out>();
-  test_iterators<ProxyIterator<contiguous_iterator<int*>>, Out>();
-}
-
 #if TEST_STD_VER >= 23
 constexpr bool test_vector_bool(std::size_t N) {
   std::vector<bool> in(N, false);
@@ -104,17 +84,12 @@ constexpr bool test_vector_bool(std::size_t N) {
 #endif
 
 constexpr bool test() {
-  test_in_iterators<cpp20_input_iterator<int*>>();
-  test_in_iterators<forward_iterator<int*>>();
-  test_in_iterators<bidirectional_iterator<int*>>();
-  test_in_iterators<random_access_iterator<int*>>();
-  test_in_iterators<contiguous_iterator<int*>>();
-
-  test_proxy_in_iterators<ProxyIterator<cpp20_input_iterator<int*>>>();
-  test_proxy_in_iterators<ProxyIterator<forward_iterator<int*>>>();
-  test_proxy_in_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
-  test_proxy_in_iterators<ProxyIterator<random_access_iterator<int*>>>();
-  test_proxy_in_iterators<ProxyIterator<contiguous_iterator<int*>>>();
+  types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Out>() {
+    types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class In>() {
+      test_iterators<In, Out>();
+      test_iterators<ProxyIterator<In>, ProxyIterator<Out>>();
+    });
+  });
 
   { // check that every element is copied exactly once
     struct CopyOnce {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
index 011dfb2c3484eea..98c412fb6cdc02a 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
@@ -24,18 +24,14 @@
 #include "test_iterators.h"
 #include "type_algorithms.h"
 #include "user_defined_integral.h"
- 
+
 typedef UserDefinedIntegral<unsigned> UDI;
 
 template <class Iter, class Container>
 TEST_CONSTEXPR_CXX20 void
-test(Container& in,
-     typename Container::iterator first,
-     size_t n,
-     typename Container::value_type value,
-     const Container& expected) {
-  Iter it = std::fill_n(Iter(first), UDI(n), value);
-  assert(base(it) == first + n);
+test(Container in, size_t from, size_t n, typename Container::value_type value, Container expected) {
+  Iter it = std::fill_n(Iter(in.data() + from), UDI(n), value);
+  assert(base(it) == in.data() + from + n);
   assert(in == expected);
 }
 
@@ -46,22 +42,23 @@ struct Test {
     {
       std::array<T, 4> in       = {1, 2, 3, 4};
       std::array<T, 4> expected = {5, 5, 5, 5};
-      test<Iter>(in, in.begin(), 4, 5, expected);
+      test<Iter>(in, 0, 4, 5, expected);
     }
     {
       std::array<T, 4> in       = {1, 2, 3, 4};
       std::array<T, 4> expected = {1, 5, 5, 4};
-      test<Iter>(in, in.begin() + 1, 2, 5, expected);
+      test<Iter>(in, 1, 2, 5, expected);
     }
   }
 };
 
-TEST_CONSTEXPR void test_int_array() {
+TEST_CONSTEXPR_CXX20 void test_int_array() {
   {
     int a[4] = {};
     assert(std::fill_n(a, UDI(4), static_cast<char>(1)) == a + 4);
     assert(a[0] == 1 && a[1] == 1 && a[2] == 1 && a[3] == 1);
   }
+#if TEST_STD_VER >= 11
   {
     const std::size_t N = 5;
     int ib[]            = {0, 0, 0, 0, 0, 0}; // one bigger than N
@@ -71,6 +68,7 @@ TEST_CONSTEXPR void test_int_array() {
            *it == 0 // don't overwrite the last value in the output array
     );
   }
+#endif
 }
 
 struct source {
@@ -153,12 +151,12 @@ TEST_CONSTEXPR_CXX20 void test_struct_array() {
     assert(a[2] == A('a'));
   }
   {
-    B test1a[4] = {};
-    assert(std::fill_n(test1a, UDI(4), static_cast<char>(10)) == test1a + 4);
-    assert(test1a[0].c == 11);
-    assert(test1a[1].c == 11);
-    assert(test1a[2].c == 11);
-    assert(test1a[3].c == 11);
+    B b[4] = {};
+    assert(std::fill_n(b, UDI(4), static_cast<char>(10)) == b + 4);
+    assert(b[0].c == 11);
+    assert(b[1].c == 11);
+    assert(b[2].c == 11);
+    assert(b[3].c == 11);
   }
   {
     Storage foo[5];
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
index 1b85fbbfd7c6dac..5324a327b50bcba 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
@@ -22,47 +22,24 @@
 #include <memory>
 
 #include "MoveOnly.h"
-#include "../alg.copy/common.h"
 #include "test_iterators.h"
 #include "test_macros.h"
 #include "type_algorithms.h"
 
-TEST_CONSTEXPR_CXX20 void test_padding() { // Make sure that padding bits aren't copied
-  Derived src(1, 2, 3);
-  Derived dst(4, 5, 6);
-  std::move(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
-  assert(dst.a_ == 1);
-  assert(dst.b_ == 2);
-  assert(dst.c_ == 6);
-}
+class PaddedBase {
+public:
+  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
 
-TEST_CONSTEXPR_CXX20 void test_overlapping() { // Make sure that overlapping ranges can be copied
-  int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-  std::move(a + 3, a + 10, a);
-  int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
-  assert(std::equal(a, a + 10, expected));
-}
+  std::int16_t a_;
+  std::int8_t b_;
+};
 
-TEST_CONSTEXPR_CXX20 void test_moveonly() { // Make sure that the algorithm works with move-only types
-  // When non-trivial
-  {
-    MoveOnly from[3] = {1, 2, 3};
-    MoveOnly to[3]   = {};
-    std::move(std::begin(from), std::end(from), std::begin(to));
-    assert(to[0] == MoveOnly(1));
-    assert(to[1] == MoveOnly(2));
-    assert(to[2] == MoveOnly(3));
-  }
-  // When trivial
-  {
-    TrivialMoveOnly from[3] = {1, 2, 3};
-    TrivialMoveOnly to[3]   = {};
-    std::move(std::begin(from), std::end(from), std::begin(to));
-    assert(to[0] == TrivialMoveOnly(1));
-    assert(to[1] == TrivialMoveOnly(2));
-    assert(to[2] == TrivialMoveOnly(3));
-  }
-}
+class Derived : public PaddedBase {
+public:
+  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+
+  std::int8_t c_;
+};
 
 template <class InIter>
 struct Test {
@@ -120,9 +97,40 @@ TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::cpp17_input_iterator_list<int*>(), TestOutIters());
   if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)
     types::for_each(types::cpp17_input_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
-  test_padding();
-  test_overlapping();
-  test_moveonly();
+  { // Make sure that padding bits aren't copied
+    Derived src(1, 2, 3);
+    Derived dst(4, 5, 6);
+    std::move(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
+    assert(dst.a_ == 1);
+    assert(dst.b_ == 2);
+    assert(dst.c_ == 6);
+  }
+  { // Make sure that overlapping ranges can be copied
+    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    std::move(a + 3, a + 10, a);
+    int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
+    assert(std::equal(a, a + 10, expected));
+  }
+  { // Make sure that the algorithm works with move-only types
+    // When non-trivial
+    {
+      MoveOnly from[3] = {1, 2, 3};
+      MoveOnly to[3]   = {};
+      std::move(std::begin(from), std::end(from), std::begin(to));
+      assert(to[0] == MoveOnly(1));
+      assert(to[1] == MoveOnly(2));
+      assert(to[2] == MoveOnly(3));
+    }
+    // When trivial
+    {
+      TrivialMoveOnly from[3] = {1, 2, 3};
+      TrivialMoveOnly to[3]   = {};
+      std::move(std::begin(from), std::end(from), std::begin(to));
+      assert(to[0] == TrivialMoveOnly(1));
+      assert(to[1] == TrivialMoveOnly(2));
+      assert(to[2] == TrivialMoveOnly(3));
+    }
+  }
 
   return true;
 }
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
index 2c64edb529f7bb9..d166c854f30aaf0 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
@@ -21,48 +21,24 @@
 #include <memory>
 
 #include "MoveOnly.h"
-#include "../alg.copy/common.h"
 #include "test_iterators.h"
 #include "test_macros.h"
 #include "type_algorithms.h"
 
-TEST_CONSTEXPR_CXX20 void test_padding() { // Make sure that padding bits aren't copied
-  Derived src(1, 2, 3);
-  Derived dst(4, 5, 6);
-  std::move_backward(
-      static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
-  assert(dst.a_ == 1);
-  assert(dst.b_ == 2);
-  assert(dst.c_ == 6);
-}
+class PaddedBase {
+public:
+  TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
 
-TEST_CONSTEXPR_CXX20 void test_overlapping() { // Make sure that overlapping ranges can be copied
-  int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-  std::move_backward(a, a + 7, a + 10);
-  int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
-  assert(std::equal(a, a + 10, expected));
-}
+  std::int16_t a_;
+  std::int8_t b_;
+};
 
-TEST_CONSTEXPR_CXX20 void test_moveonly() { // Make sure that the algorithm works with move-only types
-  // When non-trivial
-  {
-    MoveOnly from[3] = {1, 2, 3};
-    MoveOnly to[3]   = {};
-    std::move_backward(std::begin(from), std::end(from), std::end(to));
-    assert(to[0] == MoveOnly(1));
-    assert(to[1] == MoveOnly(2));
-    assert(to[2] == MoveOnly(3));
-  }
-  // When trivial
-  {
-    TrivialMoveOnly from[3] = {1, 2, 3};
-    TrivialMoveOnly to[3]   = {};
-    std::move_backward(std::begin(from), std::end(from), std::end(to));
-    assert(to[0] == TrivialMoveOnly(1));
-    assert(to[1] == TrivialMoveOnly(2));
-    assert(to[2] == TrivialMoveOnly(3));
-  }
-}
+class Derived : public PaddedBase {
+public:
+  TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
+
+  std::int8_t c_;
+};
 
 template <class InIter>
 struct Test {
@@ -117,9 +93,41 @@ TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::bidirectional_iterator_list<int*>(), TestOutIters());
   if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)
     types::for_each(types::bidirectional_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
-  test_padding();
-  test_overlapping();
-  test_moveonly();
+  { // Make sure that padding bits aren't copied
+    Derived src(1, 2, 3);
+    Derived dst(4, 5, 6);
+    std::move_backward(
+        static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
+    assert(dst.a_ == 1);
+    assert(dst.b_ == 2);
+    assert(dst.c_ == 6);
+  }
+  { // Make sure that overlapping ranges can be copied
+    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    std::move_backward(a, a + 7, a + 10);
+    int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
+    assert(std::equal(a, a + 10, expected));
+  }
+  { // Make sure that the algorithm works with move-only types
+    // When non-trivial
+    {
+      MoveOnly from[3] = {1, 2, 3};
+      MoveOnly to[3]   = {};
+      std::move_backward(std::begin(from), std::end(from), std::end(to));
+      assert(to[0] == MoveOnly(1));
+      assert(to[1] == MoveOnly(2));
+      assert(to[2] == MoveOnly(3));
+    }
+    // When trivial
+    {
+      TrivialMoveOnly from[3] = {1, 2, 3};
+      TrivialMoveOnly to[3]   = {};
+      std::move_backward(std::begin(from), std::end(from), std::end(to));
+      assert(to[0] == TrivialMoveOnly(1));
+      assert(to[1] == TrivialMoveOnly(2));
+      assert(to[2] == TrivialMoveOnly(3));
+    }
+  }
 
   return true;
 }



More information about the libcxx-commits mailing list