mirror of git://gcc.gnu.org/git/gcc.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 <tkaminsk@redhat.com>
This commit is contained in:
parent
ea42e28cbc
commit
03562c1e02
|
|
@ -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";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) */
|
||||
|
|
|
|||
|
|
@ -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<typename _Tp, typename _Up,
|
||||
typename _Cref = 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 _Cref&>
|
||||
|| convertible_to<_Tp, const _Cref&>;
|
||||
requires convertible_to<const _Up&, const _Cref&>
|
||||
|| convertible_to<_Up, const _Cref&>;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
concept __comparison_common_type_with
|
||||
= __comparison_common_type_with_impl<remove_cvref_t<_Tp>,
|
||||
remove_cvref_t<_Up>>;
|
||||
} // namespace __detail
|
||||
|
||||
// [concept.equalitycomparable], concept equality_comparable
|
||||
|
||||
namespace __detail
|
||||
|
|
@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp, typename _Up>
|
||||
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<common_reference_t<__detail::__cref<_Tp>,
|
||||
__detail::__cref<_Up>>>
|
||||
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
|
||||
|
|
|
|||
|
|
@ -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 <bits/version.h>
|
||||
|
|
@ -499,10 +500,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
|||
|
||||
template<typename _Tp, typename _Up, typename _Cat = partial_ordering>
|
||||
concept three_way_comparable_with
|
||||
= three_way_comparable<_Tp, _Cat>
|
||||
&& three_way_comparable<_Up, _Cat>
|
||||
&& common_reference_with<const remove_reference_t<_Tp>&,
|
||||
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<_Tp>&,
|
||||
const remove_reference_t<_Up>&>, _Cat>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
|
||||
#include <concepts>
|
||||
#include <compare>
|
||||
|
||||
// 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 <compare>"
|
||||
#elif __cpp_lib_concepts < 202207L
|
||||
# error "Feature-test macro __cpp_lib_concepts has wrong value in <compare>"
|
||||
#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<MoveOnly, int>);
|
||||
static_assert(std::totally_ordered_with<MoveOnly, int>);
|
||||
static_assert(std::three_way_comparable_with<MoveOnly, int>);
|
||||
Loading…
Reference in New Issue