Skip to content

Commit a0c00cc

Browse files
H-G-HristovZingamphilnik777
authored
[libc++] P2944R3: Constrained comparisons - update reference_wrapper implementation (#139368)
Updates the implementation `std::reference_wrapper` - [P2944R3](https://wg21.link/P2944R3) as discussed in #117664 (comment) This PR also refactors the tests in preparation to implements the constrained comparisons for `optional`, `variant` etc. - Moves the test helpers (concepts and types) for testing constrained comparisons to `test_comparisons.h`. - Updates the `std::reference_wrapper` implementation to use the concept `__core_convertible_to<bool>` as per comments in #135759. Closes #138233 # References: - [refwrap.comparisons](https://wg21.link/refwrap.comparisons) --------- Co-authored-by: Hristo Hristov <[email protected]> Co-authored-by: Nikolas Klauser <[email protected]>
1 parent 24c8d90 commit a0c00cc

13 files changed

+59
-126
lines changed

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>`__","Enabling list-initialization for algorithms","2024-03 (Tokyo)","","",""
6060
"`P2810R4 <https://wg21.link/P2810R4>`__","``is_debugger_present`` ``is_replaceable``","2024-03 (Tokyo)","","",""
6161
"`P1068R11 <https://wg21.link/P1068R11>`__","Vector API for random number generation","2024-03 (Tokyo)","","",""
62-
"`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","","Implemented changes to ``reference_wrapper`` and ``pair``"
62+
"`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","","The changes to ``optional``, ``tuple`` and ``variant`` are not yet implemented"
6363
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","",""
6464
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19",""
6565
"","","","","",""

libcxx/include/__functional/reference_wrapper.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
#define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
1212

1313
#include <__compare/synth_three_way.h>
14-
#include <__concepts/boolean_testable.h>
1514
#include <__config>
1615
#include <__functional/weak_result_type.h>
1716
#include <__memory/addressof.h>
1817
#include <__type_traits/desugars_to.h>
1918
#include <__type_traits/enable_if.h>
2019
#include <__type_traits/invoke.h>
2120
#include <__type_traits/is_const.h>
21+
#include <__type_traits/is_core_convertible.h>
2222
#include <__type_traits/remove_cvref.h>
2323
#include <__type_traits/void_t.h>
2424
#include <__utility/declval.h>
@@ -75,23 +75,23 @@ class reference_wrapper : public __weak_result_type<_Tp> {
7575

7676
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y)
7777
requires requires {
78-
{ __x.get() == __y.get() } -> __boolean_testable;
78+
{ __x.get() == __y.get() } -> __core_convertible_to<bool>;
7979
}
8080
{
8181
return __x.get() == __y.get();
8282
}
8383

8484
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y)
8585
requires requires {
86-
{ __x.get() == __y } -> __boolean_testable;
86+
{ __x.get() == __y } -> __core_convertible_to<bool>;
8787
}
8888
{
8989
return __x.get() == __y;
9090
}
9191

9292
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y)
9393
requires(!is_const_v<_Tp>) && requires {
94-
{ __x.get() == __y.get() } -> __boolean_testable;
94+
{ __x.get() == __y.get() } -> __core_convertible_to<bool>;
9595
}
9696
{
9797
return __x.get() == __y.get();

libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ constexpr std::size_t N{1};
2626
static_assert(std::three_way_comparable<std::array<int, N>>);
2727

2828
// Thanks to SFINAE, the following is not a compiler error but returns `false`
29-
struct NonComparable {};
3029
static_assert(!std::three_way_comparable<std::array<NonComparable, N>>);
3130

3231
// Implementation detail of `test_sequence_container_array_spaceship`

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.refwrap.const_ref.pass.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -23,16 +23,13 @@
2323
#include "test_comparisons.h"
2424
#include "test_macros.h"
2525

26-
#include "helper_concepts.h"
27-
#include "helper_types.h"
28-
2926
// Test SFINAE.
3027

31-
static_assert(HasSpaceshipOperatorWithInt<std::reference_wrapper<StrongOrder>>);
32-
static_assert(HasSpaceshipOperatorWithInt<std::reference_wrapper<WeakOrder>>);
33-
static_assert(HasSpaceshipOperatorWithInt<std::reference_wrapper<PartialOrder>>);
28+
static_assert(HasOperatorSpaceship<std::reference_wrapper<StrongOrder>, int>);
29+
static_assert(HasOperatorSpaceship<std::reference_wrapper<WeakOrder>, int>);
30+
static_assert(HasOperatorSpaceship<std::reference_wrapper<PartialOrder>, int>);
3431

35-
static_assert(!HasSpaceshipOperatorWithInt<std::reference_wrapper<NonComparable>>);
32+
static_assert(!HasOperatorSpaceship<std::reference_wrapper<NonComparable>, int>);
3633

3734
// Test comparisons.
3835

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.refwrap.refwrap.pass.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -22,17 +22,13 @@
2222

2323
#include "test_comparisons.h"
2424
#include "test_macros.h"
25-
26-
#include "helper_concepts.h"
27-
#include "helper_types.h"
28-
2925
// Test SFINAE.
3026

31-
static_assert(std::three_way_comparable<std::reference_wrapper<StrongOrder>>);
32-
static_assert(std::three_way_comparable<std::reference_wrapper<WeakOrder>>);
33-
static_assert(std::three_way_comparable<std::reference_wrapper<PartialOrder>>);
27+
static_assert(HasOperatorSpaceship<std::reference_wrapper<StrongOrder>>);
28+
static_assert(HasOperatorSpaceship<std::reference_wrapper<WeakOrder>>);
29+
static_assert(HasOperatorSpaceship<std::reference_wrapper<PartialOrder>>);
3430

35-
static_assert(!std::three_way_comparable<std::reference_wrapper<NonComparable>>);
31+
static_assert(!HasOperatorSpaceship<std::reference_wrapper<NonComparable>>);
3632

3733
// Test comparisons.
3834

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/compare.three_way.refwrap.refwrap_const.pass.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -23,18 +23,15 @@
2323
#include "test_comparisons.h"
2424
#include "test_macros.h"
2525

26-
#include "helper_concepts.h"
27-
#include "helper_types.h"
28-
2926
// Test SFINAE.
3027

31-
static_assert(std::three_way_comparable_with<std::reference_wrapper<StrongOrder>, const StrongOrder>);
32-
static_assert(std::three_way_comparable_with<std::reference_wrapper<WeakOrder>, const WeakOrder>);
33-
static_assert(std::three_way_comparable_with<std::reference_wrapper<PartialOrder>, const PartialOrder>);
28+
static_assert(HasOperatorSpaceship<std::reference_wrapper<StrongOrder>, std::reference_wrapper<const StrongOrder>>);
29+
static_assert(HasOperatorSpaceship<std::reference_wrapper<WeakOrder>, std::reference_wrapper<const WeakOrder>>);
30+
static_assert(HasOperatorSpaceship<std::reference_wrapper<PartialOrder>, std::reference_wrapper<const PartialOrder>>);
3431

35-
static_assert(!std::three_way_comparable_with<std::reference_wrapper<StrongOrder>, const NonComparable>);
36-
static_assert(!std::three_way_comparable_with<std::reference_wrapper<WeakOrder>, const NonComparable>);
37-
static_assert(!std::three_way_comparable_with<std::reference_wrapper<PartialOrder>, const NonComparable>);
32+
static_assert(!HasOperatorSpaceship<std::reference_wrapper<StrongOrder>, std::reference_wrapper<const NonComparable>>);
33+
static_assert(!HasOperatorSpaceship<std::reference_wrapper<WeakOrder>, std::reference_wrapper<const NonComparable>>);
34+
static_assert(!HasOperatorSpaceship<std::reference_wrapper<PartialOrder>, std::reference_wrapper<const NonComparable>>);
3835

3936
// Test comparisons.
4037

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.refwrap.const_ref.pass.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -23,14 +23,13 @@
2323
#include "test_comparisons.h"
2424
#include "test_macros.h"
2525

26-
#include "helper_concepts.h"
27-
#include "helper_types.h"
28-
2926
// Test SFINAE.
3027

31-
static_assert(HasEqualityOperatorWithInt<std::reference_wrapper<EqualityComparable>>);
28+
static_assert(HasOperatorEqual<std::reference_wrapper<EqualityComparable>>);
29+
static_assert(HasOperatorEqual<std::reference_wrapper<EqualityComparable>, int>);
3230

33-
static_assert(!HasEqualityOperatorWithInt<std::reference_wrapper<NonComparable>>);
31+
static_assert(!HasOperatorEqual<std::reference_wrapper<NonComparable>>);
32+
static_assert(!HasOperatorEqual<std::reference_wrapper<NonComparable>, int>);
3433

3534
// Test equality.
3635

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.refwrap.refwrap.pass.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -22,14 +22,11 @@
2222
#include "test_comparisons.h"
2323
#include "test_macros.h"
2424

25-
#include "helper_concepts.h"
26-
#include "helper_types.h"
27-
2825
// Test SFINAE.
2926

30-
static_assert(std::equality_comparable<std::reference_wrapper<EqualityComparable>>);
27+
static_assert(HasOperatorEqual<std::reference_wrapper<EqualityComparable>>);
3128

32-
static_assert(!std::equality_comparable<std::reference_wrapper<NonComparable>>);
29+
static_assert(!HasOperatorEqual<std::reference_wrapper<NonComparable>>);
3330

3431
// Test equality.
3532

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/equal.refwrap.refwrap_const.pass.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
9+
// REQUIRES: std-at-least-c++26
1010

1111
// <functional>
1212

@@ -23,16 +23,13 @@
2323
#include "test_comparisons.h"
2424
#include "test_macros.h"
2525

26-
#include "helper_concepts.h"
27-
#include "helper_types.h"
28-
2926
// Test SFINAE.
3027

31-
static_assert(std::equality_comparable_with<std::reference_wrapper<EqualityComparable>,
32-
std::reference_wrapper<const EqualityComparable>>);
28+
static_assert(
29+
HasOperatorEqual<std::reference_wrapper<EqualityComparable>, std::reference_wrapper<const EqualityComparable>>);
3330

34-
static_assert(!std::equality_comparable_with<std::reference_wrapper<EqualityComparable>,
35-
std::reference_wrapper<const NonComparable>>);
31+
static_assert(
32+
!HasOperatorEqual<std::reference_wrapper<EqualityComparable>, std::reference_wrapper<const NonComparable>>);
3633

3734
// Test equality.
3835

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/helper_concepts.h

Lines changed: 0 additions & 38 deletions
This file was deleted.

libcxx/test/std/utilities/function.objects/refwrap/refwrap.comparissons/helper_types.h

Lines changed: 0 additions & 30 deletions
This file was deleted.

libcxx/test/support/test_comparisons.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,29 @@ struct PartialOrder {
268268
}
269269
};
270270

