[libcxx-commits] [libcxx] [libc++][ranges] P2609R3: Relaxing Ranges Just A Smidge (PR #101715)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 27 20:25:41 PDT 2024


https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/101715

>From cc39cf1feec8cec50f6e59085c4b2680f58851b1 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 3 Aug 2024 00:29:17 +0800
Subject: [PATCH 1/6] Implement the major part of P2609R3

---
 libcxx/include/__iterator/concepts.h  | 58 ++++++++++++++++++++-------
 libcxx/include/__iterator/projected.h |  8 ++++
 2 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index 0a4878308d55f0..be2890bee49284 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -35,6 +35,7 @@
 #include <__type_traits/add_pointer.h>
 #include <__type_traits/common_reference.h>
 #include <__type_traits/is_pointer.h>
+#include <__type_traits/is_primary_template.h>
 #include <__type_traits/is_reference.h>
 #include <__type_traits/remove_cv.h>
 #include <__type_traits/remove_cvref.h>
@@ -64,8 +65,33 @@ concept __indirectly_readable_impl =
 template <class _In>
 concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>;
 
+template <class _Tp>
+using __projected_iterator_t = typename _Tp::__projected_iterator;
+
+template <class _Tp>
+using __projected_projection_t = typename _Tp::__projected_projection;
+
+template <class _Tp>
+concept __specialization_of_projected = requires {
+  typename __projected_iterator_t<_Tp>;
+  typename __projected_projection_t<_Tp>;
+} && __is_primary_template<_Tp>::value;
+
+template <class _Tp>
+struct __indirect_value_t_impl {
+  using type = iter_value_t<_Tp>&;
+};
+template <__specialization_of_projected _Tp>
+struct __indirect_value_t_impl<_Tp> {
+  using type = invoke_result_t<__projected_projection_t<_Tp>&,
+                               typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>;
+};
+
+template <indirectly_readable _Tp>
+using __indirect_value_t = typename __indirect_value_t_impl<_Tp>::type;
+
 template <indirectly_readable _Tp>
-using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
+using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>;
 
 // [iterator.concept.writable]
 template <class _Out, class _Tp>
@@ -176,43 +202,45 @@ concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip
 // [indirectcallable.indirectinvocable]
 template <class _Fp, class _It>
 concept indirectly_unary_invocable =
-    indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, iter_value_t<_It>&> &&
+    indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, __indirect_value_t<_It>> &&
     invocable<_Fp&, iter_reference_t<_It>> &&
-    common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
+    common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
+                           invoke_result_t<_Fp&, iter_reference_t<_It>>>;
 
 template <class _Fp, class _It>
 concept indirectly_regular_unary_invocable =
-    indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, iter_value_t<_It>&> &&
+    indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, __indirect_value_t<_It>> &&
     regular_invocable<_Fp&, iter_reference_t<_It>> &&
-    common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
+    common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
+                           invoke_result_t<_Fp&, iter_reference_t<_It>>>;
 
 template <class _Fp, class _It>
 concept indirect_unary_predicate =
-    indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, iter_value_t<_It>&> &&
+    indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, __indirect_value_t<_It>> &&
     predicate<_Fp&, iter_reference_t<_It>>;
 
 template <class _Fp, class _It1, class _It2>
 concept indirect_binary_predicate =
     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
-    predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
-    predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
-    predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
+    predicate<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
+    predicate<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
+    predicate<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
     predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
 
 template <class _Fp, class _It1, class _It2 = _It1>
 concept indirect_equivalence_relation =
     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
-    equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
-    equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
-    equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
+    equivalence_relation<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
+    equivalence_relation<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
+    equivalence_relation<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
     equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
 
 template <class _Fp, class _It1, class _It2 = _It1>
 concept indirect_strict_weak_order =
     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
-    strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
-    strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
-    strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
+    strict_weak_order<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
+    strict_weak_order<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
+    strict_weak_order<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
     strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
 
 template <class _Fp, class... _Its>
diff --git a/libcxx/include/__iterator/projected.h b/libcxx/include/__iterator/projected.h
index 463d07b0d33c2d..1c560ec0550011 100644
--- a/libcxx/include/__iterator/projected.h
+++ b/libcxx/include/__iterator/projected.h
@@ -26,6 +26,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _It, class _Proj>
 struct __projected_impl {
   struct __type {
+    using __primary_template     = __type;
+    using __projected_iterator   = _It;
+    using __projected_projection = _Proj;
+
     using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
     indirect_result_t<_Proj&, _It> operator*() const; // not defined
   };
@@ -34,6 +38,10 @@ struct __projected_impl {
 template <weakly_incrementable _It, class _Proj>
 struct __projected_impl<_It, _Proj> {
   struct __type {
+    using __primary_template     = __type;
+    using __projected_iterator   = _It;
+    using __projected_projection = _Proj;
+
     using value_type      = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
     using difference_type = iter_difference_t<_It>;
     indirect_result_t<_Proj&, _It> operator*() const; // not defined

>From 6098b44e34a7fbe3d9b6ec19d3564ea557ecb432 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 3 Aug 2024 00:30:30 +0800
Subject: [PATCH 2/6] Test coverage for P2609R3

Co-authored-by: Jakub Mazurkiewicz <mazkuba3 at gmail.com>
---
 .../indirect.value.t.compile.pass.cpp         | 75 +++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp

diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp
new file mode 100644
index 00000000000000..7a903c781d6881
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// template<indirectly_readable T>
+// using indirect-value-t = see below; // exposition only
+
+#include <algorithm>
+#include <memory>
+#include <ranges>
+#include <utility>
+#include <vector>
+
+void test() {
+  auto ints             = std::views::iota(0, 5);
+  auto unique_ptr_maker = []<std::movable T>(T v) { return std::make_unique<T>(std::move(v)); };
+
+  using iota_iter             = std::ranges::iterator_t<decltype(ints)>;
+  using unique_ptr_projection = decltype(unique_ptr_maker);
+  using projected_iter        = std::projected<iota_iter, unique_ptr_projection>;
+
+  { // Check std::indirectly_unary_invocable
+    auto consume = [](auto) {};
+    static_assert(std::indirectly_unary_invocable<decltype(consume), projected_iter>);
+
+    std::ranges::for_each(ints, consume, unique_ptr_maker);
+    std::ranges::for_each(ints.begin(), ints.end(), consume, unique_ptr_maker);
+  }
+
+  { // Check std::indirectly_regular_unary_invocable
+    static_assert(std::indirectly_regular_unary_invocable<decltype([](auto) {}), projected_iter>);
+    using check_wellformedness [[maybe_unused]] = std::projected<projected_iter, unique_ptr_projection>;
+  }
+
+  { // Check std::indirect_unary_predicate
+    auto unary_pred = [](auto) { return false; };
+    static_assert(std::indirect_unary_predicate<decltype(unary_pred), projected_iter>);
+
+    (void)std::ranges::find_if(ints, unary_pred, unique_ptr_maker);
+    (void)std::ranges::find_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
+    (void)std::ranges::count_if(ints, unary_pred, unique_ptr_maker);
+    (void)std::ranges::count_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
+  }
+
+  { // Check std::indirect_binary_predicate
+    auto binary_pred = [](auto, auto) { return false; };
+    static_assert(std::indirect_binary_predicate<decltype(binary_pred), projected_iter, projected_iter>);
+
+    (void)std::ranges::adjacent_find(ints, binary_pred, unique_ptr_maker);
+    (void)std::ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, unique_ptr_maker);
+  }
+
+  { // Check std::indirect_equivalence_relation
+    auto rel = [](auto, auto) { return false; };
+    static_assert(std::indirect_equivalence_relation<decltype(rel), projected_iter>);
+
+    std::vector<int> out;
+    (void)std::ranges::unique_copy(ints, std::back_inserter(out), rel, unique_ptr_maker);
+    (void)std::ranges::unique_copy(ints.begin(), ints.end(), std::back_inserter(out), rel, unique_ptr_maker);
+  }
+
+  { // Check std::indirect_strict_weak_order
+    auto rel = [](auto x, auto y) { return x < y; };
+    static_assert(std::indirect_strict_weak_order<decltype(rel), projected_iter>);
+
+    (void)std::ranges::is_sorted_until(ints, rel, unique_ptr_maker);
+    (void)std::ranges::is_sorted_until(ints.begin(), ints.end(), rel, unique_ptr_maker);
+  }
+}

>From 377730bcfbf233cdefb036bc257f0152096d9ade Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 3 Aug 2024 00:42:24 +0800
Subject: [PATCH 3/6] Adjust feature-test macro `__cpp_lib_ranges`

In C++20 mode the value should be 202110L because
-  202202L covers `range_adaptor_closure` (P2387R3), and
- 202207L covers move-only types in range adaptors (P2494R2).

And of these changes are only available since C++23 mode.

In C++23 mode the value should be 202406L because
- 202211L covers removing poison overloads (P2602R2),
- 202302L covers relaxing projected value types (P2609R3), and
- 202406L covers removing requirements on iter_common_reference_t (P2997R1).

And all of these changes are already or being implemented.
---
 libcxx/docs/FeatureTestMacroTable.rst             |  4 +++-
 libcxx/include/version                            |  7 +++++--
 .../algorithm.version.compile.pass.cpp            | 15 ++++++++-------
 .../functional.version.compile.pass.cpp           | 15 ++++++++-------
 .../iterator.version.compile.pass.cpp             | 15 ++++++++-------
 .../memory.version.compile.pass.cpp               | 15 ++++++++-------
 .../ranges.version.compile.pass.cpp               | 15 ++++++++-------
 .../version.version.compile.pass.cpp              | 15 ++++++++-------
 .../generate_feature_test_macro_components.py     |  5 ++---
 9 files changed, 58 insertions(+), 48 deletions(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a1506e115fe70f..7e6666f9abd916 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -266,7 +266,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_polymorphic_allocator``                        ``201902L``
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_ranges``                                       ``202207L``
+    ``__cpp_lib_ranges``                                       ``202110L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_remove_cvref``                                 ``201711L``
     ---------------------------------------------------------- -----------------
@@ -350,6 +350,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_print``                                        ``202207L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_ranges``                                       ``202406L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_ranges_as_const``                              *unimplemented*
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_ranges_as_rvalue``                             ``202207L``
diff --git a/libcxx/include/version b/libcxx/include/version
index fe64343eafbc9c..abd2ffe2c08be1 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -182,8 +182,9 @@ __cpp_lib_philox_engine                                 202406L <random>
 __cpp_lib_polymorphic_allocator                         201902L <memory_resource>
 __cpp_lib_print                                         202207L <ostream> <print>
 __cpp_lib_quoted_string_io                              201304L <iomanip>
-__cpp_lib_ranges                                        202207L <algorithm> <functional> <iterator>
+__cpp_lib_ranges                                        202406L <algorithm> <functional> <iterator>
                                                                 <memory> <ranges>
+                                                        202110L // C++20
 __cpp_lib_ranges_as_const                               202207L <ranges>
 __cpp_lib_ranges_as_rvalue                              202207L <ranges>
 __cpp_lib_ranges_chunk                                  202202L <ranges>
@@ -428,7 +429,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # if _LIBCPP_AVAILABILITY_HAS_PMR
 #   define __cpp_lib_polymorphic_allocator              201902L
 # endif
-# define __cpp_lib_ranges                               202207L
+# define __cpp_lib_ranges                               202110L
 # define __cpp_lib_remove_cvref                         201711L
 # if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
 #   define __cpp_lib_semaphore                          201907L
@@ -480,6 +481,8 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_optional                             202110L
 # define __cpp_lib_out_ptr                              202106L
 # define __cpp_lib_print                                202207L
+# undef  __cpp_lib_ranges
+# define __cpp_lib_ranges                               202406L
 // # define __cpp_lib_ranges_as_const                      202207L
 # define __cpp_lib_ranges_as_rvalue                     202207L
 // # define __cpp_lib_ranges_chunk                         202202L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
index ded80060632419..42ccbfceb8d77a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
@@ -21,7 +21,8 @@
     __cpp_lib_default_template_type_for_algorithm_values    202403L [C++26]
     __cpp_lib_freestanding_algorithm                        202311L [C++26]
     __cpp_lib_parallel_algorithm                            201603L [C++17]
-    __cpp_lib_ranges                                        202207L [C++20]
+    __cpp_lib_ranges                                        202110L [C++20]
+                                                            202406L [C++23]
     __cpp_lib_ranges_contains                               202207L [C++23]
     __cpp_lib_ranges_find_last                              202207L [C++23]
     __cpp_lib_ranges_starts_ends_with                       202106L [C++23]
@@ -244,8 +245,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifdef __cpp_lib_ranges_contains
@@ -321,8 +322,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # ifndef __cpp_lib_ranges_contains
@@ -425,8 +426,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # ifndef __cpp_lib_ranges_contains
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
index 27e76e5b2b05a3..8ea19345903630 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
@@ -27,7 +27,8 @@
     __cpp_lib_invoke_r                 202106L [C++23]
     __cpp_lib_move_only_function       202110L [C++23]
     __cpp_lib_not_fn                   201603L [C++17]
-    __cpp_lib_ranges                   202207L [C++20]
+    __cpp_lib_ranges                   202110L [C++20]
+                                       202406L [C++23]
     __cpp_lib_reference_wrapper        202403L [C++26]
     __cpp_lib_result_of_sfinae         201210L [C++14]
     __cpp_lib_transparent_operators    201210L [C++14]
@@ -305,8 +306,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifdef __cpp_lib_reference_wrapper
@@ -409,8 +410,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # ifdef __cpp_lib_reference_wrapper
@@ -531,8 +532,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # ifndef __cpp_lib_reference_wrapper
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
index 700907ce9bb071..a756d10fcc375d 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
@@ -23,7 +23,8 @@
     __cpp_lib_move_iterator_concept         202207L [C++20]
     __cpp_lib_nonmember_container_access    201411L [C++17]
     __cpp_lib_null_iterators                201304L [C++14]
-    __cpp_lib_ranges                        202207L [C++20]
+    __cpp_lib_ranges                        202110L [C++20]
+                                            202406L [C++23]
     __cpp_lib_ssize                         201902L [C++20]
 */
 
@@ -197,8 +198,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifndef __cpp_lib_ssize
@@ -255,8 +256,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # ifndef __cpp_lib_ssize
@@ -313,8 +314,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # ifndef __cpp_lib_ssize
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
index aa1170658b103a..315058f7f46370 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
@@ -28,7 +28,8 @@
     __cpp_lib_make_unique                         201304L [C++14]
     __cpp_lib_out_ptr                             202106L [C++23]
                                                   202311L [C++26]
-    __cpp_lib_ranges                              202207L [C++20]
+    __cpp_lib_ranges                              202110L [C++20]
+                                                  202406L [C++23]
     __cpp_lib_raw_memory_algorithms               201606L [C++17]
     __cpp_lib_shared_ptr_arrays                   201611L [C++17]
                                                   201707L [C++20]
@@ -364,8 +365,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifndef __cpp_lib_raw_memory_algorithms
@@ -495,8 +496,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # ifndef __cpp_lib_raw_memory_algorithms
@@ -626,8 +627,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # ifndef __cpp_lib_raw_memory_algorithms
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index 30feacd796d8e1..8493505ef0236d 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -17,7 +17,8 @@
 
 /*  Constant                                                Value
     __cpp_lib_default_template_type_for_algorithm_values    202403L [C++26]
-    __cpp_lib_ranges                                        202207L [C++20]
+    __cpp_lib_ranges                                        202110L [C++20]
+                                                            202406L [C++23]
     __cpp_lib_ranges_as_const                               202207L [C++23]
     __cpp_lib_ranges_as_rvalue                              202207L [C++23]
     __cpp_lib_ranges_chunk                                  202202L [C++23]
@@ -192,8 +193,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifdef __cpp_lib_ranges_as_const
@@ -245,8 +246,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # if !defined(_LIBCPP_VERSION)
@@ -364,8 +365,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index b8bad696f1bae0..239d108fc34088 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -166,7 +166,8 @@
     __cpp_lib_polymorphic_allocator                         201902L [C++20]
     __cpp_lib_print                                         202207L [C++23]
     __cpp_lib_quoted_string_io                              201304L [C++14]
-    __cpp_lib_ranges                                        202207L [C++20]
+    __cpp_lib_ranges                                        202110L [C++20]
+                                                            202406L [C++23]
     __cpp_lib_ranges_as_const                               202207L [C++23]
     __cpp_lib_ranges_as_rvalue                              202207L [C++23]
     __cpp_lib_ranges_chunk                                  202202L [C++23]
@@ -4131,8 +4132,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++20"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202110L
+#   error "__cpp_lib_ranges should have the value 202110L in c++20"
 # endif
 
 # ifdef __cpp_lib_ranges_as_const
@@ -5619,8 +5620,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++23"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++23"
 # endif
 
 # if !defined(_LIBCPP_VERSION)
@@ -7470,8 +7471,8 @@
 # ifndef __cpp_lib_ranges
 #   error "__cpp_lib_ranges should be defined in c++26"
 # endif
-# if __cpp_lib_ranges != 202207L
-#   error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202406L
+#   error "__cpp_lib_ranges should have the value 202406L in c++26"
 # endif
 
 # if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 6c42748002aee3..0022be190b7c8d 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -991,9 +991,8 @@ def add_version_header(tc):
         {
             "name": "__cpp_lib_ranges",
             "values": {
-                "c++20": 202207,
-                # "c++23": 202302,  # Relaxing Ranges Just A Smidge
-                # "c++26": 202406,  # P2997R1 Removing the common reference requirement from the indirectly invocable concepts (already implemented as a DR)
+                "c++20": 202110,  # P2415R2 What is a view?
+                "c++23": 202406,  # P2997R1 Removing the common reference requirement from the indirectly invocable concepts (implemented as a DR against C++20)
             },
             "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
         },

>From e460d7d2aff02f19f74b21d237ba3f64259d5642 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 3 Aug 2024 00:43:21 +0800
Subject: [PATCH 4/6] Add release notes

---
 libcxx/docs/ReleaseNotes/20.rst    | 2 ++
 libcxx/docs/Status/Cxx23.rst       | 1 +
 libcxx/docs/Status/Cxx23Papers.csv | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 960fdd7ce05626..c05f22cbc4a9c5 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -38,6 +38,8 @@ What's New in Libc++ 20.0.0?
 Implemented Papers
 ------------------
 
+- P2609R3 - Relaxing Ranges Just A Smidge
+
 - TODO
 
 
diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst
index 23d30c8128d71e..5c85f6ec82c8ba 100644
--- a/libcxx/docs/Status/Cxx23.rst
+++ b/libcxx/docs/Status/Cxx23.rst
@@ -46,6 +46,7 @@ Paper Status
    .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
    .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
    .. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
+   .. [#note-P2609R3] This paper is applied as DR against C++20. (MSVC STL does the same.)
    .. [#note-P2693R1] P2693R1: The formatter for ``std::thread::id`` is implemented.
       The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is
       not implemented yet.
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index da498629ca5dd4..1d7f50421784c1 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -107,7 +107,7 @@
 "`P2770R0 <https://wg21.link/P2770R0>`__","Stashing stashing ``iterators`` for proper flattening","February 2023","|Partial| [#note-P2770R0]_","","|ranges|"
 "`P2164R9 <https://wg21.link/P2164R9>`__","``views::enumerate``","February 2023","","","|ranges|"
 "`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","February 2023","|In Progress| [#note-P2711R1]_","","|ranges|"
-"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","February 2023","","","|ranges|"
+"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","February 2023","|Complete| [#note-P2609R3]_","20.0","|ranges|"
 "`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","February 2023","|Complete|","19.0","|format|"
 "`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","February 2023","|Complete|","17.0","|format|"
 "`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","February 2023","|Complete|","17.0","|format|"

>From 2d8791a3c6816997028915fcc630b820d2acda10 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 24 Aug 2024 18:40:02 +0800
Subject: [PATCH 5/6] Add Github link to 20.rst

---
 libcxx/docs/ReleaseNotes/20.rst | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 7159d89ba5c871..5db6a9058d6e30 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -38,9 +38,7 @@ What's New in Libc++ 20.0.0?
 Implemented Papers
 ------------------
 
-- P2609R3 - Relaxing Ranges Just A Smidge
-
-- TODO
+- P2609R3 - Relaxing Ranges Just A Smidge  (`Github <https://github.com/llvm/llvm-project/issues/105253>`__)
 
 
 Improvements and New Features

>From ff841c89568695e102b4fbaf79f51fce11e70a90 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 28 Aug 2024 11:24:39 +0800
Subject: [PATCH 6/6] Run the test (also in constant evaluation since C++23)

---
 ...ile.pass.cpp => indirect.value.t.pass.cpp} | 33 +++++++++++++------
 1 file changed, 23 insertions(+), 10 deletions(-)
 rename libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/{indirect.value.t.compile.pass.cpp => indirect.value.t.pass.cpp} (71%)

diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.pass.cpp
similarity index 71%
rename from libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp
rename to libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.pass.cpp
index 7a903c781d6881..f278643d1a0913 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.pass.cpp
@@ -11,13 +11,17 @@
 // template<indirectly_readable T>
 // using indirect-value-t = see below; // exposition only
 
+#include <cassert>
+
 #include <algorithm>
 #include <memory>
 #include <ranges>
 #include <utility>
 #include <vector>
 
-void test() {
+#include "test_macros.h"
+
+TEST_CONSTEXPR_CXX23 void test() {
   auto ints             = std::views::iota(0, 5);
   auto unique_ptr_maker = []<std::movable T>(T v) { return std::make_unique<T>(std::move(v)); };
 
@@ -42,18 +46,18 @@ void test() {
     auto unary_pred = [](auto) { return false; };
     static_assert(std::indirect_unary_predicate<decltype(unary_pred), projected_iter>);
 
-    (void)std::ranges::find_if(ints, unary_pred, unique_ptr_maker);
-    (void)std::ranges::find_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
-    (void)std::ranges::count_if(ints, unary_pred, unique_ptr_maker);
-    (void)std::ranges::count_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
+    assert(std::ranges::find_if(ints, unary_pred, unique_ptr_maker) == ints.end());
+    assert(std::ranges::find_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker) == ints.end());
+    assert(std::ranges::count_if(ints, unary_pred, unique_ptr_maker) == 0);
+    assert(std::ranges::count_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker) == 0);
   }
 
   { // Check std::indirect_binary_predicate
     auto binary_pred = [](auto, auto) { return false; };
     static_assert(std::indirect_binary_predicate<decltype(binary_pred), projected_iter, projected_iter>);
 
-    (void)std::ranges::adjacent_find(ints, binary_pred, unique_ptr_maker);
-    (void)std::ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, unique_ptr_maker);
+    assert(std::ranges::adjacent_find(ints, binary_pred, unique_ptr_maker) == ints.end());
+    assert(std::ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, unique_ptr_maker) == ints.end());
   }
 
   { // Check std::indirect_equivalence_relation
@@ -66,10 +70,19 @@ void test() {
   }
 
   { // Check std::indirect_strict_weak_order
-    auto rel = [](auto x, auto y) { return x < y; };
+    auto rel = [](auto x, auto y) { return *x < *y; };
     static_assert(std::indirect_strict_weak_order<decltype(rel), projected_iter>);
 
-    (void)std::ranges::is_sorted_until(ints, rel, unique_ptr_maker);
-    (void)std::ranges::is_sorted_until(ints.begin(), ints.end(), rel, unique_ptr_maker);
+    assert(std::ranges::is_sorted_until(ints, rel, unique_ptr_maker) == ints.end());
+    assert(std::ranges::is_sorted_until(ints.begin(), ints.end(), rel, unique_ptr_maker) == ints.end());
   }
 }
+
+#if TEST_STD_VER >= 23
+static_assert((test(), true));
+#endif
+
+int main(int, char**) {
+  test();
+  return 0;
+}



More information about the libcxx-commits mailing list