Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 52 additions & 5 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ struct _Char_traits { // properties of a string or stream element
using pos_type = streampos;
using off_type = streamoff;
using state_type = _Mbstatet;
#if _HAS_CXX20
using comparison_category = strong_ordering;
#endif // _HAS_CXX20

// For copy/move, we can uniformly call memcpy/memmove (or their builtin versions) for all element types.

Expand Down Expand Up @@ -1671,7 +1674,7 @@ _NODISCARD constexpr bool operator==(
return _Lhs._Equal(_Rhs);
}


#if !_HAS_CXX20
// FUNCTION TEMPLATES operator!= FOR basic_string_view
template <class _Elem, class _Traits>
_NODISCARD constexpr bool operator!=(
Expand Down Expand Up @@ -1770,7 +1773,37 @@ _NODISCARD constexpr bool operator>=(
const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t<basic_string_view<_Elem, _Traits>> _Rhs) noexcept {
return _Lhs.compare(_Rhs) >= 0;
}
#endif // !_HAS_CXX20

#if _HAS_CXX20
template <class _Traits, class = void>
struct _Get_comparison_category {
using comparison_category = weak_ordering;
};

template <class _Traits>
struct _Get_comparison_category<_Traits, void_t<typename _Traits::comparison_category>> {
using comparison_category = typename _Traits::comparison_category;
};

template <class _Elem, class _Traits>
_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>(
const basic_string_view<_Elem, _Traits>& _Lhs, const basic_string_view<_Elem, _Traits>& _Rhs) noexcept {
return static_cast<typename _Get_comparison_category<_Traits>::comparison_category>(_Lhs.compare(_Rhs) <=> 0);
}

template <class _Elem, class _Traits, int = 1> // TRANSITION, VSO-409326
_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>(
const _Identity_t<basic_string_view<_Elem, _Traits>> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept {
return static_cast<typename _Get_comparison_category<_Traits>::comparison_category>(_Lhs.compare(_Rhs) <=> 0);
}

template <class _Elem, class _Traits, int = 2> // TRANSITION, VSO-409326
_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>(
const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t<basic_string_view<_Elem, _Traits>> _Rhs) noexcept {
return static_cast<typename _Get_comparison_category<_Traits>::comparison_category>(_Lhs.compare(_Rhs) <=> 0);
}
#endif // _HAS_CXX20

// TYPEDEFS FOR basic_string_view
using string_view = basic_string_view<char>;
Expand Down Expand Up @@ -4512,13 +4545,14 @@ _NODISCARD bool operator==(
}

template <class _Elem, class _Traits, class _Alloc>
_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) {
return _Right._Equal(_Left);
_NODISCARD bool operator==(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) {
return _Left._Equal(_Right);
}

#if !_HAS_CXX20
template <class _Elem, class _Traits, class _Alloc>
_NODISCARD bool operator==(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) {
return _Left._Equal(_Right);
_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) {
return _Right._Equal(_Left);
}

template <class _Elem, class _Traits, class _Alloc>
Expand Down Expand Up @@ -4600,6 +4634,19 @@ template <class _Elem, class _Traits, class _Alloc>
_NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) {
return !(_Left < _Right);
}
#else // !_HAS_CXX20
template <class _Elem, class _Traits, class _Alloc>
_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>(
const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept {
return static_cast<typename _Get_comparison_category<_Traits>::comparison_category>(_Left.compare(_Right) <=> 0);
}

template <class _Elem, class _Traits, class _Alloc>
_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>(
const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) {
return static_cast<typename _Get_comparison_category<_Traits>::comparison_category>(_Left.compare(_Right) <=> 0);
}
#endif // !_HAS_CXX20

using string = basic_string<char, char_traits<char>, allocator<char>>;
using wstring = basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>;
Expand Down
48 changes: 38 additions & 10 deletions tests/std/tests/P1614R2_spaceship/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,27 +433,55 @@ void ordering_test_cases() {
std::ssub_match sm3 = m3[0];
std::ssub_match sm4 = m4[0];

// TRANSITION, std::char_traits<char> doesn't define comparison_category
spaceship_test<std::weak_ordering>(sm1, sm1_equal, sm2);
spaceship_test<std::weak_ordering>(sm1, s1, s2);
spaceship_test<std::weak_ordering>(sm1, s1.c_str(), s2.c_str());
spaceship_test<std::weak_ordering>(sm3, 'c', 'm');
spaceship_test<std::weak_ordering>(s1, sm1, sm2);
spaceship_test<std::weak_ordering>(s1.c_str(), sm1, sm2);
spaceship_test<std::weak_ordering>('c', sm3, sm4);
spaceship_test<std::strong_ordering>(sm1, sm1_equal, sm2);
spaceship_test<std::strong_ordering>(sm1, s1, s2);
spaceship_test<std::strong_ordering>(sm1, s1.c_str(), s2.c_str());
spaceship_test<std::strong_ordering>(sm3, 'c', 'm');
spaceship_test<std::strong_ordering>(s1, sm1, sm2);
spaceship_test<std::strong_ordering>(s1.c_str(), sm1, sm2);
spaceship_test<std::strong_ordering>('c', sm3, sm4);

using StronglyOrderedMatch = std::ssub_match;
using WeaklyOrderedMatch = std::sub_match<std::basic_string<WeaklyOrderedChar>::const_iterator>;
using WeaklyOrderdByOmissionMatch =
std::sub_match<std::basic_string<WeaklyOrderedByOmissionChar>::const_iterator>;
using PartiallyOrderedMatch = std::sub_match<std::basic_string<PartiallyOrderedChar>::const_iterator>;

// TRANSITION, std::char_traits<char> doesn't define comparison_category
static_assert(std::is_same_v<SpaceshipType<StronglyOrderedMatch>, std::weak_ordering>);
static_assert(std::is_same_v<SpaceshipType<StronglyOrderedMatch>, std::strong_ordering>);
static_assert(std::is_same_v<SpaceshipType<WeaklyOrderedMatch>, std::weak_ordering>);
static_assert(std::is_same_v<SpaceshipType<WeaklyOrderdByOmissionMatch>, std::weak_ordering>);
static_assert(std::is_same_v<SpaceshipType<PartiallyOrderedMatch>, std::partial_ordering>);
}
{ // Strings library
const std::string a1 = "abcdef";
const std::string a2 = "abcdef";
const std::string a3 = "abcdefg";
const std::string a4 = "abcde";
const std::string a5 = "abddef";
const std::string a6 = "abbdef";

assert((a1 <=> a2) == std::strong_ordering::equivalent);
assert((a1 <=> a3) == std::strong_ordering::less);
assert((a1 <=> a4) == std::strong_ordering::greater);
assert((a1 <=> a5) == std::strong_ordering::less);
assert((a1 <=> a6) == std::strong_ordering::greater);

assert(a1 == a2);
assert(a1 >= a2);
assert(a1 <= a2);
assert(a1 < a3);
assert(a1 <= a3);
assert(a1 != a3);
assert(a1 > a4);
assert(a1 >= a4);
assert(a1 != a4);
assert(a1 < a5);
assert(a1 <= a5);
assert(a1 != a5);
assert(a1 > a6);
assert(a1 >= a6);
assert(a1 != a6);
}
{ // Diagnostics Library
diagnostics_test<std::error_code>();
diagnostics_test<std::error_condition>();
Expand Down