271-
#endif
271+
template <typename T1, typename T2 = T1>
272+
concept HasOperatorEqual = requires(T1 t1, T2 t2) { t1 == t2; };
273+
274+
template <typename T1, typename T2 = T1>
275+
concept HasOperatorSpaceship = requires(T1 t1, T2 t2) { t1 <=> t2; };
276+
277+
struct NonComparable {};
278+
static_assert(!std::equality_comparable<NonComparable>);
279+
static_assert(!HasOperatorEqual<NonComparable>);
280+
static_assert(!HasOperatorSpaceship<NonComparable>);
281+
282+
class EqualityComparable {
283+
public:
284+
constexpr EqualityComparable(int value) : value_{value} {};
285+
286+
friend constexpr bool operator==(const EqualityComparable&, const EqualityComparable&) noexcept = default;
287+
288+
private:
289+
int value_;
290+
};
291+
static_assert(std::equality_comparable<EqualityComparable>);
292+
static_assert(HasOperatorEqual<EqualityComparable>);
293+
294+
#endif // TEST_STD_VER >= 20
272295

273296
#endif // TEST_COMPARISONS_H

libcxx/test/support/test_container_comparisons.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ constexpr bool test_sequence_container_spaceship() {
8888
std::weak_ordering>();
8989

9090
// Thanks to SFINAE, the following is not a compiler error but returns `false`
91-
struct NonComparable {};
9291
static_assert(!std::three_way_comparable<Container<NonComparable>>);
9392

9493
return true;
@@ -163,7 +162,6 @@ constexpr void test_sequence_container_adaptor_spaceship_with_type() {
163162
template <template <typename...> typename ContainerAdaptor, template <typename...> typename Container>
164163
constexpr bool test_sequence_container_adaptor_spaceship() {
165164
// Thanks to SFINAE, the following is not a compiler error but returns `false`
166-
struct NonComparable {};
167165
static_assert(!std::three_way_comparable<ContainerAdaptor<NonComparable>>);
168166

169167
// The container should fulfill `std::three_way_comparable`
@@ -301,7 +299,6 @@ constexpr void test_ordered_map_container_spaceship_with_type(Compare comp) {
301299
template <template <typename...> typename Container>
302300
constexpr bool test_ordered_map_container_spaceship() {
303301
// Thanks to SFINAE, the following is not a compiler error but returns `false`
304-
struct NonComparable {};
305302
static_assert(!std::three_way_comparable<Container<int, NonComparable>>);
306303

307304
// The container should fulfill `std::three_way_comparable`
@@ -444,7 +441,6 @@ constexpr void test_ordered_set_spaceship_with_type(Compare comp) {
444441
template <template <typename...> typename Container>
445442
constexpr bool test_ordered_set_container_spaceship() {
446443
// Thanks to SFINAE, the following is not a compiler error but returns `false`
447-
struct NonComparable {};
448444
static_assert(!std::three_way_comparable<Container<NonComparable>>);
449445

450446
// The container should fulfill `std::three_way_comparable`

0 commit comments

Comments
 (0)