Skip to content

[libc++] P2944R3: Constrained comparisions - variant #141396

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"`P2248R8 <https://wg21.link/P2248R8>`__","Enabling list-initialization for algorithms","2024-03 (Tokyo)","","",""
"`P2810R4 <https://wg21.link/P2810R4>`__","``is_debugger_present`` ``is_replaceable``","2024-03 (Tokyo)","","",""
"`P1068R11 <https://wg21.link/P1068R11>`__","Vector API for random number generation","2024-03 (Tokyo)","","",""
"`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","","The changes to ``optional``, ``tuple`` and ``variant`` are not yet implemented"
"`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","","The changes to ``optional`` and ``tuple`` are not yet implemented"
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","",""
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19",""
"","","","","",""
Expand Down
31 changes: 31 additions & 0 deletions libcxx/include/variant
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ namespace std {
# include <__type_traits/is_assignable.h>
# include <__type_traits/is_constructible.h>
# include <__type_traits/is_convertible.h>
# include <__type_traits/is_core_convertible.h>
# include <__type_traits/is_destructible.h>
# include <__type_traits/is_nothrow_assignable.h>
# include <__type_traits/is_nothrow_constructible.h>
Expand Down Expand Up @@ -1442,6 +1443,11 @@ struct __convert_to_bool {
};

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t == __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__lhs.index() != __rhs.index())
Expand Down Expand Up @@ -1474,6 +1480,11 @@ operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
# endif // _LIBCPP_STD_VER >= 20

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t != __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__lhs.index() != __rhs.index())
Expand All @@ -1484,6 +1495,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs,
}

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t < __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__rhs.valueless_by_exception())
Expand All @@ -1498,6 +1514,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs,
}

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t > __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__lhs.valueless_by_exception())
Expand All @@ -1512,6 +1533,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs,
}

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t <= __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__lhs.valueless_by_exception())
Expand All @@ -1526,6 +1552,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs,
}

template <class... _Types>
# if _LIBCPP_STD_VER >= 26
requires(requires(const _Types& __t) {
{ __t >= __t } -> __core_convertible_to<bool>;
} && ...)
# endif
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;
if (__rhs.valueless_by_exception())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,57 @@
#include <utility>
#include <variant>

#include "test_comparisons.h"
#include "test_macros.h"

#if TEST_STD_VER >= 26

// Test SFINAE.

// ==
static_assert(HasOperatorEqual<std::variant<EqualityComparable>>);
static_assert(HasOperatorEqual<std::variant<EqualityComparable, int, long>>);

static_assert(!HasOperatorEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorEqual<std::variant<NonComparable, EqualityComparable>>);

// >
static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable, int, long>>);

static_assert(!HasOperatorGreaterThan<std::variant<NonComparable>>);
static_assert(!HasOperatorGreaterThan<std::variant<NonComparable, ThreeWayComparable>>);

// >=
static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable, int, long>>);

static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable, ThreeWayComparable>>);

// <
static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable, int, long>>);

static_assert(!HasOperatorLessThan<std::variant<NonComparable>>);
static_assert(!HasOperatorLessThan<std::variant<NonComparable, ThreeWayComparable>>);

// <=
static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable, int, long>>);

static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable, ThreeWayComparable>>);

// !=
static_assert(HasOperatorNotEqual<std::variant<EqualityComparable>>);
static_assert(HasOperatorNotEqual<std::variant<EqualityComparable, int, long>>);

static_assert(!HasOperatorNotEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorNotEqual<std::variant<NonComparable, EqualityComparable>>);

#endif

#ifndef TEST_HAS_NO_EXCEPTIONS
struct MakeEmptyT {
MakeEmptyT() = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@

#include "test_macros.h"


#if TEST_STD_VER >= 26
// expected-no-diagnostics
#else
struct MyBoolExplicit {
bool value;
constexpr explicit MyBoolExplicit(bool v) : value(v) {}
Expand Down Expand Up @@ -70,8 +72,7 @@ inline constexpr MyBoolExplicit operator>=(const ComparesToMyBoolExplicit& LHS,
return MyBoolExplicit(LHS.value >= RHS.value);
}


int main(int, char**) {
void test() {
using V = std::variant<int, ComparesToMyBoolExplicit>;
V v1(42);
V v2(101);
Expand All @@ -83,6 +84,6 @@ int main(int, char**) {
(void)(v1 <= v2); // expected-note {{here}}
(void)(v1 > v2); // expected-note {{here}}
(void)(v1 >= v2); // expected-note {{here}}

return 0;
}

#endif
41 changes: 41 additions & 0 deletions libcxx/test/support/test_comparisons.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,31 @@ struct PartialOrder {
template <typename T1, typename T2 = T1>
concept HasOperatorEqual = requires(T1 t1, T2 t2) { t1 == t2; };

template <typename T1, typename T2 = T1>
concept HasOperatorGreaterThan = requires(T1 t1, T2 t2) { t1 > t2; };

template <typename T1, typename T2 = T1>
concept HasOperatorGreaterThanEqual = requires(T1 t1, T2 t2) { t1 >= t2; };
template <typename T1, typename T2 = T1>
concept HasOperatorLessThan = requires(T1 t1, T2 t2) { t1 < t2; };

template <typename T1, typename T2 = T1>
concept HasOperatorLessThanEqual = requires(T1 t1, T2 t2) { t1 <= t2; };

template <typename T1, typename T2 = T1>
concept HasOperatorNotEqual = requires(T1 t1, T2 t2) { t1 != t2; };

template <typename T1, typename T2 = T1>
concept HasOperatorSpaceship = requires(T1 t1, T2 t2) { t1 <=> t2; };

struct NonComparable {};
static_assert(!std::equality_comparable<NonComparable>);
static_assert(!HasOperatorEqual<NonComparable>);
static_assert(!HasOperatorGreaterThan<NonComparable>);
static_assert(!HasOperatorGreaterThanEqual<NonComparable>);
static_assert(!HasOperatorLessThan<NonComparable>);
static_assert(!HasOperatorLessThanEqual<NonComparable>);
static_assert(!HasOperatorNotEqual<NonComparable>);
static_assert(!HasOperatorSpaceship<NonComparable>);

class EqualityComparable {
Expand All @@ -290,6 +309,28 @@ class EqualityComparable {
};
static_assert(std::equality_comparable<EqualityComparable>);
static_assert(HasOperatorEqual<EqualityComparable>);
static_assert(HasOperatorNotEqual<EqualityComparable>);

class ThreeWayComparable {
public:
constexpr ThreeWayComparable(int value) : value_{value} {};

friend constexpr bool operator==(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
friend constexpr std::strong_ordering
operator<=>(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;

private:
int value_;
};
static_assert(std::equality_comparable<ThreeWayComparable>);
static_assert(std::three_way_comparable<ThreeWayComparable>);
static_assert(HasOperatorEqual<ThreeWayComparable>);
static_assert(HasOperatorGreaterThan<ThreeWayComparable>);
static_assert(HasOperatorGreaterThanEqual<ThreeWayComparable>);
static_assert(HasOperatorLessThan<ThreeWayComparable>);
static_assert(HasOperatorLessThanEqual<ThreeWayComparable>);
static_assert(HasOperatorNotEqual<ThreeWayComparable>);
static_assert(HasOperatorSpaceship<ThreeWayComparable>);

#endif // TEST_STD_VER >= 20

Expand Down
Loading