[libcxx-commits] [libcxx] [libc++][test] Refactor tests for rotate and rotate_copy (PR #126458)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 21 08:59:21 PST 2025


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

>From 11713920df794ed9c59be9dbc0946e70c59d0f3f Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 9 Feb 2025 22:49:18 -0500
Subject: [PATCH 1/2] Refactor tests for rotate and rotate_copy

---
 .../alg.rotate/pstl.rotate_copy.pass.cpp      |   1 +
 .../alg.rotate/ranges.rotate_copy.pass.cpp    |  43 +--
 .../alg.rotate/ranges_rotate.pass.cpp         |  60 ++--
 .../alg.rotate/rotate.pass.cpp                | 303 +++++++++---------
 .../alg.rotate/rotate_copy.pass.cpp           | 247 +++++++-------
 libcxx/test/support/test_iterators.h          |   7 +
 6 files changed, 319 insertions(+), 342 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/pstl.rotate_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/pstl.rotate_copy.pass.cpp
index 989313cc6d68d..5d1e34150c472 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/pstl.rotate_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/pstl.rotate_copy.pass.cpp
@@ -27,6 +27,7 @@
 #include "test_macros.h"
 #include "test_execution_policies.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 template <class Iter>
 struct Test {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
index 58b0f75d9b5f2..35856a65cc703 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
@@ -26,9 +26,11 @@
 
 #include "almost_satisfies_types.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 template <class Iter, class Out = int*, class Sent = sentinel_wrapper<Iter>>
-concept HasRotateCopyIt = requires(Iter first, Sent last, Out out) { std::ranges::rotate_copy(first, first, last, out); };
+concept HasRotateCopyIt =
+    requires(Iter first, Sent last, Out out) { std::ranges::rotate_copy(first, first, last, out); };
 
 template <class Range, class Out = int*>
 concept HasRotateCopyR = requires(Range range, Out out) { std::ranges::rotate_copy(range, nullptr, out); };
@@ -54,11 +56,8 @@ template <class Iter, class OutIter, class Sent, int N>
 constexpr void test(std::array<int, N> value, std::size_t middle, std::array<int, N> expected) {
   {
     std::array<int, N> out;
-    std::same_as<std::ranges::in_out_result<Iter, OutIter>> decltype(auto) ret =
-        std::ranges::rotate_copy(Iter(value.data()),
-                                 Iter(value.data() + middle),
-                                 Sent(Iter(value.data() + value.size())),
-                                 OutIter(out.data()));
+    std::same_as<std::ranges::in_out_result<Iter, OutIter>> decltype(auto) ret = std::ranges::rotate_copy(
+        Iter(value.data()), Iter(value.data() + middle), Sent(Iter(value.data() + value.size())), OutIter(out.data()));
     assert(base(ret.in) == value.data() + value.size());
     assert(base(ret.out) == out.data() + out.size());
     assert(out == expected);
@@ -74,7 +73,7 @@ constexpr void test(std::array<int, N> value, std::size_t middle, std::array<int
   }
 }
 
-template <class Iter, class OutIter, class Sent>
+template <class Iter, class OutIter, class Sent = Iter>
 constexpr void test_iterators() {
   // simple test
   test<Iter, OutIter, Sent, 4>({1, 2, 3, 4}, 2, {3, 4, 1, 2});
@@ -101,41 +100,33 @@ constexpr void test_iterators() {
   test<Iter, OutIter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 7, {1, 2, 3, 4, 5, 6, 7});
 }
 
-template <class Iter, class Sent = Iter>
-constexpr void test_out_iterators() {
-  test_iterators<Iter, cpp20_output_iterator<int*>, Sent>();
-  test_iterators<Iter, forward_iterator<int*>, Sent>();
-  test_iterators<Iter, bidirectional_iterator<int*>, Sent>();
-  test_iterators<Iter, random_access_iterator<int*>, Sent>();
-  test_iterators<Iter, contiguous_iterator<int*>, Sent>();
-  test_iterators<Iter, int*, Sent>();
-}
-
 constexpr bool test() {
-  test_out_iterators<forward_iterator<int*>>();
-  test_out_iterators<bidirectional_iterator<int*>>();
-  test_out_iterators<random_access_iterator<int*>>();
-  test_out_iterators<contiguous_iterator<int*>>();
-  test_out_iterators<int*>();
-  test_out_iterators<const int*>();
+  types::for_each(types::forward_iterator_list<int*>(), []<class Iter>() {
+    types::for_each(types::cpp20_output_iterator_list<int*>(), []<class OutIter>() {
+      test_iterators<Iter, OutIter>();
+    });
+  });
 
   {
     struct AssignmentCounter {
       int* counter;
 
       constexpr AssignmentCounter(int* counter_) : counter(counter_) {}
-      constexpr AssignmentCounter& operator=(const AssignmentCounter&) { ++*counter; return *this; }
+      constexpr AssignmentCounter& operator=(const AssignmentCounter&) {
+        ++*counter;
+        return *this;
+      }
     };
 
     {
-      int c = 0;
+      int c                 = 0;
       AssignmentCounter a[] = {&c, &c, &c, &c};
       AssignmentCounter b[] = {&c, &c, &c, &c};
       std::ranges::rotate_copy(a, a + 2, a + 4, b);
       assert(c == 4);
     }
     {
-      int c = 0;
+      int c                 = 0;
       AssignmentCounter a[] = {&c, &c, &c, &c};
       AssignmentCounter b[] = {&c, &c, &c, &c};
       std::ranges::rotate_copy(a, a + 2, b);
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges_rotate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges_rotate.pass.cpp
index 1506ce79b5dbd..56d0dfaf9ee27 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges_rotate.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges_rotate.pass.cpp
@@ -24,15 +24,15 @@
 
 #include "almost_satisfies_types.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
 // Test constraints of the (iterator, sentinel) overload.
 // ======================================================
 
 template <class Iter = int*, class Sent = int*>
-concept HasRotateIter =
-    requires(Iter&& iter, Sent&& sent) {
-      std::ranges::rotate(std::forward<Iter>(iter), std::forward<Iter>(iter), std::forward<Sent>(sent));
-    };
+concept HasRotateIter = requires(Iter&& iter, Sent&& sent) {
+  std::ranges::rotate(std::forward<Iter>(iter), std::forward<Iter>(iter), std::forward<Sent>(sent));
+};
 
 static_assert(HasRotateIter<int*, int*>);
 
@@ -48,10 +48,9 @@ static_assert(!HasRotateIter<int*, SentinelForNotWeaklyEqualityComparableWith>);
 // =========================================
 
 template <class Range>
-concept HasRotateRange =
-    requires(Range&& range, std::ranges::iterator_t<Range> iter) {
-      std::ranges::rotate(std::forward<Range>(range), iter);
-    };
+concept HasRotateRange = requires(Range&& range, std::ranges::iterator_t<Range> iter) {
+  std::ranges::rotate(std::forward<Range>(range), iter);
+};
 
 template <class T>
 using R = UncheckedRange<T>;
@@ -73,10 +72,10 @@ constexpr void test_one(const std::array<int, N> input, std::size_t mid_index, s
   assert(mid_index <= N);
 
   { // (iterator, sentinel) overload.
-    auto in = input;
+    auto in    = input;
     auto begin = Iter(in.data());
-    auto mid = Iter(in.data() + mid_index);
-    auto end = Sent(Iter(in.data() + in.size()));
+    auto mid   = Iter(in.data() + mid_index);
+    auto end   = Sent(Iter(in.data() + in.size()));
 
     std::same_as<std::ranges::subrange<Iter>> decltype(auto) result = std::ranges::rotate(begin, mid, end);
     assert(base(result.begin()) == in.data() + in.size() - mid_index);
@@ -85,10 +84,10 @@ constexpr void test_one(const std::array<int, N> input, std::size_t mid_index, s
   }
 
   { // (range) overload.
-    auto in = input;
+    auto in    = input;
     auto begin = Iter(in.data());
-    auto mid = Iter(in.data() + mid_index);
-    auto end = Sent(Iter(in.data() + in.size()));
+    auto mid   = Iter(in.data() + mid_index);
+    auto end   = Sent(Iter(in.data() + in.size()));
     auto range = std::ranges::subrange(std::move(begin), std::move(end));
 
     std::same_as<std::ranges::subrange<Iter>> decltype(auto) result = std::ranges::rotate(range, mid);
@@ -132,32 +131,21 @@ constexpr void test_iter_sent() {
   test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 7, {1, 2, 3, 4, 5, 6, 7});
 }
 
-template <class Iter>
-constexpr void test_iter() {
-  test_iter_sent<Iter, Iter>();
-  test_iter_sent<Iter, sentinel_wrapper<Iter>>();
-}
-
-constexpr void test_iterators() {
-  test_iter<forward_iterator<int*>>();
-  test_iter<bidirectional_iterator<int*>>();
-  test_iter<random_access_iterator<int*>>();
-  test_iter<contiguous_iterator<int*>>();
-  test_iter<int*>();
-}
-
 constexpr bool test() {
-  test_iterators();
+  types::for_each(types::forward_iterator_list<int*>(), []<class Iter>() {
+    test_iter_sent<Iter, Iter>();
+    test_iter_sent<Iter, sentinel_wrapper<Iter>>();
+  });
 
   { // Complexity: at most `last - first` swaps.
     const std::array input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    auto expected = static_cast<int>(input.size());
+    auto expected          = static_cast<int>(input.size());
 
     {
-      auto in = input;
-      int swaps = 0;
+      auto in    = input;
+      int swaps  = 0;
       auto begin = adl::Iterator::TrackSwaps(in.data(), swaps);
-      auto end = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps);
+      auto end   = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps);
 
       for (std::size_t mid = 0; mid != input.size(); ++mid) {
         std::ranges::rotate(begin, begin + mid, end);
@@ -166,10 +154,10 @@ constexpr bool test() {
     }
 
     {
-      auto in = input;
-      int swaps = 0;
+      auto in    = input;
+      int swaps  = 0;
       auto begin = adl::Iterator::TrackSwaps(in.data(), swaps);
-      auto end = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps);
+      auto end   = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps);
       auto range = std::ranges::subrange(begin, end);
 
       for (std::size_t mid = 0; mid != input.size(); ++mid) {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
index 7bbf3abd43dc5..91a74786216ec 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
@@ -9,141 +9,141 @@
 // <algorithm>
 
 // template<ShuffleIterator Iter>
-//   Iter
-//   rotate(Iter first, Iter middle, Iter last);
+//   Iter rotate(Iter first, Iter middle, Iter last); // constexpr since C++20
 
 #include <algorithm>
 #include <cassert>
 #include <memory>
+#include <type_traits>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
-template <class Iter>
-TEST_CONSTEXPR_CXX17 bool
-test()
-{
-    int ia[] = {0};
-    const int sa = static_cast<int>(sizeof(ia)/sizeof(ia[0]));
-    Iter r = std::rotate(Iter(ia), Iter(ia), Iter(ia));
+struct TestIter {
+  template <class Iter>
+  TEST_CONSTEXPR_CXX20 void operator()() const {
+    int ia[]     = {0};
+    const int sa = static_cast<int>(sizeof(ia) / sizeof(ia[0]));
+    Iter r       = std::rotate(Iter(ia), Iter(ia), Iter(ia));
     assert(base(r) == ia);
     assert(ia[0] == 0);
-    r = std::rotate(Iter(ia), Iter(ia), Iter(ia+sa));
-    assert(base(r) == ia+sa);
+    r = std::rotate(Iter(ia), Iter(ia), Iter(ia + sa));
+    assert(base(r) == ia + sa);
     assert(ia[0] == 0);
-    r = std::rotate(Iter(ia), Iter(ia+sa), Iter(ia+sa));
+    r = std::rotate(Iter(ia), Iter(ia + sa), Iter(ia + sa));
     assert(base(r) == ia);
     assert(ia[0] == 0);
 
-    int ib[] = {0, 1};
-    const int sb = static_cast<int>(sizeof(ib)/sizeof(ib[0]));
-    r = std::rotate(Iter(ib), Iter(ib), Iter(ib+sb));
-    assert(base(r) == ib+sb);
+    int ib[]     = {0, 1};
+    const int sb = static_cast<int>(sizeof(ib) / sizeof(ib[0]));
+    r            = std::rotate(Iter(ib), Iter(ib), Iter(ib + sb));
+    assert(base(r) == ib + sb);
     assert(ib[0] == 0);
     assert(ib[1] == 1);
-    r = std::rotate(Iter(ib), Iter(ib+1), Iter(ib+sb));
-    assert(base(r) == ib+1);
+    r = std::rotate(Iter(ib), Iter(ib + 1), Iter(ib + sb));
+    assert(base(r) == ib + 1);
     assert(ib[0] == 1);
     assert(ib[1] == 0);
-    r = std::rotate(Iter(ib), Iter(ib+sb), Iter(ib+sb));
+    r = std::rotate(Iter(ib), Iter(ib + sb), Iter(ib + sb));
     assert(base(r) == ib);
     assert(ib[0] == 1);
     assert(ib[1] == 0);
 
-    int ic[] = {0, 1, 2};
-    const int sc = static_cast<int>(sizeof(ic)/sizeof(ic[0]));
-    r = std::rotate(Iter(ic), Iter(ic), Iter(ic+sc));
-    assert(base(r) == ic+sc);
+    int ic[]     = {0, 1, 2};
+    const int sc = static_cast<int>(sizeof(ic) / sizeof(ic[0]));
+    r            = std::rotate(Iter(ic), Iter(ic), Iter(ic + sc));
+    assert(base(r) == ic + sc);
     assert(ic[0] == 0);
     assert(ic[1] == 1);
     assert(ic[2] == 2);
-    r = std::rotate(Iter(ic), Iter(ic+1), Iter(ic+sc));
-    assert(base(r) == ic+2);
+    r = std::rotate(Iter(ic), Iter(ic + 1), Iter(ic + sc));
+    assert(base(r) == ic + 2);
     assert(ic[0] == 1);
     assert(ic[1] == 2);
     assert(ic[2] == 0);
-    r = std::rotate(Iter(ic), Iter(ic+2), Iter(ic+sc));
-    assert(base(r) == ic+1);
+    r = std::rotate(Iter(ic), Iter(ic + 2), Iter(ic + sc));
+    assert(base(r) == ic + 1);
     assert(ic[0] == 0);
     assert(ic[1] == 1);
     assert(ic[2] == 2);
-    r = std::rotate(Iter(ic), Iter(ic+sc), Iter(ic+sc));
+    r = std::rotate(Iter(ic), Iter(ic + sc), Iter(ic + sc));
     assert(base(r) == ic);
     assert(ic[0] == 0);
     assert(ic[1] == 1);
     assert(ic[2] == 2);
 
-    int id[] = {0, 1, 2, 3};
-    const int sd = static_cast<int>(sizeof(id)/sizeof(id[0]));
-    r = std::rotate(Iter(id), Iter(id), Iter(id+sd));
-    assert(base(r) == id+sd);
+    int id[]     = {0, 1, 2, 3};
+    const int sd = static_cast<int>(sizeof(id) / sizeof(id[0]));
+    r            = std::rotate(Iter(id), Iter(id), Iter(id + sd));
+    assert(base(r) == id + sd);
     assert(id[0] == 0);
     assert(id[1] == 1);
     assert(id[2] == 2);
     assert(id[3] == 3);
-    r = std::rotate(Iter(id), Iter(id+1), Iter(id+sd));
-    assert(base(r) == id+3);
+    r = std::rotate(Iter(id), Iter(id + 1), Iter(id + sd));
+    assert(base(r) == id + 3);
     assert(id[0] == 1);
     assert(id[1] == 2);
     assert(id[2] == 3);
     assert(id[3] == 0);
-    r = std::rotate(Iter(id), Iter(id+2), Iter(id+sd));
-    assert(base(r) == id+2);
+    r = std::rotate(Iter(id), Iter(id + 2), Iter(id + sd));
+    assert(base(r) == id + 2);
     assert(id[0] == 3);
     assert(id[1] == 0);
     assert(id[2] == 1);
     assert(id[3] == 2);
-    r = std::rotate(Iter(id), Iter(id+3), Iter(id+sd));
-    assert(base(r) == id+1);
+    r = std::rotate(Iter(id), Iter(id + 3), Iter(id + sd));
+    assert(base(r) == id + 1);
     assert(id[0] == 2);
     assert(id[1] == 3);
     assert(id[2] == 0);
     assert(id[3] == 1);
-    r = std::rotate(Iter(id), Iter(id+sd), Iter(id+sd));
+    r = std::rotate(Iter(id), Iter(id + sd), Iter(id + sd));
     assert(base(r) == id);
     assert(id[0] == 2);
     assert(id[1] == 3);
     assert(id[2] == 0);
     assert(id[3] == 1);
 
-    int ie[] = {0, 1, 2, 3, 4};
-    const int se = static_cast<int>(sizeof(ie)/sizeof(ie[0]));
-    r = std::rotate(Iter(ie), Iter(ie), Iter(ie+se));
-    assert(base(r) == ie+se);
+    int ie[]     = {0, 1, 2, 3, 4};
+    const int se = static_cast<int>(sizeof(ie) / sizeof(ie[0]));
+    r            = std::rotate(Iter(ie), Iter(ie), Iter(ie + se));
+    assert(base(r) == ie + se);
     assert(ie[0] == 0);
     assert(ie[1] == 1);
     assert(ie[2] == 2);
     assert(ie[3] == 3);
     assert(ie[4] == 4);
-    r = std::rotate(Iter(ie), Iter(ie+1), Iter(ie+se));
-    assert(base(r) == ie+4);
+    r = std::rotate(Iter(ie), Iter(ie + 1), Iter(ie + se));
+    assert(base(r) == ie + 4);
     assert(ie[0] == 1);
     assert(ie[1] == 2);
     assert(ie[2] == 3);
     assert(ie[3] == 4);
     assert(ie[4] == 0);
-    r = std::rotate(Iter(ie), Iter(ie+2), Iter(ie+se));
-    assert(base(r) == ie+3);
+    r = std::rotate(Iter(ie), Iter(ie + 2), Iter(ie + se));
+    assert(base(r) == ie + 3);
     assert(ie[0] == 3);
     assert(ie[1] == 4);
     assert(ie[2] == 0);
     assert(ie[3] == 1);
     assert(ie[4] == 2);
-    r = std::rotate(Iter(ie), Iter(ie+3), Iter(ie+se));
-    assert(base(r) == ie+2);
+    r = std::rotate(Iter(ie), Iter(ie + 3), Iter(ie + se));
+    assert(base(r) == ie + 2);
     assert(ie[0] == 1);
     assert(ie[1] == 2);
     assert(ie[2] == 3);
     assert(ie[3] == 4);
     assert(ie[4] == 0);
-    r = std::rotate(Iter(ie), Iter(ie+4), Iter(ie+se));
-    assert(base(r) == ie+1);
+    r = std::rotate(Iter(ie), Iter(ie + 4), Iter(ie + se));
+    assert(base(r) == ie + 1);
     assert(ie[0] == 0);
     assert(ie[1] == 1);
     assert(ie[2] == 2);
     assert(ie[3] == 3);
     assert(ie[4] == 4);
-    r = std::rotate(Iter(ie), Iter(ie+se), Iter(ie+se));
+    r = std::rotate(Iter(ie), Iter(ie + se), Iter(ie + se));
     assert(base(r) == ie);
     assert(ie[0] == 0);
     assert(ie[1] == 1);
@@ -151,57 +151,57 @@ test()
     assert(ie[3] == 3);
     assert(ie[4] == 4);
 
-    int ig[] = {0, 1, 2, 3, 4, 5};
-    const int sg = static_cast<int>(sizeof(ig)/sizeof(ig[0]));
-    r = std::rotate(Iter(ig), Iter(ig), Iter(ig+sg));
-    assert(base(r) == ig+sg);
+    int ig[]     = {0, 1, 2, 3, 4, 5};
+    const int sg = static_cast<int>(sizeof(ig) / sizeof(ig[0]));
+    r            = std::rotate(Iter(ig), Iter(ig), Iter(ig + sg));
+    assert(base(r) == ig + sg);
     assert(ig[0] == 0);
     assert(ig[1] == 1);
     assert(ig[2] == 2);
     assert(ig[3] == 3);
     assert(ig[4] == 4);
     assert(ig[5] == 5);
-    r = std::rotate(Iter(ig), Iter(ig+1), Iter(ig+sg));
-    assert(base(r) == ig+5);
+    r = std::rotate(Iter(ig), Iter(ig + 1), Iter(ig + sg));
+    assert(base(r) == ig + 5);
     assert(ig[0] == 1);
     assert(ig[1] == 2);
     assert(ig[2] == 3);
     assert(ig[3] == 4);
     assert(ig[4] == 5);
     assert(ig[5] == 0);
-    r = std::rotate(Iter(ig), Iter(ig+2), Iter(ig+sg));
-    assert(base(r) == ig+4);
+    r = std::rotate(Iter(ig), Iter(ig + 2), Iter(ig + sg));
+    assert(base(r) == ig + 4);
     assert(ig[0] == 3);
     assert(ig[1] == 4);
     assert(ig[2] == 5);
     assert(ig[3] == 0);
     assert(ig[4] == 1);
     assert(ig[5] == 2);
-    r = std::rotate(Iter(ig), Iter(ig+3), Iter(ig+sg));
-    assert(base(r) == ig+3);
+    r = std::rotate(Iter(ig), Iter(ig + 3), Iter(ig + sg));
+    assert(base(r) == ig + 3);
     assert(ig[0] == 0);
     assert(ig[1] == 1);
     assert(ig[2] == 2);
     assert(ig[3] == 3);
     assert(ig[4] == 4);
     assert(ig[5] == 5);
-    r = std::rotate(Iter(ig), Iter(ig+4), Iter(ig+sg));
-    assert(base(r) == ig+2);
+    r = std::rotate(Iter(ig), Iter(ig + 4), Iter(ig + sg));
+    assert(base(r) == ig + 2);
     assert(ig[0] == 4);
     assert(ig[1] == 5);
     assert(ig[2] == 0);
     assert(ig[3] == 1);
     assert(ig[4] == 2);
     assert(ig[5] == 3);
-    r = std::rotate(Iter(ig), Iter(ig+5), Iter(ig+sg));
-    assert(base(r) == ig+1);
+    r = std::rotate(Iter(ig), Iter(ig + 5), Iter(ig + sg));
+    assert(base(r) == ig + 1);
     assert(ig[0] == 3);
     assert(ig[1] == 4);
     assert(ig[2] == 5);
     assert(ig[3] == 0);
     assert(ig[4] == 1);
     assert(ig[5] == 2);
-    r = std::rotate(Iter(ig), Iter(ig+sg), Iter(ig+sg));
+    r = std::rotate(Iter(ig), Iter(ig + sg), Iter(ig + sg));
     assert(base(r) == ig);
     assert(ig[0] == 3);
     assert(ig[1] == 4);
@@ -209,101 +209,99 @@ test()
     assert(ig[3] == 0);
     assert(ig[4] == 1);
     assert(ig[5] == 2);
-
-    return true;
-}
+  }
+};
 
 #if TEST_STD_VER >= 11
 
-template <class Iter>
-void
-test1()
-{
+struct TestUniquePtr {
+  template <class Iter>
+  TEST_CONSTEXPR_CXX23 void operator()() const {
     std::unique_ptr<int> ia[1];
-    const int sa = static_cast<int>(sizeof(ia)/sizeof(ia[0]));
+    const int sa = static_cast<int>(sizeof(ia) / sizeof(ia[0]));
     for (int i = 0; i < sa; ++i)
-        ia[i].reset(new int(i));
+      ia[i].reset(new int(i));
     Iter r = std::rotate(Iter(ia), Iter(ia), Iter(ia));
     assert(base(r) == ia);
     assert(*ia[0] == 0);
-    r = std::rotate(Iter(ia), Iter(ia), Iter(ia+sa));
-    assert(base(r) == ia+sa);
+    r = std::rotate(Iter(ia), Iter(ia), Iter(ia + sa));
+    assert(base(r) == ia + sa);
     assert(*ia[0] == 0);
-    r = std::rotate(Iter(ia), Iter(ia+sa), Iter(ia+sa));
+    r = std::rotate(Iter(ia), Iter(ia + sa), Iter(ia + sa));
     assert(base(r) == ia);
     assert(*ia[0] == 0);
 
     std::unique_ptr<int> ib[2];
-    const int sb = static_cast<int>(sizeof(ib)/sizeof(ib[0]));
+    const int sb = static_cast<int>(sizeof(ib) / sizeof(ib[0]));
     for (int i = 0; i < sb; ++i)
-        ib[i].reset(new int(i));
-    r = std::rotate(Iter(ib), Iter(ib), Iter(ib+sb));
-    assert(base(r) == ib+sb);
+      ib[i].reset(new int(i));
+    r = std::rotate(Iter(ib), Iter(ib), Iter(ib + sb));
+    assert(base(r) == ib + sb);
     assert(*ib[0] == 0);
     assert(*ib[1] == 1);
-    r = std::rotate(Iter(ib), Iter(ib+1), Iter(ib+sb));
-    assert(base(r) == ib+1);
+    r = std::rotate(Iter(ib), Iter(ib + 1), Iter(ib + sb));
+    assert(base(r) == ib + 1);
     assert(*ib[0] == 1);
     assert(*ib[1] == 0);
-    r = std::rotate(Iter(ib), Iter(ib+sb), Iter(ib+sb));
+    r = std::rotate(Iter(ib), Iter(ib + sb), Iter(ib + sb));
     assert(base(r) == ib);
     assert(*ib[0] == 1);
     assert(*ib[1] == 0);
 
     std::unique_ptr<int> ic[3];
-    const int sc = static_cast<int>(sizeof(ic)/sizeof(ic[0]));
+    const int sc = static_cast<int>(sizeof(ic) / sizeof(ic[0]));
     for (int i = 0; i < sc; ++i)
-        ic[i].reset(new int(i));
-    r = std::rotate(Iter(ic), Iter(ic), Iter(ic+sc));
-    assert(base(r) == ic+sc);
+      ic[i].reset(new int(i));
+    r = std::rotate(Iter(ic), Iter(ic), Iter(ic + sc));
+    assert(base(r) == ic + sc);
     assert(*ic[0] == 0);
     assert(*ic[1] == 1);
     assert(*ic[2] == 2);
-    r = std::rotate(Iter(ic), Iter(ic+1), Iter(ic+sc));
-    assert(base(r) == ic+2);
+    r = std::rotate(Iter(ic), Iter(ic + 1), Iter(ic + sc));
+    assert(base(r) == ic + 2);
     assert(*ic[0] == 1);
     assert(*ic[1] == 2);
     assert(*ic[2] == 0);
-    r = std::rotate(Iter(ic), Iter(ic+2), Iter(ic+sc));
-    assert(base(r) == ic+1);
+    r = std::rotate(Iter(ic), Iter(ic + 2), Iter(ic + sc));
+    assert(base(r) == ic + 1);
     assert(*ic[0] == 0);
     assert(*ic[1] == 1);
     assert(*ic[2] == 2);
-    r = std::rotate(Iter(ic), Iter(ic+sc), Iter(ic+sc));
+    r = std::rotate(Iter(ic), Iter(ic + sc), Iter(ic + sc));
     assert(base(r) == ic);
     assert(*ic[0] == 0);
     assert(*ic[1] == 1);
     assert(*ic[2] == 2);
 
     std::unique_ptr<int> id[4];
-    const int sd = static_cast<int>(sizeof(id)/sizeof(id[0]));
+    const int sd = static_cast<int>(sizeof(id) / sizeof(id[0]));
     for (int i = 0; i < sd; ++i)
-        id[i].reset(new int(i));
-    r = std::rotate(Iter(id), Iter(id), Iter(id+sd));
-    assert(base(r) == id+sd);
+      id[i].reset(new int(i));
+    r = std::rotate(Iter(id), Iter(id), Iter(id + sd));
+    assert(base(r) == id + sd);
     assert(*id[0] == 0);
     assert(*id[1] == 1);
     assert(*id[2] == 2);
     assert(*id[3] == 3);
-    r = std::rotate(Iter(id), Iter(id+1), Iter(id+sd));
-    assert(base(r) == id+3);
+    r = std::rotate(Iter(id), Iter(id + 1), Iter(id + sd));
+    assert(base(r) == id + 3);
     assert(*id[0] == 1);
     assert(*id[1] == 2);
     assert(*id[2] == 3);
     assert(*id[3] == 0);
-    r = std::rotate(Iter(id), Iter(id+2), Iter(id+sd));
-    assert(base(r) == id+2);
+    r = std::rotate(Iter(id), Iter(id + 2), Iter(id + sd));
+    assert(base(r) == id + 2);
     assert(*id[0] == 3);
     assert(*id[1] == 0);
     assert(*id[2] == 1);
     assert(*id[3] == 2);
-    r = std::rotate(Iter(id), Iter(id+3), Iter(id+sd));
-    assert(base(r) == id+1);
+    r = std::rotate(Iter(id), Iter(id + 3), Iter(id + sd));
+    assert(base(r) == id + 1);
     assert(*id[0] == 2);
     assert(*id[1] == 3);
     assert(*id[2] == 0);
     assert(*id[3] == 1);
-    r = std::rotate(Iter(id), Iter(id+sd), Iter(id+sd));
+    r = std::rotate(Iter(id), Iter(id + sd), Iter(id + sd));
     assert(base(r) == id);
     assert(*id[0] == 2);
     assert(*id[1] == 3);
@@ -311,45 +309,45 @@ test1()
     assert(*id[3] == 1);
 
     std::unique_ptr<int> ie[5];
-    const int se = static_cast<int>(sizeof(ie)/sizeof(ie[0]));
+    const int se = static_cast<int>(sizeof(ie) / sizeof(ie[0]));
     for (int i = 0; i < se; ++i)
-        ie[i].reset(new int(i));
-    r = std::rotate(Iter(ie), Iter(ie), Iter(ie+se));
-    assert(base(r) == ie+se);
+      ie[i].reset(new int(i));
+    r = std::rotate(Iter(ie), Iter(ie), Iter(ie + se));
+    assert(base(r) == ie + se);
     assert(*ie[0] == 0);
     assert(*ie[1] == 1);
     assert(*ie[2] == 2);
     assert(*ie[3] == 3);
     assert(*ie[4] == 4);
-    r = std::rotate(Iter(ie), Iter(ie+1), Iter(ie+se));
-    assert(base(r) == ie+4);
+    r = std::rotate(Iter(ie), Iter(ie + 1), Iter(ie + se));
+    assert(base(r) == ie + 4);
     assert(*ie[0] == 1);
     assert(*ie[1] == 2);
     assert(*ie[2] == 3);
     assert(*ie[3] == 4);
     assert(*ie[4] == 0);
-    r = std::rotate(Iter(ie), Iter(ie+2), Iter(ie+se));
-    assert(base(r) == ie+3);
+    r = std::rotate(Iter(ie), Iter(ie + 2), Iter(ie + se));
+    assert(base(r) == ie + 3);
     assert(*ie[0] == 3);
     assert(*ie[1] == 4);
     assert(*ie[2] == 0);
     assert(*ie[3] == 1);
     assert(*ie[4] == 2);
-    r = std::rotate(Iter(ie), Iter(ie+3), Iter(ie+se));
-    assert(base(r) == ie+2);
+    r = std::rotate(Iter(ie), Iter(ie + 3), Iter(ie + se));
+    assert(base(r) == ie + 2);
     assert(*ie[0] == 1);
     assert(*ie[1] == 2);
     assert(*ie[2] == 3);
     assert(*ie[3] == 4);
     assert(*ie[4] == 0);
-    r = std::rotate(Iter(ie), Iter(ie+4), Iter(ie+se));
-    assert(base(r) == ie+1);
+    r = std::rotate(Iter(ie), Iter(ie + 4), Iter(ie + se));
+    assert(base(r) == ie + 1);
     assert(*ie[0] == 0);
     assert(*ie[1] == 1);
     assert(*ie[2] == 2);
     assert(*ie[3] == 3);
     assert(*ie[4] == 4);
-    r = std::rotate(Iter(ie), Iter(ie+se), Iter(ie+se));
+    r = std::rotate(Iter(ie), Iter(ie + se), Iter(ie + se));
     assert(base(r) == ie);
     assert(*ie[0] == 0);
     assert(*ie[1] == 1);
@@ -358,58 +356,58 @@ test1()
     assert(*ie[4] == 4);
 
     std::unique_ptr<int> ig[6];
-    const int sg = static_cast<int>(sizeof(ig)/sizeof(ig[0]));
+    const int sg = static_cast<int>(sizeof(ig) / sizeof(ig[0]));
     for (int i = 0; i < sg; ++i)
-        ig[i].reset(new int(i));
-    r = std::rotate(Iter(ig), Iter(ig), Iter(ig+sg));
-    assert(base(r) == ig+sg);
+      ig[i].reset(new int(i));
+    r = std::rotate(Iter(ig), Iter(ig), Iter(ig + sg));
+    assert(base(r) == ig + sg);
     assert(*ig[0] == 0);
     assert(*ig[1] == 1);
     assert(*ig[2] == 2);
     assert(*ig[3] == 3);
     assert(*ig[4] == 4);
     assert(*ig[5] == 5);
-    r = std::rotate(Iter(ig), Iter(ig+1), Iter(ig+sg));
-    assert(base(r) == ig+5);
+    r = std::rotate(Iter(ig), Iter(ig + 1), Iter(ig + sg));
+    assert(base(r) == ig + 5);
     assert(*ig[0] == 1);
     assert(*ig[1] == 2);
     assert(*ig[2] == 3);
     assert(*ig[3] == 4);
     assert(*ig[4] == 5);
     assert(*ig[5] == 0);
-    r = std::rotate(Iter(ig), Iter(ig+2), Iter(ig+sg));
-    assert(base(r) == ig+4);
+    r = std::rotate(Iter(ig), Iter(ig + 2), Iter(ig + sg));
+    assert(base(r) == ig + 4);
     assert(*ig[0] == 3);
     assert(*ig[1] == 4);
     assert(*ig[2] == 5);
     assert(*ig[3] == 0);
     assert(*ig[4] == 1);
     assert(*ig[5] == 2);
-    r = std::rotate(Iter(ig), Iter(ig+3), Iter(ig+sg));
-    assert(base(r) == ig+3);
+    r = std::rotate(Iter(ig), Iter(ig + 3), Iter(ig + sg));
+    assert(base(r) == ig + 3);
     assert(*ig[0] == 0);
     assert(*ig[1] == 1);
     assert(*ig[2] == 2);
     assert(*ig[3] == 3);
     assert(*ig[4] == 4);
     assert(*ig[5] == 5);
-    r = std::rotate(Iter(ig), Iter(ig+4), Iter(ig+sg));
-    assert(base(r) == ig+2);
+    r = std::rotate(Iter(ig), Iter(ig + 4), Iter(ig + sg));
+    assert(base(r) == ig + 2);
     assert(*ig[0] == 4);
     assert(*ig[1] == 5);
     assert(*ig[2] == 0);
     assert(*ig[3] == 1);
     assert(*ig[4] == 2);
     assert(*ig[5] == 3);
-    r = std::rotate(Iter(ig), Iter(ig+5), Iter(ig+sg));
-    assert(base(r) == ig+1);
+    r = std::rotate(Iter(ig), Iter(ig + 5), Iter(ig + sg));
+    assert(base(r) == ig + 1);
     assert(*ig[0] == 3);
     assert(*ig[1] == 4);
     assert(*ig[2] == 5);
     assert(*ig[3] == 0);
     assert(*ig[4] == 1);
     assert(*ig[5] == 2);
-    r = std::rotate(Iter(ig), Iter(ig+sg), Iter(ig+sg));
+    r = std::rotate(Iter(ig), Iter(ig + sg), Iter(ig + sg));
     assert(base(r) == ig);
     assert(*ig[0] == 3);
     assert(*ig[1] == 4);
@@ -417,32 +415,31 @@ test1()
     assert(*ig[3] == 0);
     assert(*ig[4] == 1);
     assert(*ig[5] == 2);
-}
+  }
+};
 
 #endif // TEST_STD_VER >= 11
 
-int main(int, char**)
-{
-    test<forward_iterator<int*> >();
-    test<bidirectional_iterator<int*> >();
-    test<random_access_iterator<int*> >();
-    test<int*>();
+TEST_CONSTEXPR_CXX20 bool test() {
+  types::for_each(types::forward_iterator_list<int*>(), TestIter());
 
-#if TEST_STD_VER >= 11
+#if TEST_STD_VER >= 11 && TEST_STD_VER <= 17
+  types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
+#elif TEST_STD_VER == 20
+  if (!std::is_constant_evaluated())
+    types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
+#elif TEST_STD_VER >= 23
+  types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
+#endif
 
-    test1<forward_iterator<std::unique_ptr<int>*> >();
-    test1<bidirectional_iterator<std::unique_ptr<int>*> >();
-    test1<random_access_iterator<std::unique_ptr<int>*> >();
-    test1<std::unique_ptr<int>*>();
+  return true;
+}
 
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
 #endif
 
-#if TEST_STD_VER > 17
-    static_assert(test<forward_iterator<int*> >());
-    static_assert(test<bidirectional_iterator<int*> >());
-    static_assert(test<random_access_iterator<int*> >());
-    static_assert(test<int*>());
-#endif // TEST_STD_VER > 17
-
   return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
index c19f44a6d7eeb..f975afed282b1 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
@@ -9,7 +9,7 @@
 // <algorithm>
 
 // template<ForwardIterator InIter, OutputIterator<auto, InIter::reference> OutIter>
-//   constexpr OutIter          // constexpr after C++17
+//   constexpr OutIter          // constexpr since C++20
 //   rotate_copy(InIter first, InIter middle, InIter last, OutIter result);
 
 #include <algorithm>
@@ -17,140 +17,133 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "type_algorithms.h"
 
-
-template <class InIter, class OutIter>
-TEST_CONSTEXPR_CXX20 void test() {
-  int ia[] = {0, 1, 2, 3};
-  const unsigned sa = sizeof(ia) / sizeof(ia[0]);
-  int ib[sa] = {0};
-
-  OutIter r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia), OutIter(ib));
-  assert(base(r) == ib);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 1), OutIter(ib));
-  assert(base(r) == ib + 1);
-  assert(ib[0] == 0);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 1), OutIter(ib));
-  assert(base(r) == ib + 1);
-  assert(ib[0] == 0);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 2), OutIter(ib));
-  assert(base(r) == ib + 2);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 2), OutIter(ib));
-  assert(base(r) == ib + 2);
-  assert(ib[0] == 1);
-  assert(ib[1] == 0);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 2), OutIter(ib));
-  assert(base(r) == ib + 2);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 3), OutIter(ib));
-  assert(base(r) == ib + 3);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-  assert(ib[2] == 2);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 3), OutIter(ib));
-  assert(base(r) == ib + 3);
-  assert(ib[0] == 1);
-  assert(ib[1] == 2);
-  assert(ib[2] == 0);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 3), OutIter(ib));
-  assert(base(r) == ib + 3);
-  assert(ib[0] == 2);
-  assert(ib[1] == 0);
-  assert(ib[2] == 1);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 3), InIter(ia + 3), OutIter(ib));
-  assert(base(r) == ib + 3);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-  assert(ib[2] == 2);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 4), OutIter(ib));
-  assert(base(r) == ib + 4);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-  assert(ib[2] == 2);
-  assert(ib[3] == 3);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 4), OutIter(ib));
-  assert(base(r) == ib + 4);
-  assert(ib[0] == 1);
-  assert(ib[1] == 2);
-  assert(ib[2] == 3);
-  assert(ib[3] == 0);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 4), OutIter(ib));
-  assert(base(r) == ib + 4);
-  assert(ib[0] == 2);
-  assert(ib[1] == 3);
-  assert(ib[2] == 0);
-  assert(ib[3] == 1);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 3), InIter(ia + 4), OutIter(ib));
-  assert(base(r) == ib + 4);
-  assert(ib[0] == 3);
-  assert(ib[1] == 0);
-  assert(ib[2] == 1);
-  assert(ib[3] == 2);
-
-  r = std::rotate_copy(InIter(ia), InIter(ia + 4), InIter(ia + 4), OutIter(ib));
-  assert(base(r) == ib + 4);
-  assert(ib[0] == 0);
-  assert(ib[1] == 1);
-  assert(ib[2] == 2);
-  assert(ib[3] == 3);
-
-  {
-    int ints[] = {1, 3, 5, 2, 5, 6};
-    int const n_ints = sizeof(ints)/sizeof(int);
-    int zeros[n_ints] = {0};
-
-    const std::size_t N = 2;
-    const auto middle = std::begin(ints) + N;
-    auto it = std::rotate_copy(std::begin(ints), middle, std::end(ints), std::begin(zeros));
-    assert(std::distance(std::begin(zeros), it) == n_ints);
-    assert(std::equal(std::begin(ints), middle, std::begin(zeros) + n_ints - N));
-    assert(std::equal(middle, std::end(ints), std::begin(zeros)));
+struct TestIter {
+  template <class InIter>
+  TEST_CONSTEXPR_CXX20 void operator()() const {
+    types::for_each(types::cpp17_output_iterator_list<int*>(), TestImpl<InIter>());
   }
-}
-
-TEST_CONSTEXPR_CXX20 bool all_tests() {
-  test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
-  test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-  test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-  test<bidirectional_iterator<const int*>, int*>();
-
-  test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
-  test<random_access_iterator<const int*>, forward_iterator<int*> >();
-  test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-  test<random_access_iterator<const int*>, random_access_iterator<int*> >();
-  test<random_access_iterator<const int*>, int*>();
-
-  test<const int*, cpp17_output_iterator<int*> >();
-  test<const int*, forward_iterator<int*> >();
-  test<const int*, bidirectional_iterator<int*> >();
-  test<const int*, random_access_iterator<int*> >();
-  test<const int*, int*>();
 
+  template <class InIter>
+  struct TestImpl {
+    template <class OutIter>
+    TEST_CONSTEXPR_CXX20 void operator()() const {
+      int ia[]          = {0, 1, 2, 3};
+      const unsigned sa = sizeof(ia) / sizeof(ia[0]);
+      int ib[sa]        = {0};
+
+      OutIter r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia), OutIter(ib));
+      assert(base(r) == ib);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 1), OutIter(ib));
+      assert(base(r) == ib + 1);
+      assert(ib[0] == 0);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 1), OutIter(ib));
+      assert(base(r) == ib + 1);
+      assert(ib[0] == 0);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 2), OutIter(ib));
+      assert(base(r) == ib + 2);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 2), OutIter(ib));
+      assert(base(r) == ib + 2);
+      assert(ib[0] == 1);
+      assert(ib[1] == 0);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 2), OutIter(ib));
+      assert(base(r) == ib + 2);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 3), OutIter(ib));
+      assert(base(r) == ib + 3);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+      assert(ib[2] == 2);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 3), OutIter(ib));
+      assert(base(r) == ib + 3);
+      assert(ib[0] == 1);
+      assert(ib[1] == 2);
+      assert(ib[2] == 0);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 3), OutIter(ib));
+      assert(base(r) == ib + 3);
+      assert(ib[0] == 2);
+      assert(ib[1] == 0);
+      assert(ib[2] == 1);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 3), InIter(ia + 3), OutIter(ib));
+      assert(base(r) == ib + 3);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+      assert(ib[2] == 2);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia), InIter(ia + 4), OutIter(ib));
+      assert(base(r) == ib + 4);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+      assert(ib[2] == 2);
+      assert(ib[3] == 3);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 1), InIter(ia + 4), OutIter(ib));
+      assert(base(r) == ib + 4);
+      assert(ib[0] == 1);
+      assert(ib[1] == 2);
+      assert(ib[2] == 3);
+      assert(ib[3] == 0);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 2), InIter(ia + 4), OutIter(ib));
+      assert(base(r) == ib + 4);
+      assert(ib[0] == 2);
+      assert(ib[1] == 3);
+      assert(ib[2] == 0);
+      assert(ib[3] == 1);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 3), InIter(ia + 4), OutIter(ib));
+      assert(base(r) == ib + 4);
+      assert(ib[0] == 3);
+      assert(ib[1] == 0);
+      assert(ib[2] == 1);
+      assert(ib[3] == 2);
+
+      r = std::rotate_copy(InIter(ia), InIter(ia + 4), InIter(ia + 4), OutIter(ib));
+      assert(base(r) == ib + 4);
+      assert(ib[0] == 0);
+      assert(ib[1] == 1);
+      assert(ib[2] == 2);
+      assert(ib[3] == 3);
+
+      {
+        int ints[]        = {1, 3, 5, 2, 5, 6};
+        int const n_ints  = sizeof(ints) / sizeof(int);
+        int zeros[n_ints] = {0};
+
+        const std::size_t N = 2;
+        const auto middle   = std::begin(ints) + N;
+        auto it             = std::rotate_copy(std::begin(ints), middle, std::end(ints), std::begin(zeros));
+        assert(std::distance(std::begin(zeros), it) == n_ints);
+        assert(std::equal(std::begin(ints), middle, std::begin(zeros) + n_ints - N));
+        assert(std::equal(middle, std::end(ints), std::begin(zeros)));
+      }
+    }
+  };
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  types::for_each(types::bidirectional_iterator_list<const int*>(), TestIter());
   return true;
 }
 
 int main(int, char**) {
-  all_tests();
+  test();
 
-#if TEST_STD_VER > 17
-  static_assert(all_tests());
+#if TEST_STD_VER >= 20
+  static_assert(test());
 #endif
   return 0;
 }
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index 419f1d86730b8..030023f92e72b 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -1664,10 +1664,17 @@ using forward_iterator_list = concatenate_t<bidirectional_iterator_list<Ptr>, ty
 template <class Ptr>
 using cpp17_input_iterator_list = concatenate_t<forward_iterator_list<Ptr>, type_list<cpp17_input_iterator<Ptr> > >;
 
