Skip to content

Commit a7517fd

Browse files
committed
[libc++] P2944R3: Constrained comparisions - optional and reference_wrapper
Implements `variant`: https://wg21.link/P2944R3 Closes #136769
1 parent 953302e commit a7517fd

File tree

3 files changed

+139
-1
lines changed

3 files changed

+139
-1
lines changed

libcxx/include/variant

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ namespace std {
242242
# include <__type_traits/is_assignable.h>
243243
# include <__type_traits/is_constructible.h>
244244
# include <__type_traits/is_convertible.h>
245+
# include <__type_traits/is_core_convertible.h>
245246
# include <__type_traits/is_destructible.h>
246247
# include <__type_traits/is_nothrow_assignable.h>
247248
# include <__type_traits/is_nothrow_constructible.h>
@@ -1453,6 +1454,11 @@ struct __convert_to_bool {
14531454
};
14541455

14551456
template <class... _Types>
1457+
# if _LIBCPP_STD_VER >= 26
1458+
requires(requires(const _Types& __t) {
1459+
{ __t == __t } -> __core_convertible_to<bool>
1460+
} && ...)
1461+
# endif
14561462
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
14571463
using __variant_detail::__visitation::__variant;
14581464
if (__lhs.index() != __rhs.index())
@@ -1485,6 +1491,11 @@ operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
14851491
# endif // _LIBCPP_STD_VER >= 20
14861492

14871493
template <class... _Types>
1494+
# if _LIBCPP_STD_VER >= 26
1495+
requires(requires(const _Types& __t) {
1496+
{ __t != __t } -> __core_convertible_to<bool>
1497+
} && ...)
1498+
# endif
14881499
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
14891500
using __variant_detail::__visitation::__variant;
14901501
if (__lhs.index() != __rhs.index())
@@ -1495,6 +1506,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs,
14951506
}
14961507

14971508
template <class... _Types>
1509+
# if _LIBCPP_STD_VER >= 26
1510+
requires(requires(const _Types& __t) {
1511+
{ __t < __t } -> __core_convertible_to<bool>
1512+
} && ...)
1513+
# endif
14981514
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
14991515
using __variant_detail::__visitation::__variant;
15001516
if (__rhs.valueless_by_exception())
@@ -1509,6 +1525,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs,
15091525
}
15101526

15111527
template <class... _Types>
1528+
# if _LIBCPP_STD_VER >= 26
1529+
requires(requires(const _Types& __t) {
1530+
{ __t > __t } -> __core_convertible_to<bool>
1531+
} && ...)
1532+
# endif
15121533
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
15131534
using __variant_detail::__visitation::__variant;
15141535
if (__lhs.valueless_by_exception())
@@ -1523,6 +1544,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs,
15231544
}
15241545

15251546
template <class... _Types>
1547+
# if _LIBCPP_STD_VER >= 26
1548+
requires(requires(const _Types& __t) {
1549+
{ __t <= __t } -> __core_convertible_to<bool>
1550+
} && ...)
1551+
# endif
15261552
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
15271553
using __variant_detail::__visitation::__variant;
15281554
if (__lhs.valueless_by_exception())
@@ -1537,6 +1563,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs,
15371563
}
15381564

15391565
template <class... _Types>
1566+
# if _LIBCPP_STD_VER >= 26
1567+
requires(requires(const _Types& __t) {
1568+
{ __t >= __t } -> __core_convertible_to<bool>
1569+
} && ...)
1570+
# endif
15401571
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
15411572
using __variant_detail::__visitation::__variant;
15421573
if (__rhs.valueless_by_exception())

libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,51 @@
3939
#include <utility>
4040
#include <variant>
4141

42+
#include "test_comparisons.h"
4243
#include "test_macros.h"
4344

