Skip to content

[libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only) #88384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

H-G-Hristov
Copy link
Contributor

@H-G-Hristov H-G-Hristov commented Apr 11, 2024

@Zingam Zingam added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Apr 11, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 11, 2024

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

Implements https://wg21.link/P2944R3 (partially)


Full diff: https://github.com/llvm/llvm-project/pull/88384.diff

12 Files Affected:

  • (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1)
  • (modified) libcxx/docs/ReleaseNotes/19.rst (+1)
  • (modified) libcxx/docs/Status/Cxx2c.rst (+1)
  • (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1)
  • (modified) libcxx/include/__functional/reference_wrapper.h (+43)
  • (modified) libcxx/include/functional (+9)
  • (modified) libcxx/include/version (+1-1)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp (+5-11)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+5-11)
  • (added) libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.pass.cpp (+33)
  • (added) libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.pass.cpp (+68)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (-1)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3197d2cd1b271c..83d8213ec29f9e 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -444,7 +444,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_rcu``                                          *unimplemented*
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_reference_wrapper``                            *unimplemented*
+    ``__cpp_lib_reference_wrapper``                            ``202403L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_saturation_arithmetic``                        ``202311L``
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 81c05b9112bd26..a4c6975764cd73 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -45,6 +45,7 @@ Implemented Papers
 - P2867R2 - Remove Deprecated ``strstream``\s From C++26
 - P2872R3 - Remove ``wstring_convert`` From C++26
 - P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
+- P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only)
 - P2302R4 - ``std::ranges::contains``
 - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
 
diff --git a/libcxx/docs/Status/Cxx2c.rst b/libcxx/docs/Status/Cxx2c.rst
index a7ebc4662f517c..b6f1714a182a6c 100644
--- a/libcxx/docs/Status/Cxx2c.rst
+++ b/libcxx/docs/Status/Cxx2c.rst
@@ -40,6 +40,7 @@ Paper Status
 .. note::
 
    .. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
+   .. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only.
 
 .. _issues-status-cxx2c:
 
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index fa11da62bc080e..333d8fe824039f 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -59,7 +59,7 @@
 "`P2248R8 <https://wg21.link/P2248R8>`__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","",""
 "`P2810R4 <https://wg21.link/P2810R4>`__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","",""
 "`P1068R11 <https://wg21.link/P1068R11>`__","LWG","Vector API for random number generation","Tokyo March 2024","","",""
-"`P2944R3 <https://wg21.link/P2944R3>`__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","","",""
+"`P2944R3 <https://wg21.link/P2944R3>`__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","|Partial|","19.0",""
 "`P2642R6 <https://wg21.link/P2642R6>`__","LWG","Padded ``mdspan`` layouts","Tokyo March 2024","","",""
 "`P3029R1 <https://wg21.link/P3029R1>`__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","","",""
 "","","","","","",""
diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h
index 94b39e3bc78616..6c6643882886d7 100644
--- a/libcxx/include/__functional/reference_wrapper.h
+++ b/libcxx/include/__functional/reference_wrapper.h
@@ -10,11 +10,14 @@
 #ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
 #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
 
+#include <__compare/synth_three_way.h>
 #include <__config>
 #include <__functional/invoke.h>
 #include <__functional/weak_result_type.h>
 #include <__memory/addressof.h>
 #include <__type_traits/enable_if.h>
+#include <__type_traits/is_const.h>
+#include <__type_traits/is_convertible.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
@@ -64,6 +67,46 @@ class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> {
   {
     return std::__invoke(get(), std::forward<_ArgTypes>(__args)...);
   }
+
+#if _LIBCPP_STD_VER >= 26
+
+  // [refwrap.comparisons], comparisons
+
+  friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) {
+    static_assert(is_convertible_v<decltype(__x.get() == __y.get()), bool>);
+
+    return __x.get() == __y.get();
+  }
+
+  friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) {
+    static_assert(is_convertible_v<decltype(__x.get() == __y), bool>);
+
+    return __x.get() == __y;
+  }
+
+  friend constexpr bool operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y)
+    requires(!is_const_v<_Tp>)
+  {
+    static_assert(is_convertible_v<decltype(__x.get() == __y.get()), bool>);
+
+    return __x.get() == __y.get();
+  }
+
+  friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, reference_wrapper __y) {
+    return std::__synth_three_way(__x.get(), __y.get());
+  }
+
+  friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, const _Tp& __y) {
+    return std::__synth_three_way(__x.get(), __y.get());
+  }
+
+  friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, reference_wrapper<const _Tp> __y)
+    requires(!is_const_v<_Tp>)
+  {
+    return std::__synth_three_way(__x.get(), __y.get());
+  }
+
+#endif // _LIBCPP_STD_VER >= 26
 };
 
 #if _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/functional b/libcxx/include/functional
