[libcxx-commits] [libcxx] cb3de24 - [libc++][iterator][ranges] P2997R1: Removing the common reference requirement from the indirectly invocable concepts (#98817)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 18 04:54:32 PDT 2024


Author: Hristo Hristov
Date: 2024-07-18T14:54:29+03:00
New Revision: cb3de24b5c0a662ba4a03c6c06a2d765d558bf62

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

LOG: [libc++][iterator][ranges] P2997R1: Removing the common reference requirement from the indirectly invocable concepts (#98817)

Implements as DR against C++20: https://wg21.link/P2997R1

References:
- https://eel.is/c++draft/indirectcallable.indirectinvocable
- https://eel.is/c++draft/version.syn#header:%3cversion%3e

---------

Co-authored-by: Hristo Hristov <zingam at outlook.com>

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes/19.rst
    libcxx/docs/Status/Cxx2c.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/__iterator/concepts.h
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 80f43256f1270..a28dae52e8579 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -48,6 +48,7 @@ Implemented Papers
 - P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only)
 - P2591R5 - Concatenation of strings and string views
 - P2968R2 - Make ``std::ignore`` a first-class object
+- P2997R1 - Removing the common reference requirement from the indirectly invocable concepts (as DR against C++20)
 - P2302R4 - ``std::ranges::contains``
 - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
 - P3029R1 - Better ``mdspan``'s CTAD

diff  --git a/libcxx/docs/Status/Cxx2c.rst b/libcxx/docs/Status/Cxx2c.rst
index 03a6eeaa40c79..1b8d96588c3cb 100644
--- a/libcxx/docs/Status/Cxx2c.rst
+++ b/libcxx/docs/Status/Cxx2c.rst
@@ -43,6 +43,7 @@ Paper Status
    .. [#note-P3142R0] This paper is applied as DR against C++23. (MSVC STL and libstdc++ will do the same.)
    .. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only.
    .. [#note-P2422R1] Libc++ keeps the ``nodiscard`` attributes as a conforming extension.
+   .. [#note-P2997R1] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
 
 .. _issues-status-cxx2c:
 

diff  --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 968d82a973a79..130e4ef894f29 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -64,7 +64,7 @@
 "`P3029R1 <https://wg21.link/P3029R1>`__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","|Complete|","19.0",""
 "","","","","","",""
 "`P2747R2 <https://wg21.link/P2747R2>`__","CWG","``constexpr`` placement new","St. Louis June 2024","","",""
-"`P2997R1 <https://wg21.link/P2997R1>`__","LWG","Removing the common reference requirement from the indirectly invocable concepts","St. Louis June 2024","","",""
+"`P2997R1 <https://wg21.link/P2997R1>`__","LWG","Removing the common reference requirement from the indirectly invocable concepts","St. Louis June 2024","|Complete| [#note-P2997R1]_","19.0",""
 "`P2389R2 <https://wg21.link/P2389R2>`__","LWG","``dextents`` Index Type Parameter","St. Louis June 2024","|Complete|","19.0",""
 "`P3168R2 <https://wg21.link/P3168R2>`__","LWG","Give ``std::optional`` Range Support","St. Louis June 2024","","","|ranges|"
 "`P3217R0 <https://wg21.link/P3217R0>`__","LWG","Adjoints to 'Enabling list-initialization for algorithms': find_last","St. Louis June 2024","","",""

diff  --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index afb7b821a99ce..0a4878308d55f 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -177,19 +177,19 @@ concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip
 template <class _Fp, class _It>
 concept indirectly_unary_invocable =
     indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, iter_value_t<_It>&> &&
-    invocable<_Fp&, iter_reference_t<_It>> && invocable<_Fp&, iter_common_reference_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>>>;
 
 template <class _Fp, class _It>
 concept indirectly_regular_unary_invocable =
     indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, iter_value_t<_It>&> &&
-    regular_invocable<_Fp&, iter_reference_t<_It>> && regular_invocable<_Fp&, iter_common_reference_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>>>;
 
 template <class _Fp, class _It>
 concept indirect_unary_predicate =
     indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, iter_value_t<_It>&> &&
-    predicate<_Fp&, iter_reference_t<_It>> && predicate<_Fp&, iter_common_reference_t<_It>>;
+    predicate<_Fp&, iter_reference_t<_It>>;
 
 template <class _Fp, class _It1, class _It2>
 concept indirect_binary_predicate =
@@ -197,8 +197,7 @@ concept indirect_binary_predicate =
     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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
-    predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
+    predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
 
 template <class _Fp, class _It1, class _It2 = _It1>
 concept indirect_equivalence_relation =
@@ -206,8 +205,7 @@ concept indirect_equivalence_relation =
     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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
-    equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_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 =
@@ -215,8 +213,7 @@ concept indirect_strict_weak_order =
     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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
-    strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
+    strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
 
 template <class _Fp, class... _Its>
   requires(indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...>

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp
index e04c508852820..38dcd70d850e6 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp
@@ -76,12 +76,13 @@ struct BadPredicate5 {
 };
 static_assert(!std::indirect_binary_predicate<BadPredicate5, It1, It2>);
 
-// Should fail when the predicate can't be called with (iter_common_reference_t, iter_common_reference_t)
-struct BadPredicate6 {
-    template <class T, class U> bool operator()(T const&, U const&) const;
-    bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodPredicate6 {
+  template <class T, class U>
+  bool operator()(T const&, U const&) const;
+  bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
 };
-static_assert(!std::indirect_binary_predicate<BadPredicate6, It1, It2>);
+static_assert(std::indirect_binary_predicate<GoodPredicate6, It1, It2>);
 
 // Test ADL-proofing (P2538R1)
 #if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp
index 56f52f28ff6fe..8ea7e8a6d9e1e 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp
@@ -91,12 +91,13 @@ struct BadRelation5 {
 };
 static_assert(!std::indirect_equivalence_relation<BadRelation5, It1, It2>);
 
-// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
-struct BadRelation6 {
-    template <class T, class U> bool operator()(T const&, U const&) const;
-    bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodRelation6 {
+  template <class T, class U>
+  bool operator()(T const&, U const&) const;
+  bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
 };
-static_assert(!std::indirect_equivalence_relation<BadRelation6, It1, It2>);
+static_assert(std::indirect_equivalence_relation<GoodRelation6, It1, It2>);
 
 // Test ADL-proofing (P2538R1)
 #if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp
index f36431c89f288..074725f97bf32 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp
@@ -91,12 +91,13 @@ struct BadOrder5 {
 };
 static_assert(!std::indirect_strict_weak_order<BadOrder5, It1, It2>);
 
-// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
-struct BadOrder6 {
-    template <class T, class U> bool operator()(T const&, U const&) const;
-    bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodOrder6 {
+  template <class T, class U>
+  bool operator()(T const&, U const&) const;
+  bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
 };
-static_assert(!std::indirect_strict_weak_order<BadOrder6, It1, It2>);
+static_assert(std::indirect_strict_weak_order<GoodOrder6, It1, It2>);
 
 // Test ADL-proofing (P2538R1)
 #if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp
index 4551113af82e8..f52ea8f9151c3 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp
@@ -57,12 +57,13 @@ struct BadPredicate3 {
 };
 static_assert(!std::indirect_unary_predicate<BadPredicate3, It>);
 
-// Should fail when the predicate can't be called with std::iter_common_reference_t<It>
-struct BadPredicate4 {
-    template <class T> bool operator()(T const&) const;
-    bool operator()(std::iter_common_reference_t<It>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodPredicate4 {
+  template <class T>
+  bool operator()(T const&) const;
+  bool operator()(std::iter_common_reference_t<It>) const = delete;
 };
-static_assert(!std::indirect_unary_predicate<BadPredicate4, It>);
+static_assert(std::indirect_unary_predicate<GoodPredicate4, It>);
 
 // Test ADL-proofing (P2538R1)
 #if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp
index 9e0c3c99dee98..fceae03a4b324 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp
@@ -56,12 +56,13 @@ struct BadInvocable3 {
 };
 static_assert(!std::indirectly_regular_unary_invocable<BadInvocable3, It>);
 
-// Should fail when the invocable can't be called with (iter_common_reference_t)
-struct BadInvocable4 {
-    template <class T> R1 operator()(T const&) const;
-    R1 operator()(std::iter_common_reference_t<It>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodInvocable4 {
+  template <class T>
+  R1 operator()(T const&) const;
+  R1 operator()(std::iter_common_reference_t<It>) const = delete;
 };
-static_assert(!std::indirectly_regular_unary_invocable<BadInvocable4, It>);
+static_assert(std::indirectly_regular_unary_invocable<GoodInvocable4, It>);
 
 // Should fail when the invocable doesn't have a common reference between its return types
 struct BadInvocable5 {

diff  --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp
index fc955eb88585a..27c078baeb194 100644
--- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp
@@ -56,12 +56,13 @@ struct BadInvocable3 {
 };
 static_assert(!std::indirectly_unary_invocable<BadInvocable3, It>);
 
-// Should fail when the invocable can't be called with (iter_common_reference_t)
-struct BadInvocable4 {
-    template <class T> R1 operator()(T const&) const;
-    R1 operator()(std::iter_common_reference_t<It>) const = delete;
+// This case was made valid by P2997R1.
+struct GoodInvocable4 {
+  template <class T>
+  R1 operator()(T const&) const;
+  R1 operator()(std::iter_common_reference_t<It>) const = delete;
 };
-static_assert(!std::indirectly_unary_invocable<BadInvocable4, It>);
+static_assert(std::indirectly_unary_invocable<GoodInvocable4, It>);
 
 // Should fail when the invocable doesn't have a common reference between its return types
 struct BadInvocable5 {

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index a267e5774e2ad..65ba2f8455f1b 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -993,7 +993,8 @@ def add_version_header(tc):
             "name": "__cpp_lib_ranges",
             "values": {
                 "c++20": 202207,
-                # "c++26": 202406, # P2997R1 Removing the common reference requirement from the indirectly invocable concepts
+                # "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)
             },
             "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
         },


        


More information about the libcxx-commits mailing list