45+
#if TEST_STD_VER >= 26
46+
47+
// Test SFINAE.
48+
49+
// ==
50+
static_assert(HasOperatorEqual<std::variant<int>>);
51+
static_assert(HasOperatorEqual<std::variant<EqualityComparable>>);
52+
53+
static_assert(!HasOperatorEqual<std::variant<NonComparable>>);
54+
55+
// >
56+
static_assert(HasOperatorGreaterThan<std::variant<int>>);
57+
static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable>>);
58+
59+
static_assert(!HasOperatorGreaterThan<std::variant<NonComparable>>);
60+
61+
// >=
62+
static_assert(HasOperatorGreaterThanEqual<std::variant<int>>);
63+
static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable>>);
64+
65+
static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable>>);
66+
67+
// <
68+
static_assert(HasOperatorLessThan<std::variant<int>>);
69+
static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable>>);
70+
71+
static_assert(!HasOperatorLessThan<std::variant<NonComparable>>);
72+
73+
// <=
74+
static_assert(HasOperatorLessThanEqual<std::variant<int>>);
75+
static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable>>);
76+
77+
static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable>>);
78+
79+
// !=
80+
static_assert(HasOperatorNotEqual<std::variant<int>>);
81+
static_assert(HasOperatorNotEqual<std::variant<EqualityComparable>>);
82+
83+
static_assert(!HasOperatorNotEqual<std::variant<NonComparable>>);
84+
85+
#endif
86+
4487
#ifndef TEST_HAS_NO_EXCEPTIONS
4588
struct MakeEmptyT {
4689
MakeEmptyT() = default;

libcxx/test/support/test_comparisons.h

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,70 @@ 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 HasOperatorGreaterThan = requires(T1 t1, T2 t2) { t1 > t2; };
276+
277+
template <typename T1, typename T2 = T1>
278+
concept HasOperatorGreaterThanEqual = requires(T1 t1, T2 t2) { t1 >= t2; };
279+
template <typename T1, typename T2 = T1>
280+
concept HasOperatorLessThan = requires(T1 t1, T2 t2) { t1 < t2; };
281+
282+
template <typename T1, typename T2 = T1>
283+
concept HasOperatorLessThanEqual = requires(T1 t1, T2 t2) { t1 <= t2; };
284+
285+
template <typename T1, typename T2 = T1>
286+
concept HasOperatorNotEqual = requires(T1 t1, T2 t2) { t1 != t2; };
287+
288+
template <typename T1, typename T2 = T1>
289+
concept HasOperatorSpaceship = requires(T1 t1, T2 t2) { t1 <=> t2; };
290+
291+
struct NonComparable {};
292+
static_assert(!std::equality_comparable<NonComparable>);
293+
static_assert(!HasOperatorEqual<NonComparable>);
294+
static_assert(!HasOperatorGreaterThan<NonComparable>);
295+
static_assert(!HasOperatorGreaterThanEqual<NonComparable>);
296+
static_assert(!HasOperatorLessThan<NonComparable>);
297+
static_assert(!HasOperatorLessThanEqual<NonComparable>);
298+
static_assert(!HasOperatorNotEqual<NonComparable>);
299+
static_assert(!HasOperatorSpaceship<NonComparable>);
300+
301+
class EqualityComparable {
302+
public:
303+
constexpr EqualityComparable(int value) : value_{value} {};
304+
305+
friend constexpr bool operator==(const EqualityComparable&, const EqualityComparable&) noexcept = default;
306+
307+
private:
308+
int value_;
309+
};
310+
static_assert(std::equality_comparable<EqualityComparable>);
311+
static_assert(HasOperatorEqual<EqualityComparable>);
312+
static_assert(HasOperatorNotEqual<EqualityComparable>);
313+
314+
class ThreeWayComparable {
315+
public:
316+
constexpr ThreeWayComparable(int value) : value_{value} {};
317+
318+
friend constexpr bool operator==(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
319+
friend constexpr std::strong_ordering
320+
operator<=>(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
321+
322+
private:
323+
int value_;
324+
};
325+
static_assert(std::equality_comparable<ThreeWayComparable>);
326+
static_assert(std::three_way_comparable<ThreeWayComparable>);
327+
static_assert(HasOperatorEqual<ThreeWayComparable>);
328+
static_assert(HasOperatorGreaterThan<ThreeWayComparable>);
329+
static_assert(HasOperatorGreaterThanEqual<ThreeWayComparable>);
330+
static_assert(HasOperatorLessThan<ThreeWayComparable>);
331+
static_assert(HasOperatorLessThanEqual<ThreeWayComparable>);
332+
static_assert(HasOperatorNotEqual<ThreeWayComparable>);
333+
static_assert(HasOperatorSpaceship<ThreeWayComparable>);
334+
335+
#endif // TEST_STD_VER >= 20
272336

273337
#endif // TEST_COMPARISONS_H

0 commit comments

Comments
 (0)