[libcxx-commits] [libcxx] ef19006 - [libc++][concepts] P2404R3: Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with (#99420)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Dec 19 01:56:38 PST 2025
Author: Janet Cobb
Date: 2025-12-19T17:56:32+08:00
New Revision: ef190061d342865dd9289ddc59fff4b0ab3428d1
URL: https://github.com/llvm/llvm-project/commit/ef190061d342865dd9289ddc59fff4b0ab3428d1
DIFF: https://github.com/llvm/llvm-project/commit/ef190061d342865dd9289ddc59fff4b0ab3428d1.diff
LOG: [libc++][concepts] P2404R3: Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with (#99420)
This implements all of [P2404R3](https://wg21.link/p2404r3)'s concept
changes.
---------
Co-authored-by: A. Jiang <de34 at live.cn>
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
Added:
libcxx/include/__concepts/comparison_common_type.h
Modified:
libcxx/docs/FeatureTestMacroTable.rst
libcxx/docs/ReleaseNotes/22.rst
libcxx/docs/Status/Cxx23Papers.csv
libcxx/include/CMakeLists.txt
libcxx/include/__compare/three_way_comparable.h
libcxx/include/__concepts/equality_comparable.h
libcxx/include/module.modulemap.in
libcxx/include/version
libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
libcxx/test/support/compare_types.h
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 756bdf71f8b22..5f1e521bd79c2 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -202,7 +202,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_common_reference_wrapper`` ``202302L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_concepts`` ``202002L``
+ ``__cpp_lib_concepts`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_algorithms`` ``201806L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 603551cb0f603..76d3bb263290f 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -44,6 +44,8 @@ Implemented Papers
- P3044R2: sub-``string_view`` from ``string`` (`Github <https://llvm.org/PR148140>`__)
- P3223R2: Making ``std::istream::ignore`` less surprising (`Github <https://llvm.org/PR148178>`__)
- P3060R3: Add ``std::views::indices(n)`` (`Github <https://llvm.org/PR148175>`__)
+- P2404R3: Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``
+ (`Github <https://llvm.org/PR105210>`__)
- P2641R4: Checking if a ``union`` alternative is active (``std::is_within_lifetime``)
(`Github <https://llvm.org/PR105381>`__)
- P2835R7: Expose ``std::atomic_ref``'s object address (`Github <https://llvm.org/PR118377>`__)
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index b655384bad7f2..e4c6cb0f51065 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","`#105206 <https://github.com/llvm/llvm-project/issues/105206>`__",""
"`P2322R6 <https://wg21.link/P2322R6>`__","``ranges::fold``","2022-07 (Virtual)","","","`#105208 <https://github.com/llvm/llvm-project/issues/105208>`__",""
"`P2374R4 <https://wg21.link/P2374R4>`__","``views::cartesian_product``","2022-07 (Virtual)","","","`#105209 <https://github.com/llvm/llvm-project/issues/105209>`__",""
-"`P2404R3 <https://wg21.link/P2404R3>`__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","","","`#105210 <https://github.com/llvm/llvm-project/issues/105210>`__",""
+"`P2404R3 <https://wg21.link/P2404R3>`__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","|Complete|","22","`#105210 <https://github.com/llvm/llvm-project/issues/105210>`__","Implemented as a DR in C++20."
"`P2408R5 <https://wg21.link/P2408R5>`__","Ranges iterators as inputs to non-Ranges algorithms","2022-07 (Virtual)","","","`#105211 <https://github.com/llvm/llvm-project/issues/105211>`__",""
"`P2417R2 <https://wg21.link/P2417R2>`__","A more ``constexpr`` ``bitset``","2022-07 (Virtual)","|Complete|","16","`#105212 <https://github.com/llvm/llvm-project/issues/105212>`__",""
"`P2419R2 <https://wg21.link/P2419R2>`__","Clarify handling of encodings in localized formatting of chrono types","2022-07 (Virtual)","","","`#105213 <https://github.com/llvm/llvm-project/issues/105213>`__",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index e6d5d444cc1c2..9df40eab678a2 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -308,6 +308,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..ad6d05a681145 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>
@@ -39,8 +40,7 @@ concept three_way_comparable =
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<_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) {
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
new file mode 100644
index 0000000000000..3f0d770511f47
--- /dev/null
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+#include <__type_traits/remove_cvref.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 20
+
+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 _CommonRef&> || convertible_to<_Tp, const _CommonRef&>;
+ requires convertible_to<const _Up&, const _CommonRef&> || convertible_to<_Up, const _CommonRef&>;
+ };
+
+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 >= 20
+
+_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..56fc6f8b685c0 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>
@@ -41,7 +42,7 @@ concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
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>> &&
+ __comparison_common_type_with<_Tp, _Up> &&
equality_comparable<
common_reference_t<
__make_const_lvalue_ref<_Tp>,
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index feb6249e1e6db..ce168f77dfea4 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1065,6 +1065,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/include/version b/libcxx/include/version
index 05532ea731ff3..c4daaffd89acf 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -63,7 +63,7 @@ __cpp_lib_clamp 201603L <algorithm>
__cpp_lib_common_reference 202302L <type_traits>
__cpp_lib_common_reference_wrapper 202302L <functional>
__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>
@@ -410,7 +410,7 @@ __cpp_lib_void_t 201411L <type_traits>
# endif
# define __cpp_lib_common_reference 202302L
# define __cpp_lib_common_reference_wrapper 202302L
-# define __cpp_lib_concepts 202002L
+# define __cpp_lib_concepts 202207L
# define __cpp_lib_constexpr_algorithms 201806L
# define __cpp_lib_constexpr_complex 201711L
# define __cpp_lib_constexpr_dynamic_alloc 201907L
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..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
@@ -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,9 @@ struct NoComparator {};
// !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
+// P2404
+static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+
// Test constraints of the (range) overload.
// ======================================================
@@ -109,7 +117,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 +125,9 @@ 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*>>);
+// P2404
+static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+
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/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 2f8d7862c0f4d..5ac48ccf9ad0f 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
@@ -1131,4 +1131,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>());
+
+// 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>());
+// TODO: Clang is broken, see https://llvm.org/PR171438
+#if defined(TEST_COMPILER_CLANG) && !defined(TEST_COMPILER_APPLE_CLANG)
+static_assert(check_equality_comparable_with<nonmovable_equality_with_int, int>());
+#else
+static_assert(!check_equality_comparable_with<nonmovable_equality_with_int, int>());
+#endif
} // 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..7cd3ad1bbe316 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,33 @@ 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;
+};
+
+// P2404
+static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+
+struct NonMovableIntComparable {
+ NonMovableIntComparable(int) {}
+
+ NonMovableIntComparable(NonMovableIntComparable&&) = delete;
+ NonMovableIntComparable& operator=(NonMovableIntComparable&&) = delete;
+
+ friend auto operator<=>(NonMovableIntComparable const&, NonMovableIntComparable const&) = default;
+};
+
+// TODO: Clang is broken, see https://llvm.org/PR171438
+#if defined(TEST_COMPILER_CLANG) && !defined(TEST_COMPILER_APPLE_CLANG)
+static_assert(check_three_way_comparable_with<NonMovableIntComparable, int>());
+#else
+static_assert(!check_three_way_comparable_with<NonMovableIntComparable, int>());
+#endif
+
} // namespace user_defined
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 e4058c2348f9b..15f1d30060ef1 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
@@ -41,8 +41,8 @@
# 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"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++20"
# endif
#elif TEST_STD_VER == 23
@@ -50,8 +50,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 +59,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 996ec29dce697..65cdf2ded816d 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
@@ -3371,8 +3371,8 @@
# 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"
+# if __cpp_lib_concepts != 202207L
+# error "__cpp_lib_concepts should have the value 202207L in c++20"
# endif
# ifndef __cpp_lib_constexpr_algorithms
@@ -4840,8 +4840,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
@@ -6537,8 +6537,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/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..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
@@ -28,9 +28,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, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+
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..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
@@ -27,9 +27,11 @@ 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>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+
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..2074599966b70 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,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, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+
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..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
@@ -27,9 +27,11 @@ 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>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+
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..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
@@ -27,9 +27,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, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+
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..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
@@ -28,9 +28,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, int, MoveOnly>);
static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+// P2404
+static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
+
static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
struct PtrAndNotEqOperator {
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index 8155f6221540c..b52e201f240ac 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -529,4 +529,30 @@ 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 nonmovable_equality_with_int {
+ nonmovable_equality_with_int(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);
+};
+
#endif // TEST_SUPPORT_COMPARE_TYPES_H
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 0802f865f9406..c91bdf4ed99ec 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -331,7 +331,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_concepts",
- "values": {"c++20": 202002},
+ "values": {"c++20": 202207},
"headers": ["concepts"],
},
{
More information about the libcxx-commits
mailing list