[libcxx-commits] [libcxx] b552a30 - [libc++] Finish implementing P0202R3

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 14 14:03:25 PDT 2020


Author: Nicholas-Baron
Date: 2020-09-14T16:58:49-04:00
New Revision: b552a30283cea1e9d3f90aef3cdd2ac24c366062

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

LOG: [libc++] Finish implementing P0202R3

cppreference lists the support for this paper as partial.
I found 4 functions which the paper marks as `constexpr`,
but did not use the appropriate macro.

Differential Revision: https://reviews.llvm.org/D84275

Added: 
    

Modified: 
    libcxx/include/algorithm
    libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate_copy.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
    libcxx/www/cxx2a_status.html

Removed: 
    


################################################################################
diff  --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 37f2b4dd7626..5d09b6c3c015 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -2529,7 +2529,7 @@ rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __l
 // rotate_copy
 
 template <class _ForwardIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _OutputIterator __result)
 {
@@ -4394,6 +4394,7 @@ binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __va
 // merge
 
 template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 __merge(_InputIterator1 __first1, _InputIterator1 __last1,
         _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -4417,7 +4418,7 @@ __merge(_InputIterator1 __first1, _InputIterator1 __last1,
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 merge(_InputIterator1 __first1, _InputIterator1 __last1,
       _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -4427,7 +4428,7 @@ merge(_InputIterator1 __first1, _InputIterator1 __last1,
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 merge(_InputIterator1 __first1, _InputIterator1 __last1,
       _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)

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 d66bf8caad6e..8acb1a129e38 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
@@ -18,139 +18,139 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-// #if TEST_STD_VER > 17
-// TEST_CONSTEXPR bool test_constexpr() {
-//     int ia[] = {1, 3, 5, 2, 5, 6};
-//     int ib[std::size(ia)] = {0};
-//
-//     const size_t N = 2;
-//     const auto middle = std::begin(ia) + N;
-//     auto it = std::rotate_copy(std::begin(ia), middle, std::end(ia), std::begin(ib));
-//
-//     return std::distance(std::begin(ib), it) == std::size(ia)
-//         && std::equal   (std::begin(ia), middle,       std::begin(ib) + std::size(ia) - N)
-//         && std::equal   (middle,         std::end(ia), std::begin(ib))
-//            ;
-//     }
-// #endif
 
 template <class InIter, class OutIter>
-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);
+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 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 all_tests() {
+  test<bidirectional_iterator<const int*>, 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*>, 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*, 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*>();
+
+  return true;
 }
 
-int main(int, char**)
-{
-    test<bidirectional_iterator<const int*>, 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*>, 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*, 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*>();
-
-// #if TEST_STD_VER > 17
-//    static_assert(test_constexpr());
-// #endif
+int main(int, char**) {
+  all_tests();
 
+#if TEST_STD_VER > 17
+  static_assert(all_tests());
+#endif
   return 0;
 }

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
index 6c6f0c46d446..167da9aa2ddd 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
@@ -24,28 +24,26 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-
-// #if TEST_STD_VER > 17
-// TEST_CONSTEXPR bool test_constexpr() {
-//           int ia[]       = {0, 1, 2, 3, 4};
-//           int ib[]       = {2, 4, 6, 8};
-//           int ic[]       = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-//     const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
-//
-//     auto it = std::merge(std::begin(ia), std::end(ia), std::begin(ib), std::end(ib), std::begin(ic));
-//     return std::distance(std::begin(ic), it) == (std::size(ia) + std::size(ib))
-//         && *it == 0
-//         && std::equal(std::begin(ic), it, std::begin(expected), std::end(expected))
-//         ;
-//     }
-// #endif
+#if TEST_STD_VER > 17
+TEST_CONSTEXPR bool test_constexpr() {
+  int ia[] = {0, 1, 2, 3, 4};
+  int ib[] = {2, 4, 6, 8};
+  int ic[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
+
+  auto it = std::merge(std::begin(ia), std::end(ia), std::begin(ib),
+                       std::end(ib), std::begin(ic));
+  assert(std::distance(std::begin(ic), it) == (std::size(ia) + std::size(ib)));
+  assert(*it == 0);
+  assert(std::equal(std::begin(ic), it, std::begin(expected), std::end(expected)));
+  return true;
+}
+#endif
 
 std::mt19937 randomness;
 
 template <class InIter1, class InIter2, class OutIter>
-void
-test()
-{
+void test() {
     {
     unsigned N = 100000;
     int* ia = new int[N];
@@ -242,9 +240,8 @@ int main(int, char**)
     test<const int*, const int*, int*>();
 
 #if TEST_STD_VER > 17
-//  Not yet - waiting on std::copy
-//     static_assert(test_constexpr());
+    static_assert(test_constexpr());
 #endif
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
index afa7073581e5..8d2dbb726858 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
@@ -28,22 +28,23 @@
 #include "test_iterators.h"
 #include "counting_predicates.h"
 
-// #if TEST_STD_VER > 17
-// TEST_CONSTEXPR bool test_constexpr() {
-//           int ia[]       = {0, 1, 2, 3, 4};
-//           int ib[]       = {2, 4, 6, 8};
-//           int ic[]       = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-//     const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
-//
-//     auto it = std::merge(std::begin(ia), std::end(ia),
-//                          std::begin(ib), std::end(ib),
-//                          std::begin(ic), [](int a, int b) {return a == b; });
-//     return std::distance(std::begin(ic), it) == (std::size(ia) + std::size(ib))
-//         && *it == 0
-//         && std::equal(std::begin(ic), it, std::begin(expected), std::end(expected))
-//         ;
-//     }
-// #endif
+#if TEST_STD_VER > 17
+TEST_CONSTEXPR bool test_constexpr() {
+  int ia[] = {0, 1, 2, 3, 4};
+  int ib[] = {2, 4, 6, 8};
+  int ic[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
+
+  auto it =
+      std::merge(std::begin(ia), std::end(ia), std::begin(ib), std::end(ib),
+                 std::begin(ic), [](int a, int b) { return a == b; });
+  assert(std::distance(std::begin(ic), it) == (std::size(ia) + std::size(ib)));
+  assert(*it == 0);
+  assert(
+      std::equal(std::begin(ic), it, std::begin(expected), std::end(expected)));
+  return true;
+}
+#endif
 
 std::mt19937 randomness;
 
@@ -253,8 +254,7 @@ int main(int, char**)
     test<const int*, const int*, int*>();
 
 #if TEST_STD_VER > 17
-//  Not yet - waiting on std::copy
-//     static_assert(test_constexpr());
+    static_assert(test_constexpr());
 #endif
 
   return 0;

diff  --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html
index c6ccd9681d75..88df02bcb117 100644
--- a/libcxx/www/cxx2a_status.html
+++ b/libcxx/www/cxx2a_status.html
@@ -261,7 +261,7 @@ <h3>Paper Status</h3>
 
 <p>The missing bits in P0600 are in [mem.res.class], [mem.poly.allocator.class], and [container.node.overview]</p>
 
-<p>The missing bits in P0202 are in <tt>copy</tt> and <tt>copy_backwards</tt> (and the ones that call them: <tt>copy_n</tt>, <tt>rotate_copy</tt>, <tt>merge</tt>, <tt>set_union</tt>, <tt>set_
diff erence</tt>, and <tt>set_symmetric_
diff erence</tt>). This is because the first four algorithms have specializations that call <tt>memmove</tt> which is not constexpr. See <a href="https://bugs.llvm.org/show_bug.cgi?id=25165">Bug 25165</a></p>
+<p>The missing bits in P0202 are in <tt>copy</tt> and <tt>copy_backwards</tt> (and the ones that call them: <tt>copy_n</tt>, <tt>set_union</tt>, <tt>set_
diff erence</tt>, and <tt>set_symmetric_
diff erence</tt>). This is because the first two algorithms have specializations that call <tt>memmove</tt> which is not constexpr. See <a href="https://bugs.llvm.org/show_bug.cgi?id=25165">Bug 25165</a></p>
 
 
   <h3>Library Working group Issues Status</h3>


        


More information about the libcxx-commits mailing list