+template <class Ptr>
+using cpp17_output_iterator_list = concatenate_t<forward_iterator_list<Ptr>, type_list<cpp17_output_iterator<Ptr> > >;
+
 #if TEST_STD_VER >= 20
 template <class Ptr>
 using cpp20_input_iterator_list =
     concatenate_t<forward_iterator_list<Ptr>, type_list<cpp20_input_iterator<Ptr>, cpp17_input_iterator<Ptr>>>;
+
+template <class Ptr>
+using cpp20_output_iterator_list =
+    concatenate_t<forward_iterator_list<Ptr>, type_list<cpp20_output_iterator<Ptr>, cpp17_output_iterator<Ptr>>>;
 #endif
 } // namespace types
 

>From 35664a0630dac01168733e83b4355eb6ee1938e6 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Fri, 21 Feb 2025 11:58:06 -0500
Subject: [PATCH 2/2] Apply ldionne suggestions

---
 .../alg.rotate/ranges.rotate_copy.pass.cpp             | 10 +++++-----
 .../alg.rotate/rotate.pass.cpp                         |  8 ++------
 .../alg.rotate/rotate_copy.pass.cpp                    |  4 +++-
 libcxx/test/support/test_iterators.h                   |  7 -------
 4 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
index 35856a65cc703..da39f9521d038 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/ranges.rotate_copy.pass.cpp
@@ -73,7 +73,7 @@ constexpr void test(std::array<int, N> value, std::size_t middle, std::array<int
   }
 }
 
