[libcxx-commits] [libcxx] [libc++][concepts] 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
Mon Jun 9 08:05:56 PDT 2025
https://github.com/randomnetcat updated https://github.com/llvm/llvm-project/pull/99420
>From 956934b795a4f030022dce82c02fa528ab864586 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 01/14] P2404R3: Move-only types for relational concepts
---
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.in | 1 +
.../equality_comparable_with.compile.pass.cpp | 10 +++++
...three_way_comparable_with.compile.pass.cpp | 28 +++++++++++++
libcxx/test/support/compare_types.h | 23 +++++++++++
8 files changed, 138 insertions(+)
create mode 100644 libcxx/include/__concepts/comparison_common_type.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 43cefd5600646..0a2f32361a86b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -305,6 +305,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.in b/libcxx/include/module.modulemap.in
index 7f625cefed1c2..1021daabc7c3c 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1073,6 +1073,7 @@ module std [system] {
module class_or_enum { header "__concepts/class_or_enum.h" }
module common_reference_with { header "__concepts/common_reference_with.h" }
module common_with { header "__concepts/common_with.h" }
+ module comparison_common_type { header "__concepts/comparison_common_type.h" }
module constructible { header "__concepts/constructible.h" }
module convertible_to { header "__concepts/convertible_to.h" }
module copyable { header "__concepts/copyable.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 0afbe582ba896..86393aebc29e4 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
@@ -1116,4 +1116,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 aa2ab1c0e9ef1..52226f6661cb0 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
@@ -15,6 +15,7 @@
#include <cstddef>
#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() {
@@ -224,4 +225,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 610a86bf1fe788b00ad5671796f30fc162c73a47 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 02/14] 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
>From 332f8e12450c4b74eba026b761de2064ab91f47c Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 23:31:09 -0400
Subject: [PATCH 03/14] Make test class naming consistent
---
.../equality_comparable_with.compile.pass.cpp | 2 +-
libcxx/test/support/compare_types.h | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
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 86393aebc29e4..c8272699e65e9 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
@@ -1125,5 +1125,5 @@ 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>());
+static_assert(!check_equality_comparable_with<immobile_equality_with_int, int>());
} // namespace types_fit_for_purpose
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index eea219d033ae9..ea24454594110 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -542,14 +542,14 @@ struct move_only_equality_with_int {
friend bool operator==(move_only_equality_with_int const&, int);
};
-struct immobile_comparable_with_int {
- immobile_comparable_with_int(int);
+struct immobile_equality_with_int {
+ immobile_equality_with_int(int);
- immobile_comparable_with_int(immobile_comparable_with_int&&) = delete;
- immobile_comparable_with_int& operator=(immobile_comparable_with_int&&) = delete;
+ immobile_equality_with_int(immobile_equality_with_int&&) = delete;
+ immobile_equality_with_int& operator=(immobile_equality_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);
+ friend bool operator==(immobile_equality_with_int const&, immobile_equality_with_int const&) = default;
+ friend bool operator==(immobile_equality_with_int const&, int);
};
#endif // TEST_SUPPORT_COMPARE_TYPES_H
>From 1c6e711d45987d8153b122a356d68ef8a62d180f Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 10:13:09 -0400
Subject: [PATCH 04/14] immobile -> nonmovable
---
.../equality_comparable_with.compile.pass.cpp | 2 +-
.../three_way_comparable_with.compile.pass.cpp | 12 ++++++------
libcxx/test/support/compare_types.h | 12 ++++++------
3 files changed, 13 insertions(+), 13 deletions(-)
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 c8272699e65e9..6df0f5f8ea138 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
@@ -1125,5 +1125,5 @@ 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_equality_with_int, int>());
+static_assert(!check_equality_comparable_with<nonmovable_equality_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 52226f6661cb0..5ff008f18dfd4 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
@@ -241,15 +241,15 @@ static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
#endif // TEST_STD_VER >= 23
-struct ImmobileIntComparable {
- ImmobileIntComparable(int) {}
+struct NonMovableIntComparable {
+ NonMovableIntComparable(int) {}
- ImmobileIntComparable(ImmobileIntComparable&&) = delete;
- ImmobileIntComparable& operator=(ImmobileIntComparable&&) = delete;
+ NonMovableIntComparable(NonMovableIntComparable&&) = delete;
+ NonMovableIntComparable& operator=(NonMovableIntComparable&&) = delete;
- friend auto operator<=>(ImmobileIntComparable const&, ImmobileIntComparable const&) = default;
+ friend auto operator<=>(NonMovableIntComparable const&, NonMovableIntComparable const&) = default;
};
-static_assert(!check_three_way_comparable_with<ImmobileIntComparable, int>());
+static_assert(!check_three_way_comparable_with<NonMovableIntComparable, int>());
} // namespace user_defined
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index ea24454594110..62203318be725 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -542,14 +542,14 @@ struct move_only_equality_with_int {
friend bool operator==(move_only_equality_with_int const&, int);
};
-struct immobile_equality_with_int {
- immobile_equality_with_int(int);
+struct nonmovable_equality_with_int {
+ nonmovable_equality_with_int(int);
- immobile_equality_with_int(immobile_equality_with_int&&) = delete;
- immobile_equality_with_int& operator=(immobile_equality_with_int&&) = delete;
+ nonmovable_equality_with_int(nonmovable_equality_with_int&&) = delete;
+ nonmovable_equality_with_int& operator=(nonmovable_equality_with_int&&) = delete;
- friend bool operator==(immobile_equality_with_int const&, immobile_equality_with_int const&) = default;
- friend bool operator==(immobile_equality_with_int const&, int);
+ friend bool operator==(nonmovable_equality_with_int const&, nonmovable_equality_with_int const&) = default;
+ friend bool operator==(nonmovable_equality_with_int const&, int);
};
#endif // TEST_SUPPORT_COMPARE_TYPES_H
>From 18ded9bbbf7acd836b9b0b13b28253735fa097de Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 10:16:29 -0400
Subject: [PATCH 05/14] _C -> _CommonRef
---
libcxx/include/__concepts/comparison_common_type.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index a1f246d2a6dca..ed95ee3a66700 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -22,11 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 23
-template <class _Tp, class _Up, class _C = common_reference_t<const _Tp&, const _Up&>>
+template <class _Tp, class _Up, class _CommonRef = 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&>;
+ requires convertible_to<const _Tp&, const _CommonRef&> || convertible_to<_Tp, const _CommonRef&>;
+ requires convertible_to<const _Up&, const _CommonRef&> || convertible_to<_Up, const _CommonRef&>;
};
template <class _Tp, class _Up>
>From 00d4c40aaba567c76f0ee4ea02df9db84366f1af Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 11:53:15 -0400
Subject: [PATCH 06/14] Update other comparison tests
---
.../ranges_partial_sort_copy.pass.cpp | 21 +++++++++++++++++--
.../range.cmp/equal_to.pass.cpp | 7 ++++++-
.../range.cmp/greater.pass.cpp | 7 ++++++-
.../range.cmp/greater_equal.pass.cpp | 7 ++++++-
.../function.objects/range.cmp/less.pass.cpp | 7 ++++++-
.../range.cmp/less_equal.pass.cpp | 7 ++++++-
.../range.cmp/not_equal_to.pass.cpp | 7 ++++++-
7 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index 532ee9b03efc0..0f799bca97775 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -75,7 +75,12 @@ static_assert(!HasPartialSortCopyIter<int*, int*, int*, int*, IndirectUnaryPredi
static_assert(!HasPartialSortCopyIter<int*, int*, int*, int*, IndirectUnaryPredicateNotCopyConstructible>);
// !indirectly_copyable<I1, I2>
-static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*>);
+struct OrderedConvertibleToInt {
+ friend auto operator<=>(OrderedConvertibleToInt const&, OrderedConvertibleToInt const&) = default;
+ operator int() const;
+};
+
+static_assert(!HasPartialSortCopyIter<int*, int*, OrderedConvertibleToInt*, OrderedConvertibleToInt*>);
// !sortable<I2, Comp, Proj2>
static_assert(!HasPartialSortCopyIter<int*, int*, const int*, const int*>);
@@ -84,6 +89,12 @@ struct NoComparator {};
// !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
+#if TEST_STD_VER >= 23
+static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#else
+static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#endif // TEST_STD_VER >= 23
+
// Test constraints of the (range) overload.
// ======================================================
@@ -109,7 +120,7 @@ static_assert(!HasPartialSortCopyRange<R<int*>, RandomAccessRangeNotDerivedFrom>
static_assert(!HasPartialSortCopyRange<R<int*>, RandomAccessRangeBadIndex>);
// !indirectly_copyable<iterator_t<R1>, iterator_t<R2>>
-static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+static_assert(!HasPartialSortCopyRange<R<int*>, R<OrderedConvertibleToInt*>>);
// !sortable<iterator_t<R2>, Comp, Proj2>
static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
@@ -117,6 +128,12 @@ static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
// !indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>
static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
+#if TEST_STD_VER >= 23
+static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#else
+static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#endif // TEST_STD_VER >= 23
+
static_assert(std::is_same_v<std::ranges::partial_sort_copy_result<int, int>, std::ranges::in_out_result<int, int>>);
template <class Iter, class Sent, class OutIter, class OutSent, std::size_t N>
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index 6d207548b2175..d5431140841e2 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -28,9 +28,14 @@ struct NotEqualityComparable {
};
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::equal_to::is_transparent; });
constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index 002ec10e07aff..7a91a6add6cc0 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
};
static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::greater::is_transparent; });
constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index ad24a98a168cf..7878d6bac04dc 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
};
static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 5afb7e0ebdef4..8dca5c80da772 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
};
static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::less::is_transparent; });
constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index 3aa903fa6321a..88d001e9fc1e7 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
};
static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::less_equal::is_transparent; });
constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 4b46bae76ce48..9463967e7e2f0 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -28,9 +28,14 @@ struct NotEqualityComparable {
};
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
struct PtrAndNotEqOperator {
>From a77778117654c23467ca91da76ba9479194486b4 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 13:36:47 -0400
Subject: [PATCH 07/14] Invert test conditionals
---
.../equality_comparable_with.compile.pass.cpp | 10 +++++-----
.../three_way_comparable_with.compile.pass.cpp | 8 ++++----
.../function.objects/range.cmp/equal_to.pass.cpp | 8 ++++----
.../function.objects/range.cmp/greater.pass.cpp | 8 ++++----
.../function.objects/range.cmp/greater_equal.pass.cpp | 8 ++++----
.../utilities/function.objects/range.cmp/less.pass.cpp | 8 ++++----
.../function.objects/range.cmp/less_equal.pass.cpp | 8 ++++----
.../function.objects/range.cmp/not_equal_to.pass.cpp | 8 ++++----
8 files changed, 33 insertions(+), 33 deletions(-)
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 6df0f5f8ea138..62da79dc1d906 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
@@ -1117,13 +1117,13 @@ static_assert(
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
+#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>());
-#endif // TEST_STD_VER >= 23
+#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<nonmovable_equality_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 5ff008f18dfd4..c0df825653693 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
@@ -235,11 +235,11 @@ struct MoveOnlyIntComparable {
friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default;
};
-#if TEST_STD_VER >= 23
-static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#else
+#if TEST_STD_VER < 23
static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#endif // TEST_STD_VER < 23
struct NonMovableIntComparable {
NonMovableIntComparable(int) {}
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index d5431140841e2..10b9aa6e59fd6 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -30,11 +30,11 @@ struct NotEqualityComparable {
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::equal_to::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index 7a91a6add6cc0..b8d1da2d1410f 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::greater::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index 7878d6bac04dc..26ec6663364ee 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 8dca5c80da772..70ed88fbcea2c 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::less::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index 88d001e9fc1e7..d422bea55f9eb 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::less_equal::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 9463967e7e2f0..147a248348da8 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -30,11 +30,11 @@ struct NotEqualityComparable {
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#if TEST_STD_VER < 23
+static_assert(!std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
#else
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
>From 0233dc162f575c5ba5bca17b8d446c0dd97b8725 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 13:49:41 -0400
Subject: [PATCH 08/14] Don't split definitions of
equality_comparable_with/totally_ordered_with
---
.../include/__compare/three_way_comparable.h | 17 -----------------
.../__concepts/comparison_common_type.h | 16 ++++++++++++++--
.../include/__concepts/equality_comparable.h | 18 ------------------
libcxx/test/support/compare_types.h | 3 +++
4 files changed, 17 insertions(+), 37 deletions(-)
diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index f43c6fb010332..ad6d05a681145 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -38,8 +38,6 @@ 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> &&
@@ -50,21 +48,6 @@ concept three_way_comparable_with =
{ __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> &&
- common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_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>;
- };
-
-# 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
index ed95ee3a66700..cff61e14d501d 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -9,10 +9,12 @@
#ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+#include "__concepts/common_reference_with.h"
#include "__concepts/convertible_to.h"
#include "__concepts/same_as.h"
#include "__config"
#include "__type_traits/common_reference.h"
+#include "__type_traits/make_const_lvalue_ref.h"
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -20,7 +22,15 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER >= 23
+#if _LIBCPP_STD_VER >= 20
+
+# if _LIBCPP_STD_VER < 23
+
+template <class _Tp, class _Up>
+concept __comparison_common_type_with =
+ common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>;
+
+# else
template <class _Tp, class _Up, class _CommonRef = common_reference_t<const _Tp&, const _Up&>>
concept __comparison_common_type_with_impl =
@@ -32,7 +42,9 @@ concept __comparison_common_type_with_impl =
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
+# endif // _LIBCPP_STD_VER < 23
+
+#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h
index 1904b2e451a8d..56fc6f8b685c0 100644
--- a/libcxx/include/__concepts/equality_comparable.h
+++ b/libcxx/include/__concepts/equality_comparable.h
@@ -38,8 +38,6 @@ 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 =
@@ -52,22 +50,6 @@ concept equality_comparable_with =
__weakly_equality_comparable_with<_Tp, _Up>;
// clang-format on
-# else
-
-// clang-format off
-template <class _Tp, class _Up>
-concept equality_comparable_with =
- equality_comparable<_Tp> && equality_comparable<_Up> &&
- common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_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
-
-# endif // _LIBCPP_STD_VER >= 23
-
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index 62203318be725..b52e201f240ac 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -548,6 +548,9 @@ struct nonmovable_equality_with_int {
nonmovable_equality_with_int(nonmovable_equality_with_int&&) = delete;
nonmovable_equality_with_int& operator=(nonmovable_equality_with_int&&) = delete;
+ nonmovable_equality_with_int(nonmovable_equality_with_int const&) = delete;
+ nonmovable_equality_with_int& operator=(nonmovable_equality_with_int const&) = delete;
+
friend bool operator==(nonmovable_equality_with_int const&, nonmovable_equality_with_int const&) = default;
friend bool operator==(nonmovable_equality_with_int const&, int);
};
>From bd2dcd96be8a30b25bddb0ee8f141c93590f2d53 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 15:00:34 -0400
Subject: [PATCH 09/14] Fix last >= 23 check
---
.../ranges_partial_sort_copy.pass.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index 0f799bca97775..fc00f9c79a94e 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -89,11 +89,11 @@ struct NoComparator {};
// !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
-#if TEST_STD_VER >= 23
-static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#else
+#if TEST_STD_VER < 23
static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#endif // TEST_STD_VER < 23
// Test constraints of the (range) overload.
// ======================================================
@@ -128,11 +128,11 @@ static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
// !indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>
static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
-#if TEST_STD_VER >= 23
-static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#else
+#if TEST_STD_VER < 23
static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#endif // TEST_STD_VER < 23
static_assert(std::is_same_v<std::ranges::partial_sort_copy_result<int, int>, std::ranges::in_out_result<int, int>>);
>From 60dc091e69365b3c321c5651b2e16cbff3d24fa4 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Fri, 19 Jul 2024 11:18:57 -0400
Subject: [PATCH 10/14] Fix quotation mark includes
---
libcxx/include/__concepts/comparison_common_type.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index cff61e14d501d..e3fd12e571c7e 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -9,12 +9,12 @@
#ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
-#include "__concepts/common_reference_with.h"
-#include "__concepts/convertible_to.h"
-#include "__concepts/same_as.h"
-#include "__config"
-#include "__type_traits/common_reference.h"
-#include "__type_traits/make_const_lvalue_ref.h"
+#include <__concepts/common_reference_with.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/same_as.h>
+#include <__config>
+#include <__type_traits/common_reference.h>
+#include <__type_traits/make_const_lvalue_ref.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
>From a065d74429c2a94f6114546dd83a76c5a805c69f Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Fri, 19 Jul 2024 11:21:36 -0400
Subject: [PATCH 11/14] Add comments to tests
---
.../partial.sort.copy/ranges_partial_sort_copy.pass.cpp | 2 ++
.../equality_comparable_with.compile.pass.cpp | 1 +
.../cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp | 1 +
.../std/utilities/function.objects/range.cmp/equal_to.pass.cpp | 1 +
.../std/utilities/function.objects/range.cmp/greater.pass.cpp | 1 +
.../utilities/function.objects/range.cmp/greater_equal.pass.cpp | 1 +
.../test/std/utilities/function.objects/range.cmp/less.pass.cpp | 1 +
.../utilities/function.objects/range.cmp/less_equal.pass.cpp | 1 +
.../utilities/function.objects/range.cmp/not_equal_to.pass.cpp | 1 +
9 files changed, 10 insertions(+)
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index fc00f9c79a94e..ffe024b3dc69f 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -92,6 +92,7 @@ static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator
#if TEST_STD_VER < 23
static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
#else
+// P2404
static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
#endif // TEST_STD_VER < 23
@@ -131,6 +132,7 @@ static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
#if TEST_STD_VER < 23
static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
#else
+// P2404
static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
#endif // TEST_STD_VER < 23
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 62da79dc1d906..10daaeb172312 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
@@ -1121,6 +1121,7 @@ static_assert(
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
+// P2404
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
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 c0df825653693..3114e26ebc583 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
@@ -238,6 +238,7 @@ struct MoveOnlyIntComparable {
#if TEST_STD_VER < 23
static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
#else
+// P2404
static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index 10b9aa6e59fd6..5007c933ce076 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -33,6 +33,7 @@ static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, exp
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index b8d1da2d1410f..765915a628f4a 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, expl
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index 26ec6663364ee..3d3cdef3124f8 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 70ed88fbcea2c..bbf92361002c2 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explici
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index d422bea55f9eb..4d3b85dce1183 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, e
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
#endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 147a248348da8..2acacd6a18fb4 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -33,6 +33,7 @@ static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, exp
#if TEST_STD_VER < 23
static_assert(!std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
#else
+// P2404
static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
#endif // TEST_STD_VER < 23
>From f26596a8943546594f063bd1b62ee8461ad83ac9 Mon Sep 17 00:00:00 2001
From: Janet Cobb <jecobb2 at ncsu.edu>
Date: Mon, 9 Jun 2025 15:58:20 +0100
Subject: [PATCH 12/14] Implement P2404 as a DR rather than only in 23
---
libcxx/include/__concepts/comparison_common_type.h | 10 ----------
.../ranges_partial_sort_copy.pass.cpp | 8 --------
.../equality_comparable_with.compile.pass.cpp | 5 -----
.../three_way_comparable_with.compile.pass.cpp | 5 +----
.../function.objects/range.cmp/equal_to.pass.cpp | 4 ----
.../function.objects/range.cmp/greater.pass.cpp | 4 ----
.../function.objects/range.cmp/greater_equal.pass.cpp | 5 -----
.../utilities/function.objects/range.cmp/less.pass.cpp | 4 ----
.../function.objects/range.cmp/less_equal.pass.cpp | 4 ----
.../function.objects/range.cmp/not_equal_to.pass.cpp | 4 ----
10 files changed, 1 insertion(+), 52 deletions(-)
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index e3fd12e571c7e..45a788c3513ed 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -24,14 +24,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
-# if _LIBCPP_STD_VER < 23
-
-template <class _Tp, class _Up>
-concept __comparison_common_type_with =
- common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>;
-
-# else
-
template <class _Tp, class _Up, class _CommonRef = 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 {
@@ -42,8 +34,6 @@ concept __comparison_common_type_with_impl =
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
-
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index ffe024b3dc69f..36ec7892faa22 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -89,12 +89,8 @@ struct NoComparator {};
// !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
-#if TEST_STD_VER < 23
-static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#else
// P2404
static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#endif // TEST_STD_VER < 23
// Test constraints of the (range) overload.
// ======================================================
@@ -129,12 +125,8 @@ static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
// !indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>
static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
-#if TEST_STD_VER < 23
-static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#else
// P2404
static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#endif // TEST_STD_VER < 23
static_assert(std::is_same_v<std::ranges::partial_sort_copy_result<int, int>, std::ranges::in_out_result<int, int>>);
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 10daaeb172312..cde4136a401ac 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
@@ -1117,14 +1117,9 @@ static_assert(
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
// P2404
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<nonmovable_equality_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 3114e26ebc583..15fdb6b4487fa 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
@@ -235,12 +235,9 @@ struct MoveOnlyIntComparable {
friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default;
};
-#if TEST_STD_VER < 23
-static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#else
+
// P2404
static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#endif // TEST_STD_VER < 23
struct NonMovableIntComparable {
NonMovableIntComparable(int) {}
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index 5007c933ce076..8b2b877092c69 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -30,12 +30,8 @@ struct NotEqualityComparable {
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#else
// P2404
static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::equal_to::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index 765915a628f4a..0a3a1f07841b3 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -29,12 +29,8 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#else
// P2404
static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::greater::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index 3d3cdef3124f8..2790d73c656ad 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -29,12 +29,7 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#else
// P2404
-static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index bbf92361002c2..b1a3cb8e86897 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -29,12 +29,8 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#else
// P2404
static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::less::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index 4d3b85dce1183..739cc3b2a912e 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -29,12 +29,8 @@ struct NotTotallyOrdered {
static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#else
// P2404
static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::less_equal::is_transparent; });
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 2acacd6a18fb4..5cff83143e463 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -30,12 +30,8 @@ struct NotEqualityComparable {
static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
-#if TEST_STD_VER < 23
-static_assert(!std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
-#else
// P2404
static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER < 23
static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
>From e8025b4ce5aadb6b6c512fda5fae1bebc84cc80d Mon Sep 17 00:00:00 2001
From: Janet Cobb <jecobb2 at ncsu.edu>
Date: Mon, 9 Jun 2025 15:30:01 +0100
Subject: [PATCH 13/14] Bump __cpp_lib_concepts
---
libcxx/docs/FeatureTestMacroTable.rst | 4 ++--
libcxx/include/version | 4 ++--
.../concepts.version.compile.pass.cpp | 21 ++++++++-----------
.../version.version.compile.pass.cpp | 21 ++++++++-----------
.../generate_feature_test_macro_components.py | 2 +-
5 files changed, 23 insertions(+), 29 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a89d4038785cd..1f43f89ee0bce 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -198,8 +198,6 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_char8_t`` ``201907L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_concepts`` ``202002L``
- ---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_algorithms`` ``201806L``
---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_complex`` ``201711L``
@@ -316,6 +314,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_byteswap`` ``202110L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_concepts`` ``202207L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_bitset`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_charconv`` ``202207L``
diff --git a/libcxx/include/version b/libcxx/include/version
index 65fae111dc8ed..84cb03b4441c5 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -60,7 +60,7 @@ __cpp_lib_chrono 201611L <chrono>
__cpp_lib_chrono_udls 201304L <chrono>
__cpp_lib_clamp 201603L <algorithm>
__cpp_lib_complex_udls 201309L <complex>
-__cpp_lib_concepts 202002L <concepts>
+__cpp_lib_concepts 202207L <concepts>
__cpp_lib_constexpr_algorithms 202306L <algorithm> <utility>
201806L // C++20
__cpp_lib_constexpr_bitset 202207L <bitset>
@@ -400,7 +400,6 @@ __cpp_lib_void_t 201411L <type_traits>
# if _LIBCPP_HAS_CHAR8_T
# define __cpp_lib_char8_t 201907L
# endif
-# define __cpp_lib_concepts 202002L
# define __cpp_lib_constexpr_algorithms 201806L
# define __cpp_lib_constexpr_complex 201711L
# define __cpp_lib_constexpr_dynamic_alloc 201907L
@@ -480,6 +479,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
# define __cpp_lib_bind_back 202202L
# define __cpp_lib_byteswap 202110L
+# define __cpp_lib_concepts 202207L
# define __cpp_lib_constexpr_bitset 202207L
# define __cpp_lib_constexpr_charconv 202207L
// # define __cpp_lib_constexpr_cmath 202202L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
index d9b2c43ecbd12..e618ea4c77e70 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
@@ -21,28 +21,25 @@
#if TEST_STD_VER < 14
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
#elif TEST_STD_VER == 14
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
#elif TEST_STD_VER == 17
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
#elif TEST_STD_VER == 20
-# ifndef __cpp_lib_concepts
-# error "__cpp_lib_concepts should be defined in c++20"
-# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++20"
+# ifdef __cpp_lib_concepts
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
#elif TEST_STD_VER == 23
@@ -50,8 +47,8 @@
# ifndef __cpp_lib_concepts
# error "__cpp_lib_concepts should be defined in c++23"
# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++23"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++23"
# endif
#elif TEST_STD_VER > 23
@@ -59,8 +56,8 @@
# ifndef __cpp_lib_concepts
# error "__cpp_lib_concepts should be defined in c++26"
# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++26"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++26"
# endif
#endif // TEST_STD_VER > 23
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index b1cc4afd30696..2e234a46e0b3b 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -169,7 +169,7 @@
# endif
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
# ifdef __cpp_lib_constexpr_algorithms
@@ -1057,7 +1057,7 @@
# endif
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
# ifdef __cpp_lib_constexpr_algorithms
@@ -2047,7 +2047,7 @@
# endif
# ifdef __cpp_lib_concepts
-# error "__cpp_lib_concepts should not be defined before c++20"
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
# ifdef __cpp_lib_constexpr_algorithms
@@ -3264,11 +3264,8 @@
# error "__cpp_lib_complex_udls should have the value 201309L in c++20"
# endif
-# ifndef __cpp_lib_concepts
-# error "__cpp_lib_concepts should be defined in c++20"
-# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++20"
+# ifdef __cpp_lib_concepts
+# error "__cpp_lib_concepts should not be defined before c++23"
# endif
# ifndef __cpp_lib_constexpr_algorithms
@@ -4704,8 +4701,8 @@
# ifndef __cpp_lib_concepts
# error "__cpp_lib_concepts should be defined in c++23"
# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++23"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++23"
# endif
# ifndef __cpp_lib_constexpr_algorithms
@@ -6375,8 +6372,8 @@
# ifndef __cpp_lib_concepts
# error "__cpp_lib_concepts should be defined in c++26"
# endif
-# if __cpp_lib_concepts != 202002L
-# error "__cpp_lib_concepts should have the value 202002L in c++26"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++26"
# endif
# ifndef __cpp_lib_constexpr_algorithms
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 82f0d09db5c36..6933a4b54df2d 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -320,7 +320,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_concepts",
- "values": {"c++20": 202002},
+ "values": {"c++23": 202207},
"headers": ["concepts"],
},
{
>From 5c6b58e9e7e46ffcfe9d077eafa3162ee0ca3a3e Mon Sep 17 00:00:00 2001
From: Janet Cobb <jecobb2 at ncsu.edu>
Date: Mon, 9 Jun 2025 16:03:29 +0100
Subject: [PATCH 14/14] Update documentation
---
libcxx/docs/ReleaseNotes/21.rst | 1 +
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 6cbc0baf29487..7bc431fed4e14 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -47,6 +47,7 @@ Implemented Papers
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github <https://github.com/llvm/llvm-project/issues/118372>`__)
- P3247R2: Deprecate the notion of trivial types (`Github <https://github.com/llvm/llvm-project/issues/118387>`__)
+- P2404R3 - Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with`` (`Github <https://github.com/llvm/llvm-project/pull/99420>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index c26363bcda796..09dba5410fc32 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -67,7 +67,7 @@
"`P2302R4 <https://wg21.link/P2302R4>`__","``std::ranges::contains``","2022-07 (Virtual)","|Complete|","19",""
"`P2322R6 <https://wg21.link/P2322R6>`__","``ranges::fold``","2022-07 (Virtual)","","",""
"`P2374R4 <https://wg21.link/P2374R4>`__","``views::cartesian_product``","2022-07 (Virtual)","","",""
-"`P2404R3 <https://wg21.link/P2404R3>`__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","","",""
+"`P2404R3 <https://wg21.link/P2404R3>`__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","|Complete|","21",""
"`P2408R5 <https://wg21.link/P2408R5>`__","Ranges iterators as inputs to non-Ranges algorithms","2022-07 (Virtual)","","",""
"`P2417R2 <https://wg21.link/P2417R2>`__","A more ``constexpr`` ``bitset``","2022-07 (Virtual)","|Complete|","16",""
"`P2419R2 <https://wg21.link/P2419R2>`__","Clarify handling of encodings in localized formatting of chrono types","2022-07 (Virtual)","","",""
More information about the libcxx-commits
mailing list