[libcxx-commits] [libcxx] [libc++][spaceship] P2404R3: Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with (PR #99420)
Janet Cobb via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 17 20:28:20 PDT 2024
https://github.com/randomnetcat updated https://github.com/llvm/llvm-project/pull/99420
>From 363738b998edbb39e6836a320d9ebc9c0c3cb28d Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 21:53:02 -0400
Subject: [PATCH 1/2] P2404R3: Move-only types for relational concepts
---
libcxx/docs/ReleaseNotes/19.rst | 1 +
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
libcxx/docs/Status/SpaceshipPapers.csv | 2 +-
libcxx/include/CMakeLists.txt | 1 +
.../include/__compare/three_way_comparable.h | 17 +++++++
.../__concepts/comparison_common_type.h | 39 ++++++++++++++++
.../include/__concepts/equality_comparable.h | 19 ++++++++
libcxx/include/module.modulemap | 45 ++++++++++---------
.../equality_comparable_with.compile.pass.cpp | 10 +++++
...three_way_comparable_with.compile.pass.cpp | 28 ++++++++++++
libcxx/test/support/compare_types.h | 23 ++++++++++
11 files changed, 163 insertions(+), 24 deletions(-)
create mode 100644 libcxx/include/__concepts/comparison_common_type.h
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index e6d8acb74aeb2..1699c97652488 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -55,6 +55,7 @@ Implemented Papers
- P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant``
- P0019R8 - ``std::atomic_ref``
- P2389R2 - Alias template ``dims`` for the ``extents`` of ``mdspan``
+- P2404R3 - Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 4f589cd938d7c..bc13e4d9ebfd3 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -67,7 +67,7 @@
"`P2302R4 <https://wg21.link/P2302R4>`__","LWG","``std::ranges::contains``","July 2022","|Complete|","19.0","|ranges|"
"`P2322R6 <https://wg21.link/P2322R6>`__","LWG","``ranges::fold``","July 2022","","","|ranges|"
"`P2374R4 <https://wg21.link/P2374R4>`__","LWG","``views::cartesian_product``","July 2022","","","|ranges|"
-"`P2404R3 <https://wg21.link/P2404R3>`__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","",""
+"`P2404R3 <https://wg21.link/P2404R3>`__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","|Complete|","19.0"
"`P2408R5 <https://wg21.link/P2408R5>`__","LWG","Ranges iterators as inputs to non-Ranges algorithms","July 2022","","","|ranges|"
"`P2417R2 <https://wg21.link/P2417R2>`__","LWG","A more ``constexpr`` ``bitset``","July 2022","|Complete|","16.0"
"`P2419R2 <https://wg21.link/P2419R2>`__","LWG","Clarify handling of encodings in localized formatting of chrono types","July 2022","",""
diff --git a/libcxx/docs/Status/SpaceshipPapers.csv b/libcxx/docs/Status/SpaceshipPapers.csv
index 39e1f968c1754..5fbf6a53b6db7 100644
--- a/libcxx/docs/Status/SpaceshipPapers.csv
+++ b/libcxx/docs/Status/SpaceshipPapers.csv
@@ -1,6 +1,6 @@
"Number","Name","Status","First released version"
`P1614R2 <https://wg21.link/P1614R2>`_,The Mothership has Landed,|In Progress|,
-`P2404R3 <https://wg21.link/P2404R3>`_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types",,
+`P2404R3 <https://wg21.link/P2404R3>`_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types","|Complete|","19.0"
`LWG3330 <https://wg21.link/LWG3330>`_,Include ``<compare>`` from most library headers,"|Complete|","13.0"
`LWG3347 <https://wg21.link/LWG3347>`_,"``std::pair<T, U>`` now requires ``T`` and ``U`` to be *less-than-comparable*",|Nothing To Do|,
`LWG3350 <https://wg21.link/LWG3350>`_,Simplify return type of ``lexicographical_compare_three_way``,|Nothing To Do|,
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cd64fe91449c2..e618847b1e27c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -296,6 +296,7 @@ set(files
__concepts/class_or_enum.h
__concepts/common_reference_with.h
__concepts/common_with.h
+ __concepts/comparison_common_type.h
__concepts/constructible.h
__concepts/convertible_to.h
__concepts/copyable.h
diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index 7a44ea9158a6f..3b14725be3309 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -12,6 +12,7 @@
#include <__compare/common_comparison_category.h>
#include <__compare/ordering.h>
#include <__concepts/common_reference_with.h>
+#include <__concepts/comparison_common_type.h>
#include <__concepts/equality_comparable.h>
#include <__concepts/same_as.h>
#include <__concepts/totally_ordered.h>
@@ -37,6 +38,20 @@ concept three_way_comparable =
{ __a <=> __b } -> __compares_as<_Cat>;
};
+# if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up, class _cat = partial_ordering>
+concept three_way_comparable_with =
+ three_way_comparable<_Tp, _cat> && three_way_comparable<_Up, _cat> && __comparison_common_type_with<_Tp, _Up> &&
+ three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _cat> &&
+ __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
+ requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
+ { __t <=> __u } -> __compares_as<_cat>;
+ { __u <=> __t } -> __compares_as<_cat>;
+ };
+
+# else
+
template <class _Tp, class _Up, class _Cat = partial_ordering>
concept three_way_comparable_with =
three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> &&
@@ -48,6 +63,8 @@ concept three_way_comparable_with =
{ __u <=> __t } -> __compares_as<_Cat>;
};
+# endif // _LIBCPP_STD_VER >= 23
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
new file mode 100644
index 0000000000000..a1f246d2a6dca
--- /dev/null
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+
+#include "__concepts/convertible_to.h"
+#include "__concepts/same_as.h"
+#include "__config"
+#include "__type_traits/common_reference.h"
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up, class _C = common_reference_t<const _Tp&, const _Up&>>
+concept __comparison_common_type_with_impl =
+ same_as<common_reference_t<const _Tp&, const _Up&>, common_reference_t<const _Up&, const _Tp&>> && requires {
+ requires convertible_to<const _Tp&, const _C&> || convertible_to<_Tp, const _C&>;
+ requires convertible_to<const _Up&, const _C&> || convertible_to<_Up, const _C&>;
+ };
+
+template <class _Tp, class _Up>
+concept __comparison_common_type_with = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h
index 278fc76409289..1904b2e451a8d 100644
--- a/libcxx/include/__concepts/equality_comparable.h
+++ b/libcxx/include/__concepts/equality_comparable.h
@@ -11,6 +11,7 @@
#include <__concepts/boolean_testable.h>
#include <__concepts/common_reference_with.h>
+#include <__concepts/comparison_common_type.h>
#include <__config>
#include <__type_traits/common_reference.h>
#include <__type_traits/make_const_lvalue_ref.h>
@@ -37,6 +38,22 @@ concept __weakly_equality_comparable_with =
template <class _Tp>
concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
+# if _LIBCPP_STD_VER >= 23
+
+// clang-format off
+template <class _Tp, class _Up>
+concept equality_comparable_with =
+ equality_comparable<_Tp> && equality_comparable<_Up> &&
+ __comparison_common_type_with<_Tp, _Up> &&
+ equality_comparable<
+ common_reference_t<
+ __make_const_lvalue_ref<_Tp>,
+ __make_const_lvalue_ref<_Up>>> &&
+ __weakly_equality_comparable_with<_Tp, _Up>;
+// clang-format on
+
+# else
+
// clang-format off
template <class _Tp, class _Up>
concept equality_comparable_with =
@@ -49,6 +66,8 @@ concept equality_comparable_with =
__weakly_equality_comparable_with<_Tp, _Up>;
// clang-format on
+# endif // _LIBCPP_STD_VER >= 23
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index f4aaa14c1c2ee..eabb32daf2c96 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1173,43 +1173,44 @@ module std_private_compare_weak_order [system] { header "__c
module std_private_complex_complex_fwd [system] { header "__fwd/complex.h" }
-module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" }
-module std_private_concepts_assignable [system] { header "__concepts/assignable.h" }
-module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" }
-module std_private_concepts_class_or_enum [system] { header "__concepts/class_or_enum.h" }
-module std_private_concepts_common_reference_with [system] { header "__concepts/common_reference_with.h" }
-module std_private_concepts_common_with [system] { header "__concepts/common_with.h" }
-module std_private_concepts_constructible [system] {
+module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" }
+module std_private_concepts_assignable [system] { header "__concepts/assignable.h" }
+module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" }
+module std_private_concepts_class_or_enum [system] { header "__concepts/class_or_enum.h" }
+module std_private_concepts_common_reference_with [system] { header "__concepts/common_reference_with.h" }
+module std_private_concepts_common_with [system] { header "__concepts/common_with.h" }
+module std_private_cooncepts_comparison_common_type [system] { header "__concepts/comparison_common_type.h" }
+module std_private_concepts_constructible [system] {
header "__concepts/constructible.h"
export std_private_concepts_destructible
}
-module std_private_concepts_convertible_to [system] { header "__concepts/convertible_to.h" }
-module std_private_concepts_copyable [system] { header "__concepts/copyable.h" }
-module std_private_concepts_derived_from [system] { header "__concepts/derived_from.h" }
-module std_private_concepts_destructible [system] {
+module std_private_concepts_convertible_to [system] { header "__concepts/convertible_to.h" }
+module std_private_concepts_copyable [system] { header "__concepts/copyable.h" }
+module std_private_concepts_derived_from [system] { header "__concepts/derived_from.h" }
+module std_private_concepts_destructible [system] {
header "__concepts/destructible.h"
export std_private_type_traits_is_nothrow_destructible
}
-module std_private_concepts_different_from [system] { header "__concepts/different_from.h" }
-module std_private_concepts_equality_comparable [system] {
+module std_private_concepts_different_from [system] { header "__concepts/different_from.h" }
+module std_private_concepts_equality_comparable [system] {
header "__concepts/equality_comparable.h"
export std_private_type_traits_common_reference
}
-module std_private_concepts_invocable [system] { header "__concepts/invocable.h" }
-module std_private_concepts_movable [system] {
+module std_private_concepts_invocable [system] { header "__concepts/invocable.h" }
+module std_private_concepts_movable [system] {
header "__concepts/movable.h"
export std_private_type_traits_is_object
}
-module std_private_concepts_predicate [system] { header "__concepts/predicate.h" }
-module std_private_concepts_regular [system] { header "__concepts/regular.h" }
-module std_private_concepts_relation [system] { header "__concepts/relation.h" }
-module std_private_concepts_same_as [system] {
+module std_private_concepts_predicate [system] { header "__concepts/predicate.h" }
+module std_private_concepts_regular [system] { header "__concepts/regular.h" }
+module std_private_concepts_relation [system] { header "__concepts/relation.h" }
+module std_private_concepts_same_as [system] {
header "__concepts/same_as.h"
export std_private_type_traits_is_same
}
-module std_private_concepts_semiregular [system] { header "__concepts/semiregular.h" }
-module std_private_concepts_swappable [system] { header "__concepts/swappable.h" }
-module std_private_concepts_totally_ordered [system] { header "__concepts/totally_ordered.h" }
+module std_private_concepts_semiregular [system] { header "__concepts/semiregular.h" }
+module std_private_concepts_swappable [system] { header "__concepts/swappable.h" }
+module std_private_concepts_totally_ordered [system] { header "__concepts/totally_ordered.h" }
module std_private_condition_variable_condition_variable [system] {
header "__condition_variable/condition_variable.h"
diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index e0edd1f332f81..45e3e88a10d14 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1119,4 +1119,14 @@ static_assert(
std::common_reference_with<one_way_ne const&, explicit_operators const&>);
static_assert(
!check_equality_comparable_with<one_way_ne, explicit_operators>());
+
+#if TEST_STD_VER >= 23
+static_assert(check_equality_comparable_with<move_only_equality_with_int, int>());
+static_assert(check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
+#else
+static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>());
+static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
+#endif // TEST_STD_VER >= 23
+
+static_assert(!check_equality_comparable_with<immobile_comparable_with_int, int>());
} // namespace types_fit_for_purpose
diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
index 50d9722aa29c0..2920240dddf55 100644
--- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
@@ -14,6 +14,7 @@
#include <compare>
#include "compare_types.h"
+#include "test_macros.h"
template <class T, class U = T, typename Cat = std::partial_ordering>
constexpr bool check_three_way_comparable_with() {
@@ -223,4 +224,31 @@ struct SpaceshipNonConstArgument {
};
static_assert(!check_three_way_comparable_with<SpaceshipNonConstArgument>());
+
+struct MoveOnlyIntComparable {
+ MoveOnlyIntComparable(int) {}
+
+ MoveOnlyIntComparable(MoveOnlyIntComparable&&) = default;
+ MoveOnlyIntComparable& operator=(MoveOnlyIntComparable&&) = default;
+
+ friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default;
+};
+
+#if TEST_STD_VER >= 23
+static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#else
+static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#endif // TEST_STD_VER >= 23
+
+struct ImmobileIntComparable {
+ ImmobileIntComparable(int) {}
+
+ ImmobileIntComparable(ImmobileIntComparable&&) = delete;
+ ImmobileIntComparable& operator=(ImmobileIntComparable&&) = delete;
+
+ friend auto operator<=>(ImmobileIntComparable const&, ImmobileIntComparable const&) = default;
+};
+
+static_assert(!check_three_way_comparable_with<ImmobileIntComparable, int>());
+
} // namespace user_defined
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index 8155f6221540c..eea219d033ae9 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -529,4 +529,27 @@ struct ForwardingTestObject {
constexpr bool operator>=(const ForwardingTestObject&) const& { return false; }
};
+struct move_only_equality_with_int {
+ move_only_equality_with_int(int);
+
+ move_only_equality_with_int(move_only_equality_with_int&&) = default;
+ move_only_equality_with_int& operator=(move_only_equality_with_int&&) = default;
+
+ move_only_equality_with_int(move_only_equality_with_int const&) = delete;
+ move_only_equality_with_int& operator=(move_only_equality_with_int const&) = delete;
+
+ friend bool operator==(move_only_equality_with_int const&, move_only_equality_with_int const&) = default;
+ friend bool operator==(move_only_equality_with_int const&, int);
+};
+
+struct immobile_comparable_with_int {
+ immobile_comparable_with_int(int);
+
+ immobile_comparable_with_int(immobile_comparable_with_int&&) = delete;
+ immobile_comparable_with_int& operator=(immobile_comparable_with_int&&) = delete;
+
+ friend bool operator==(immobile_comparable_with_int const&, immobile_comparable_with_int const&) = default;
+ friend bool operator==(immobile_comparable_with_int const&, int);
+};
+
#endif // TEST_SUPPORT_COMPARE_TYPES_H
>From 400144dbc59f68edb96caacac12e8a6b4bac3352 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 23:28:10 -0400
Subject: [PATCH 2/2] Fix _Cat capitalization
---
libcxx/include/__compare/three_way_comparable.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index 3b14725be3309..f43c6fb010332 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -40,14 +40,14 @@ concept three_way_comparable =
# if _LIBCPP_STD_VER >= 23
-template <class _Tp, class _Up, class _cat = partial_ordering>
+template <class _Tp, class _Up, class _Cat = partial_ordering>
concept three_way_comparable_with =
- three_way_comparable<_Tp, _cat> && three_way_comparable<_Up, _cat> && __comparison_common_type_with<_Tp, _Up> &&
- three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _cat> &&
+ three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && __comparison_common_type_with<_Tp, _Up> &&
+ three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
__weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
- { __t <=> __u } -> __compares_as<_cat>;
- { __u <=> __t } -> __compares_as<_cat>;
+ { __t <=> __u } -> __compares_as<_Cat>;
+ { __u <=> __t } -> __compares_as<_Cat>;
};
# else
More information about the libcxx-commits
mailing list