-template <class Iter, class OutIter, class Sent = Iter>
+template <class Iter, class OutIter, class Sent>
 constexpr void test_iterators() {
   // simple test
   test<Iter, OutIter, Sent, 4>({1, 2, 3, 4}, 2, {3, 4, 1, 2});
@@ -101,10 +101,10 @@ constexpr void test_iterators() {
 }
 
 constexpr bool test() {
-  types::for_each(types::forward_iterator_list<int*>(), []<class Iter>() {
-    types::for_each(types::cpp20_output_iterator_list<int*>(), []<class OutIter>() {
-      test_iterators<Iter, OutIter>();
-    });
+  types::for_each(types::forward_iterator_list<const int*>(), []<class Iter>() {
+    types::for_each(
+        types::concatenate_t<types::forward_iterator_list<int*>, types::type_list<cpp20_output_iterator<int*> > >(),
+        []<class OutIter>() { test_iterators<Iter, OutIter, Iter>(); });
   });
 
   {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
index 91a74786216ec..ce45bb1916816 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp
@@ -423,13 +423,9 @@ struct TestUniquePtr {
 TEST_CONSTEXPR_CXX20 bool test() {
   types::for_each(types::forward_iterator_list<int*>(), TestIter());
 
-#if TEST_STD_VER >= 11 && TEST_STD_VER <= 17
-  types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
-#elif TEST_STD_VER == 20
-  if (!std::is_constant_evaluated())
+#if TEST_STD_VER >= 11
+  if (TEST_STD_VER >= 23 || !TEST_IS_CONSTANT_EVALUATED)
     types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
-#elif TEST_STD_VER >= 23
-  types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
 #endif
 
   return true;
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
index f975afed282b1..8e356cc219fe7 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
@@ -22,7 +22,9 @@
 struct TestIter {
   template <class InIter>
   TEST_CONSTEXPR_CXX20 void operator()() const {
-    types::for_each(types::cpp17_output_iterator_list<int*>(), TestImpl<InIter>());
+    types::for_each(
+        types::concatenate_t<types::forward_iterator_list<int*>, types::type_list<cpp17_output_iterator<int*> > >(),
+        TestImpl<InIter>());
   }
 
   template <class InIter>
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index 030023f92e72b..419f1d86730b8 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -1664,17 +1664,10 @@ using forward_iterator_list = concatenate_t<bidirectional_iterator_list<Ptr>, ty
 template <class Ptr>
 using cpp17_input_iterator_list = concatenate_t<forward_iterator_list<Ptr>, type_list<cpp17_input_iterator<Ptr> > >;
 
-template <class Ptr>
-using cpp17_output_iterator_list = concatenate_t<forward_iterator_list<Ptr>, type_list<cpp17_output_iterator<Ptr> > >;
-
 #if TEST_STD_VER >= 20
 template <class Ptr>
 using cpp20_input_iterator_list =
     concatenate_t<forward_iterator_list<Ptr>, type_list<cpp20_input_iterator<Ptr>, cpp17_input_iterator<Ptr>>>;
-
-template <class Ptr>
-using cpp20_output_iterator_list =
-    concatenate_t<forward_iterator_list<Ptr>, type_list<cpp20_output_iterator<Ptr>, cpp17_output_iterator<Ptr>>>;
 #endif
 } // namespace types
 



More information about the libcxx-commits mailing list