index a2476c93ad1b43..1da953f82241b5 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -77,6 +77,15 @@ template <class T> struct unwrap_ref_decay : unwrap_reference<decay_t<T>> { };
 template <class T> using unwrap_reference_t = typename unwrap_reference<T>::type; // since C++20
 template <class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type; // since C++20
 
+// [refwrap.comparisons], comparisons
+friend constexpr bool operator==(reference_wrapper, reference_wrapper);                                // Since C++26
+friend constexpr bool operator==(reference_wrapper, const T&);                                         // Since C++26
+friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>);                       // Since C++26
+
+friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper);          // Since C++26
+friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, const T&);                   // Since C++26
+friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper<const T>); // Since C++26
+
 template <class T> // <class T=void> in C++14
 struct plus {
     T operator()(const T& x, const T& y) const;
diff --git a/libcxx/include/version b/libcxx/include/version
index 0ed77345baa71d..0ce262462eb3ee 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -524,7 +524,7 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 // # define __cpp_lib_ranges_concat                        202403L
 # define __cpp_lib_ratio                                202306L
 // # define __cpp_lib_rcu                                  202306L
-// # define __cpp_lib_reference_wrapper                    202403L
+# define __cpp_lib_reference_wrapper                    202403L
 # define __cpp_lib_saturation_arithmetic                202311L
 // # define __cpp_lib_smart_ptr_owner_equality             202306L
 # define __cpp_lib_span_at                              202311L
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 aeb09a30b42591..27e76e5b2b05a3 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
@@ -535,17 +535,11 @@
 #   error "__cpp_lib_ranges should have the value 202207L in c++26"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_reference_wrapper
-#     error "__cpp_lib_reference_wrapper should be defined in c++26"
-#   endif
-#   if __cpp_lib_reference_wrapper != 202403L
-#     error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_reference_wrapper
-#     error "__cpp_lib_reference_wrapper should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_reference_wrapper
+#   error "__cpp_lib_reference_wrapper should be defined in c++26"
+# endif
+# if __cpp_lib_reference_wrapper != 202403L
+#   error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
 # endif
 
 # ifndef __cpp_lib_result_of_sfinae
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 3ec548f56cea1d..54fb538680ebad 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
@@ -7433,17 +7433,11 @@
 #   endif
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_reference_wrapper
-#     error "__cpp_lib_reference_wrapper should be defined in c++26"
-#   endif
-#   if __cpp_lib_reference_wrapper != 202403L
-#     error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_reference_wrapper
-#     error "__cpp_lib_reference_wrapper should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_reference_wrapper
+#   error "__cpp_lib_reference_wrapper should be defined in c++26"
+# endif
+# if __cpp_lib_reference_wrapper != 202403L
+#   error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
 # endif
 
 # ifndef __cpp_lib_remove_cvref
diff --git a/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.pass.cpp b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.pass.cpp
new file mode 100644
index 00000000000000..cbf5d8830200b5
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20, c++23
+
+// <functional>
+
+// class reference_wrapper
+
+// // [refwrap.comparisons], comparisons
+
+// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper);          // Since C++26
+// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, const T&);                   // Since C++26
+// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper<const T>); // Since C++26
+
+#include <cassert>
+#include <functional>
+
+#include "test_macros.h"
+
+constexpr bool test() { return true; }
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.pass.cpp b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.pass.cpp
new file mode 100644
index 00000000000000..8012c0c40d5b8e
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20, c++23
+
+// <functional>
+
+// class reference_wrapper
+
+// // [refwrap.comparisons], comparisons
+// friend constexpr bool operator==(reference_wrapper, reference_wrapper);                                // Since C++26
+// friend constexpr bool operator==(reference_wrapper, const T&);                                         // Since C++26
+// friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>);                       // Since C++26
+
+#include <cassert>
+#include <functional>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+  int i = 92;
+  int j = 84;
+
+  // ==
+  {
+    std::reference_wrapper<int> lhs{i};
+    std::reference_wrapper<int> rhs = lhs;
+    assert(lhs == rhs);
+  }
+  {
+    std::reference_wrapper<int> lhs{i};
+    assert(lhs == i);
+  }
+  {
+    std::reference_wrapper<int> lhs{i};
+    std::reference_wrapper<const int> rhs = lhs;
+    assert(lhs == rhs);
+  }
+  // !=
+  {
+    std::reference_wrapper<int> lhs{i};
+    std::reference_wrapper<int> rhs{j};
+    assert(lhs != rhs);
+  }
+  {
+    std::reference_wrapper<int> lhs{i};
+    assert(lhs != j);
+  }
+  {
+    std::reference_wrapper<int> lhs{i};
+    std::reference_wrapper<const int> rhs{j};
+    assert(lhs != rhs);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index f2b8d55c0e11b0..5f127bd1213c14 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1040,7 +1040,6 @@ def add_version_header(tc):
             "name": "__cpp_lib_reference_wrapper",
             "values": {"c++26": 202403}, # P2944R3: Comparisons for reference_wrapper
             "headers": ["functional"],
-            "unimplemented": True,
         },
         {
             "name": "__cpp_lib_remove_cvref",

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P2944R2-Comparisons-for-reference_wrapper branch from 65c8d4c to 7616aee Compare April 17, 2024 18:48
@frederick-vs-ja
Copy link
Contributor

Oops, perhaps we need to implement LWG4071 together.

@Zingam
Copy link
Contributor

Zingam commented Apr 20, 2024

Oops, perhaps we need to implement LWG4071 together.

Thanks! This makes sense.

I am not familiar with the LWG issues process? When do they get "voted in" or whatever the action is called?

Copy link

github-actions bot commented Apr 21, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P2944R2-Comparisons-for-reference_wrapper branch from a565160 to 96c33c6 Compare April 21, 2024 07:00
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P2944R2-Comparisons-for-reference_wrapper branch from 96c33c6 to 24dc20b Compare April 21, 2024 07:28
@mordante
Copy link
Member

I am not familiar with the LWG issues process? When do they get "voted in" or whatever the action is called?
I'll send you a PM on Discord.

@H-G-Hristov H-G-Hristov marked this pull request as ready for review April 21, 2024 15:50
@H-G-Hristov H-G-Hristov requested a review from a team as a code owner April 21, 2024 15:50
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!

Comment on lines 102 to 103
requires requires(const _Tp t) {
{ t < t } -> __boolean_testable;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
requires requires(const _Tp t) {
{ t < t } -> __boolean_testable;
requires requires(const _Tp __t) {
{ __t < __t } -> __boolean_testable;

However I wonder why this constraint is used. It does not match LWG 4071.

Copy link
Contributor

@frederick-vs-ja frederick-vs-ja Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See gcc-mirror/gcc@d86472a. This approach is also suggested in LWG4071 as an equivalent but simpler implementation stategy.

Copy link
Contributor Author

@H-G-Hristov H-G-Hristov Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
requires requires(const _Tp t) {
{ t < t } -> __boolean_testable;
// `operator<=>`: Checks the constraints of `synth-three-way` as per https://wg21.link/LWG4071 directly

The comment on line 99 is supposed to explain just that the contraint is implemented according to the recommendation in LWG4071, obviously I failed to do that.

In practice the requires-clause can be implemented more simply (and efficiently) by checking the constraints of synth-three-way directly:

requires (const T t) { { t < t } -> boolean-testable; }

but when specified in prose in a Constraints: element it seems clearer to just use synth-three-way(x.get(), y.get()).

@mordante mordante self-assigned this Apr 24, 2024

_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, reference_wrapper __y)
requires requires(const _Tp __t) {
{ __t < __t } -> __boolean_testable;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not implement the proposed resolution of LWG4071. Can you update it to the current proposed resolution? We should also have additonal tests that detect objects that pass this constraint but do not satisfy the __synth_three_way concept.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your last change misses one change.
You were right and __cpp_lib_reference_wrapper should indeed be marked as implemented in this patch.

With that fixed it LGTM.

@Zingam
Copy link
Contributor

Zingam commented May 4, 2024

Your last change misses one change. You were right and __cpp_lib_reference_wrapper should indeed be marked as implemented in this patch.

With that fixed it LGTM.

I didn't bother to set it because I wanted to ask you about your comment:

#88384 (comment)

This does not implement the proposed resolution of LWG4071. Can you update it to the current proposed resolution? We should also have additonal tests that detect objects that pass this constraint but do not satisfy the __synth_three_way concept.

I don't quite understand it: __synth_three_way is a function actually. Did I address your comment by any chance :)

Could you please confirm again that your are OK for me to merge the PR now?

@Zingam Zingam changed the title WIP - [libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only) [libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only) May 4, 2024
@Zingam Zingam changed the title [libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only) [libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only) May 4, 2024
@Zingam
Copy link
Contributor

Zingam commented May 5, 2024

@mordante I would also like to start adding [[nodiscard] wherever it is appropriate but I think I should apply it to all operators/functions not just to the latest ones. So I'll do it in a separate PR. WDYT?

@mordante
Copy link
Member

mordante commented May 8, 2024

@mordante I would also like to start adding [[nodiscard] wherever it is appropriate but I think I should apply it to all operators/functions not just to the latest ones. So I'll do it in a separate PR. WDYT?

Normally I wouldn't have minded to do it in this patch. However since this patch is as good as finished I rather have it in a separate patch. Just to make reviewing easier.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Zingam
Copy link
Contributor

Zingam commented May 9, 2024

LGTM!

Thank you!

@Zingam Zingam merged commit 8afa6cf into llvm:main May 9, 2024
52 checks passed
@Zingam
Copy link
Contributor

Zingam commented May 9, 2024

@H-G-Hristov H-G-Hristov deleted the hgh/libcxx/P2944R2-Comparisons-for-reference_wrapper branch May 9, 2024 12:03
@Zingam Zingam linked an issue Aug 21, 2024 that may be closed by this pull request
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P2944R3: Comparisons for reference_wrapper
5 participants