From: Jonathan Wakely Date: Thu, 4 Dec 2025 14:45:53 +0000 (+0000) Subject: libstdc++: Implement P2404R3 relaxations to comparable_with concepts [PR122946] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03562c1e023d01cacf099a40842e617d27148c74;p=thirdparty%2Fgcc.git libstdc++: Implement P2404R3 relaxations to comparable_with concepts [PR122946] This implements the C++23 proposal P2404R3 "Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with". As agreed with the maintainers of libc++ and MSVC STL, we treat this as a DR for C++20. It allows reasonable code to compile which wasn't originally allowed in C++20, and only affects some obscure subsumption cases for valid C++20 code. libstdc++-v3/ChangeLog: PR libstdc++/122946 * include/bits/version.def (concepts): Set value to 202207. * include/bits/version.h: Regenerate. * include/std/concepts (__comparison_common_type_with_impl) (__comparison_common_type_with): New helper concepts. (equality_comparable_with): Use __comparison_common_type_with. * libsupc++/compare (three_way_comparable_with): Likewise. (__glibcxx_want_concepts): Define to get __cpp_lib_concepts here. * testsuite/std/concepts/concepts.compare/move_only.cc: New test. Reviewed-by: Tomasz KamiƄski --- diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 412b9ce96f8a..bbc8d383938f 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -879,8 +879,12 @@ ftms = { ftms = { name = concepts; + // 201806 P0898R3 Standard Library Concepts + // 201907 P1754R1 Rename concepts to standard_case for C++20 + // 202002 P1964R2 Wording for boolean-testable + // 202207 P2404R3 Move-only types for equality_comparable_with, etc. values = { - v = 202002; + v = 202207; cxxmin = 20; extra_cond = "__cpp_concepts >= 201907L"; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 2b96934ca099..7ee9ae84215e 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -985,9 +985,9 @@ #if !defined(__cpp_lib_concepts) # if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L) -# define __glibcxx_concepts 202002L +# define __glibcxx_concepts 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts) -# define __cpp_lib_concepts 202002L +# define __cpp_lib_concepts 202207L # endif # endif #endif /* !defined(__cpp_lib_concepts) */ diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts index d9920a8f20a8..870b0a47eab1 100644 --- a/libstdc++-v3/include/std/concepts +++ b/libstdc++-v3/include/std/concepts @@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; } // namespace __detail + // [concept.comparisoncommontype], helpers for comparison common types + namespace __detail + { + template> + concept __comparison_common_type_with_impl + = same_as, + common_reference_t> + && requires { + requires convertible_to + || convertible_to<_Tp, const _Cref&>; + requires convertible_to + || convertible_to<_Up, const _Cref&>; + }; + + template + concept __comparison_common_type_with + = __comparison_common_type_with_impl, + remove_cvref_t<_Up>>; + } // namespace __detail + // [concept.equalitycomparable], concept equality_comparable namespace __detail @@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template concept equality_comparable_with = equality_comparable<_Tp> && equality_comparable<_Up> - && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && __detail::__comparison_common_type_with<_Tp, _Up> && equality_comparable, __detail::__cref<_Up>>> && __detail::__weakly_eq_cmp_with<_Tp, _Up>; diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 08f2b2ba47ed..5b4f47a94e3b 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -34,6 +34,7 @@ #pragma GCC system_header #endif +#define __glibcxx_want_concepts #define __glibcxx_want_three_way_comparison #define __glibcxx_want_type_order #include @@ -499,10 +500,8 @@ namespace std _GLIBCXX_VISIBILITY(default) template concept three_way_comparable_with - = three_way_comparable<_Tp, _Cat> - && three_way_comparable<_Up, _Cat> - && common_reference_with&, - const remove_reference_t<_Up>&> + = three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> + && __detail::__comparison_common_type_with<_Tp, _Up> && three_way_comparable< common_reference_t&, const remove_reference_t<_Up>&>, _Cat> diff --git a/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc new file mode 100644 index 000000000000..01870d846267 --- /dev/null +++ b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc @@ -0,0 +1,28 @@ +// { dg-do compile { target c++20 } } + +#include +#include + +// P2404R3 Move-only types for equality_comparable_with, +// totally_ordered_with, and three_way_comparable_with + +// This was approved for C++23 but we treat it as a DR for C++20. + +#ifndef __cpp_lib_concepts +# error "Feature-test macro __cpp_lib_concepts is missing in " +#elif __cpp_lib_concepts < 202207L +# error "Feature-test macro __cpp_lib_concepts has wrong value in " +#endif + +struct MoveOnly +{ + MoveOnly(int); + MoveOnly(MoveOnly&&) = default; + auto operator<=>(const MoveOnly&) const = default; + std::strong_ordering operator<=>(int) const; + bool operator==(const MoveOnly&) const; +}; + +static_assert(std::equality_comparable_with); +static_assert(std::totally_ordered_with); +static_assert(std::three_way_comparable_with);