libstdc++: Implement spaceship for std::array (P1614R2)
As done for std::pair, this defines operator<=> as a non-member function template and does not alter operator==, as expected to be proposed as the resolution to an unpublished LWG issue. Instead of calling std::lexicographical_compare_three_way the <=> overload is implemented by hand to take advantage of the fact the element types and array sizes are known to be the same. * include/bits/cpp_type_traits.h (__is_byte<char8_t>): Add specialization. * include/std/array (operator<=>): Likewise. * testsuite/23_containers/array/comparison_operators/constexpr.cc: Test three-way comparisons and arrays of unsigned char. * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust dg-error line numbers. From-SVN: r278981
This commit is contained in:
parent
880c7b8c25
commit
3a4cc6281b
5 changed files with 62 additions and 3 deletions
|
@ -1,3 +1,13 @@
|
|||
2019-12-05 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/cpp_type_traits.h (__is_byte<char8_t>): Add
|
||||
specialization.
|
||||
* include/std/array (operator<=>): Likewise.
|
||||
* testsuite/23_containers/array/comparison_operators/constexpr.cc:
|
||||
Test three-way comparisons and arrays of unsigned char.
|
||||
* testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust
|
||||
dg-error line numbers.
|
||||
|
||||
2019-12-03 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/stl_pair.h [__cpp_lib_three_way_comparison]
|
||||
|
|
|
@ -411,6 +411,15 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
|
|||
};
|
||||
#endif // C++17
|
||||
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<>
|
||||
struct __is_byte<char8_t>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// Move iterator type
|
||||
//
|
||||
|
|
|
@ -253,6 +253,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return std::equal(__one.begin(), __one.end(), __two.begin()); }
|
||||
|
||||
#if __cpp_lib_three_way_comparison && __cpp_lib_concepts
|
||||
template<typename _Tp, size_t _Nm>
|
||||
constexpr __detail::__synth3way_t<_Tp>
|
||||
operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||
{
|
||||
if constexpr (_Nm && __is_byte<_Tp>::__value)
|
||||
return __builtin_memcmp(__a.data(), __b.data(), _Nm) <=> 0;
|
||||
else
|
||||
{
|
||||
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||
{
|
||||
auto __c = __detail::__synth3way(__a[__i], __b[__i]);
|
||||
if (__c != 0)
|
||||
return __c;
|
||||
}
|
||||
}
|
||||
return strong_ordering::equal;
|
||||
}
|
||||
#else
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
|
@ -285,6 +304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
inline bool
|
||||
operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one < __two); }
|
||||
#endif // three_way_comparison && concepts
|
||||
|
||||
// Specialized algorithms.
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
|
|
|
@ -31,3 +31,23 @@ static_assert(a1 < a3);
|
|||
static_assert(a4 > a1);
|
||||
static_assert(a1 <= a3);
|
||||
static_assert(a4 >= a1);
|
||||
static_assert(std::is_eq(a1 <=> a1));
|
||||
static_assert(std::is_neq(a1 <=> a2));
|
||||
static_assert(std::is_lt(a1 <=> a3));
|
||||
static_assert(std::is_gt(a4 <=> a1));
|
||||
|
||||
constexpr std::array<unsigned char, 3> a5{{1, 2, 3}};
|
||||
constexpr std::array<unsigned char, 3> a6{{4, 5, 6}};
|
||||
constexpr std::array<unsigned char, 3> a7{{1, 2, 4}};
|
||||
constexpr std::array<unsigned char, 3> a8{{1, 3, 3}};
|
||||
|
||||
static_assert(a5 == a5);
|
||||
static_assert(a5 != a6);
|
||||
static_assert(a5 < a7);
|
||||
static_assert(a8 > a5);
|
||||
static_assert(a5 <= a7);
|
||||
static_assert(a8 >= a5);
|
||||
static_assert(std::is_eq(a5 <=> a5));
|
||||
static_assert(std::is_neq(a5 <=> a6));
|
||||
static_assert(std::is_lt(a5 <=> a7));
|
||||
static_assert(std::is_gt(a8 <=> a5));
|
||||
|
|
|
@ -27,6 +27,6 @@ int n1 = std::get<1>(a);
|
|||
int n2 = std::get<1>(std::move(a));
|
||||
int n3 = std::get<1>(ca);
|
||||
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 316 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 325 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 333 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 336 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 345 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 353 }
|
||||
|
|
Loading…
Add table
Reference in a new issue