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

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Aug 2 09:57:24 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

<details>
<summary>Changes</summary>

Paper link: https://wg21.link/p2609r3

The test code was originally authored by @<!-- -->JMazurkiewicz.

### Notes for the DR status
P2609R3 is not officially a Defect Report, but MSVC STL implements in C++20 mode.

Moreover, P2609R3 and P2997R1 touch exactly the same set of concepts, and MSVC STL and libc++ have already treated P2997R1 as a DR.

### Notes for adjustments of 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 all 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.

References:
- https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
- https://wg21.link/p2997r1

---

Patch is 30.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/101715.diff


15 Files Affected:

- (modified) libcxx/docs/FeatureTestMacroTable.rst (+3-1) 
- (modified) libcxx/docs/ReleaseNotes/20.rst (+2) 
- (modified) libcxx/docs/Status/Cxx23.rst (+1) 
- (modified) libcxx/docs/Status/Cxx23Papers.csv (+1-1) 
- (modified) libcxx/include/__iterator/concepts.h (+43-15) 
- (modified) libcxx/include/__iterator/projected.h (+8) 
- (modified) libcxx/include/version (+5-2) 
- (added) libcxx/test/std/iterators/iterator.requirements/indirectcallable.traits/indirect.value.t.compile.pass.cpp (+75) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+8-7) 
- (modified) libcxx/utils/generate_feature_test_macro_components.py (+2-3) 


``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a1506e115fe70..7e6666f9abd91 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/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 960fdd7ce0562..c05f22cbc4a9c 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 23d30c8128d71..5c85f6ec82c8b 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 da498629ca5dd..1d7f50421784c 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|"
diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index 0a4878308d55f..be2890bee4928 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 463d07b0d33c2..1c560ec055001 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
diff --git a/libcxx/include/version b/libcxx/include/version
index fe64343eafbc9..abd2ffe2c08be 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/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 0000000000000..7a903c781d688
--- /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);
+  }
+}
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 ded8006063241..42ccbfceb8d77 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 27e76e5b2b05a..8ea1934590363 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 @@
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/101715


More information about the libcxx-commits mailing list