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);