Skip to content

Commit d08f17c

Browse files
committed
[libc++][functional] P2944R3 (partial): Comparisons for reference_wrapper (reference_wrapper operators only)
Implements parially https://wg21.link/P2944R3
1 parent b8d0cba commit d08f17c

File tree

12 files changed

+157
-26
lines changed

12 files changed

+157
-26
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ Status
444444
---------------------------------------------------------- -----------------
445445
``__cpp_lib_rcu`` *unimplemented*
446446
---------------------------------------------------------- -----------------
447-
``__cpp_lib_reference_wrapper`` *unimplemented*
447+
``__cpp_lib_reference_wrapper`` ``202403L``
448448
---------------------------------------------------------- -----------------
449449
``__cpp_lib_saturation_arithmetic`` ``202311L``
450450
---------------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Implemented Papers
4646
- P2869R4 - Remove Deprecated ``shared_ptr`` Atomic Access APIs from C++26
4747
- P2872R3 - Remove ``wstring_convert`` From C++26
4848
- P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
49+
- P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only)
4950
- P2302R4 - ``std::ranges::contains``
5051
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
5152
- P3029R1 - Better ``mdspan``'s CTAD

libcxx/docs/Status/Cxx2c.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Paper Status
4040
.. note::
4141

4242
.. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
43+
.. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only.
4344
4445
.. _issues-status-cxx2c:
4546

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"`P2248R8 <https://wg21.link/P2248R8>`__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","",""
6060
"`P2810R4 <https://wg21.link/P2810R4>`__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","",""
6161
"`P1068R11 <https://wg21.link/P1068R11>`__","LWG","Vector API for random number generation","Tokyo March 2024","","",""
62-
"`P2944R3 <https://wg21.link/P2944R3>`__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","","",""
62+
"`P2944R3 <https://wg21.link/P2944R3>`__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","|Partial|","19.0",""
6363
"`P2642R6 <https://wg21.link/P2642R6>`__","LWG","Padded ``mdspan`` layouts","Tokyo March 2024","","",""
6464
"`P3029R1 <https://wg21.link/P3029R1>`__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","|Complete|","19.0",""
6565
"","","","","","",""

libcxx/include/__functional/reference_wrapper.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
#ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
1111
#define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
1212

13+
#include <__compare/synth_three_way.h>
1314
#include <__config>
1415
#include <__functional/invoke.h>
1516
#include <__functional/weak_result_type.h>
1617
#include <__memory/addressof.h>
1718
#include <__type_traits/enable_if.h>
19+
#include <__type_traits/is_const.h>
20+
#include <__type_traits/is_convertible.h>
1821
#include <__type_traits/remove_cvref.h>
1922
#include <__type_traits/void_t.h>
2023
#include <__utility/declval.h>
@@ -64,6 +67,55 @@ class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> {
6467
{
6568
return std::__invoke(get(), std::forward<_ArgTypes>(__args)...);
6669
}
70+
71+
#if _LIBCPP_STD_VER >= 26
72+
73+
// [refwrap.comparisons], comparisons
74+
75+
friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) {
76+
// Mandates: The expression x.get() == y.get() is well-formed and its result is convertible to bool.
77+
static_assert(is_convertible_v<decltype(__x.get() == __y.get()), bool>);
78+
79+
return __x.get() == __y.get();
80+
}
81+
82+
friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) {
83+
// Mandates: The expression x.get() == y is well-formed and its result is convertible to bool.
84+
static_assert(is_convertible_v<decltype(__x.get() == __y), bool>);
85+
86+
return __x.get() == __y;
87+
}
88+
89+
friend constexpr bool operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y)
90+
requires(!is_const_v<_Tp>)
91+
{
92+
// Constraints: is_const_v<T> is false.
93+
// Mandates: The expression x.get() == y.get() is well-formed and its result is convertible to bool.
94+
static_assert(is_convertible_v<decltype(__x.get() == __y.get()), bool>);
95+
96+
return __x.get() == __y.get();
97+
}
98+
99+
friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, reference_wrapper __y) {
100+
// return __synth_three_way_result(x.get(), y.get());
101+
return std::__synth_three_way(__x.get(), __y.get());
102+
}
103+
104+
friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, const _Tp& __y) {
105+
// return __synth_three_way_result(__x.get(), __y);
106+
return std::__synth_three_way(__x.get(), __y.get());
107+
}
108+
109+
friend constexpr __synth_three_way_result<_Tp> operator<=>(reference_wrapper __x, reference_wrapper<const _Tp> __y)
110+
requires(!is_const_v<_Tp>)
111+
{
112+
// Constraints: is_const_v<T> is false.
113+
114+
// return __synth_three_way_result(__x.get(), __y.get());
115+
return std::__synth_three_way(__x.get(), __y.get());
116+
}
117+
118+
#endif // _LIBCPP_STD_VER >= 26
67119
};
68120

69121
#if _LIBCPP_STD_VER >= 17

