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 = {
|
ftms = {
|
||||||
name = concepts;
|
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 = {
|
values = {
|
||||||
v = 202002;
|
v = 202207;
|
||||||
cxxmin = 20;
|
cxxmin = 20;
|
||||||
extra_cond = "__cpp_concepts >= 201907L";
|
extra_cond = "__cpp_concepts >= 201907L";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -985,9 +985,9 @@
|
||||||
|
|
||||||
#if !defined(__cpp_lib_concepts)
|
#if !defined(__cpp_lib_concepts)
|
||||||
# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
|
# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
|
||||||
# define __glibcxx_concepts 202002L
|
# define __glibcxx_concepts 202207L
|
||||||
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts)
|
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts)
|
||||||
# define __cpp_lib_concepts 202002L
|
# define __cpp_lib_concepts 202207L
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#endif /* !defined(__cpp_lib_concepts) */
|
#endif /* !defined(__cpp_lib_concepts) */
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
|
{ { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
|
||||||
} // namespace __detail
|
} // 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
|
// [concept.equalitycomparable], concept equality_comparable
|
||||||
|
|
||||||
namespace __detail
|
namespace __detail
|
||||||
|
|
@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp, typename _Up>
|
template<typename _Tp, typename _Up>
|
||||||
concept equality_comparable_with
|
concept equality_comparable_with
|
||||||
= equality_comparable<_Tp> && equality_comparable<_Up>
|
= 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>,
|
&& equality_comparable<common_reference_t<__detail::__cref<_Tp>,
|
||||||
__detail::__cref<_Up>>>
|
__detail::__cref<_Up>>>
|
||||||
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
|
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#pragma GCC system_header
|
#pragma GCC system_header
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define __glibcxx_want_concepts
|
||||||
#define __glibcxx_want_three_way_comparison
|
#define __glibcxx_want_three_way_comparison
|
||||||
#define __glibcxx_want_type_order
|
#define __glibcxx_want_type_order
|
||||||
#include <bits/version.h>
|
#include <bits/version.h>
|
||||||
|
|
@ -499,10 +500,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||||
|
|
||||||
template<typename _Tp, typename _Up, typename _Cat = partial_ordering>
|
template<typename _Tp, typename _Up, typename _Cat = partial_ordering>
|
||||||
concept three_way_comparable_with
|
concept three_way_comparable_with
|
||||||
= three_way_comparable<_Tp, _Cat>
|
= three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat>
|
||||||
&& three_way_comparable<_Up, _Cat>
|
&& __detail::__comparison_common_type_with<_Tp, _Up>
|
||||||
&& common_reference_with<const remove_reference_t<_Tp>&,
|
|
||||||
const remove_reference_t<_Up>&>
|
|
||||||
&& three_way_comparable<
|
&& three_way_comparable<
|
||||||
common_reference_t<const remove_reference_t<_Tp>&,
|
common_reference_t<const remove_reference_t<_Tp>&,
|
||||||
const remove_reference_t<_Up>&>, _Cat>
|
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