libcxx/include/functional

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ template <class T> struct unwrap_ref_decay : unwrap_reference<decay_t<T>> { };
7777
template <class T> using unwrap_reference_t = typename unwrap_reference<T>::type; // since C++20
7878
template <class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type; // since C++20
7979
80+
// [refwrap.comparisons], comparisons
81+
friend constexpr bool operator==(reference_wrapper, reference_wrapper); // Since C++26
82+
friend constexpr bool operator==(reference_wrapper, const T&); // Since C++26
83+
friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>); // Since C++26
84+
85+
friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper); // Since C++26
86+
friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, const T&); // Since C++26
87+
friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper<const T>); // Since C++26
88+
8089
template <class T> // <class T=void> in C++14
8190
struct plus {
8291
T operator()(const T& x, const T& y) const;

libcxx/include/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
524524
// # define __cpp_lib_ranges_concat 202403L
525525
# define __cpp_lib_ratio 202306L
526526
// # define __cpp_lib_rcu 202306L
527-
// # define __cpp_lib_reference_wrapper 202403L
527+
# define __cpp_lib_reference_wrapper 202403L
528528
# define __cpp_lib_saturation_arithmetic 202311L
529529
// # define __cpp_lib_smart_ptr_owner_equality 202306L
530530
# define __cpp_lib_span_at 202311L

libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -535,17 +535,11 @@
535535
# error "__cpp_lib_ranges should have the value 202207L in c++26"
536536
# endif
537537

538-
# if !defined(_LIBCPP_VERSION)
539-
# ifndef __cpp_lib_reference_wrapper
540-
# error "__cpp_lib_reference_wrapper should be defined in c++26"
541-
# endif
542-
# if __cpp_lib_reference_wrapper != 202403L
543-
# error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
544-
# endif
545-
# else // _LIBCPP_VERSION
546-
# ifdef __cpp_lib_reference_wrapper
547-
# error "__cpp_lib_reference_wrapper should not be defined because it is unimplemented in libc++!"
548-
# endif
538+
# ifndef __cpp_lib_reference_wrapper
539+
# error "__cpp_lib_reference_wrapper should be defined in c++26"
540+
# endif
541+
# if __cpp_lib_reference_wrapper != 202403L
542+
# error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
549543
# endif
550544

551545
# ifndef __cpp_lib_result_of_sfinae

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7433,17 +7433,11 @@
74337433
# endif
74347434
# endif
74357435

7436-
# if !defined(_LIBCPP_VERSION)
7437-
# ifndef __cpp_lib_reference_wrapper
7438-
# error "__cpp_lib_reference_wrapper should be defined in c++26"
7439-
# endif
7440-
# if __cpp_lib_reference_wrapper != 202403L
7441-
# error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
7442-
# endif
7443-
# else // _LIBCPP_VERSION
7444-
# ifdef __cpp_lib_reference_wrapper
7445-
# error "__cpp_lib_reference_wrapper should not be defined because it is unimplemented in libc++!"
7446-
# endif
7436+
# ifndef __cpp_lib_reference_wrapper
7437+
# error "__cpp_lib_reference_wrapper should be defined in c++26"
7438+
# endif
7439+
# if __cpp_lib_reference_wrapper != 202403L
7440+
# error "__cpp_lib_reference_wrapper should have the value 202403L in c++26"
74477441
# endif
74487442

74497443
# ifndef __cpp_lib_remove_cvref
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
11+
// <functional>
12+
13+
// class reference_wrapper
14+
15+
// // [refwrap.comparisons], comparisons
16+
17+
// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper); // Since C++26
18+
// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, const T&); // Since C++26
19+
// friend constexpr synth-three-way-result<T> operator<=>(reference_wrapper, reference_wrapper<const T>); // Since C++26
20+
21+
#include <cassert>
22+
#include <functional>
23+
24+
#include "test_macros.h"
25+
26+
constexpr bool test() { return true; }
27+
28+
int main(int, char**) {
29+
test();
30+
static_assert(test());
31+
32+
return 0;
33+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
11+
// <functional>
12+
13+
// class reference_wrapper
14+
15+
// // [refwrap.comparisons], comparisons
16+
// friend constexpr bool operator==(reference_wrapper, reference_wrapper); // Since C++26
17+
// friend constexpr bool operator==(reference_wrapper, const T&); // Since C++26
18+
// friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>); // Since C++26
19+
20+
#include <cassert>
21+
#include <functional>
22+
23+
#include "test_macros.h"
24+
25+
constexpr bool test() {
26+
{
27+
int i = 92;
28+
std::reference_wrapper<int> lhs{i};
29+
std::reference_wrapper<int> rhs = lhs;
30+
assert(lhs == rhs);
31+
}
32+
{
33+
int i = 92;
34+
std::reference_wrapper<int> lhs{i};
35+
int j = 84;
36+
std::reference_wrapper<int> rhs{j};
37+
assert(lhs != rhs);
38+
}
39+
40+
return true;
41+
}
42+
43+
int main(int, char**) {
44+
test();
45+
static_assert(test());
46+
47+
return 0;
48+
}

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,6 @@ def add_version_header(tc):
10401040
"name": "__cpp_lib_reference_wrapper",
10411041
"values": {"c++26": 202403}, # P2944R3: Comparisons for reference_wrapper
10421042
"headers": ["functional"],
1043-
"unimplemented": True,
10441043
},
10451044
{
10461045
"name": "__cpp_lib_remove_cvref",

0 commit comments

Comments
 (0)