Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
65 changes: 60 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 @@ -217,6 +220,9 @@ public:
using pos_type = streampos;
using off_type = streamoff;
using state_type = mbstate_t;
#if _HAS_CXX20
using comparison_category = strong_ordering;
#endif // _HAS_CXX20
Comment thread
AnjuDel marked this conversation as resolved.

using _Primary_char_traits::_Copy_s;
using _Primary_char_traits::copy;
Expand Down Expand Up @@ -355,6 +361,9 @@ public:
using pos_type = streampos;
using off_type = streamoff;
using state_type = mbstate_t;
#if _HAS_CXX20
using comparison_category = strong_ordering;
#endif // _HAS_CXX20

using _Primary_char_traits::_Copy_s;
using _Primary_char_traits::copy;
Expand Down Expand Up @@ -1659,19 +1668,21 @@ _NODISCARD constexpr bool operator==(
return _Lhs._Equal(_Rhs);
}

#if !_HAS_CXX20
template <class _Elem, class _Traits, int = 1> // TRANSITION, VSO-409326
_NODISCARD constexpr bool operator==(
const _Identity_t<basic_string_view<_Elem, _Traits>> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept {
return _Lhs._Equal(_Rhs);
}
#endif // !_HAS_CXX20

template <class _Elem, class _Traits, int = 2> // TRANSITION, VSO-409326
_NODISCARD constexpr bool operator==(
const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t<basic_string_view<_Elem, _Traits>> _Rhs) noexcept {
return _Lhs._Equal(_Rhs);
}


#if !_HAS_CXX20
Comment thread
AnjuDel marked this conversation as resolved.
// FUNCTION TEMPLATES operator!= FOR basic_string_view
template <class _Elem, class _Traits>
_NODISCARD constexpr bool operator!=(
Expand Down Expand Up @@ -1770,7 +1781,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 type = weak_ordering;
};

template <class _Traits>
Comment thread
AnjuDel marked this conversation as resolved.
struct _Get_comparison_category<_Traits, void_t<typename _Traits::comparison_category>> {
using type = typename _Traits::comparison_category;

static_assert(_Is_any_of_v<type, partial_ordering, weak_ordering, strong_ordering>,
"N4878 [string.view.comparison]/4: Mandates: R denotes a comparison category type.");
};

template <class _Traits>
using _Get_comparison_category_t = typename _Get_comparison_category<_Traits>::type;

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

template <class _Elem, class _Traits, int = 2> // TRANSITION, VSO-409326
_NODISCARD constexpr _Get_comparison_category_t<_Traits> operator<=>(
const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t<basic_string_view<_Elem, _Traits>> _Rhs) noexcept {
return static_cast<_Get_comparison_category_t<_Traits>>(_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 +4553,26 @@ _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 _Get_comparison_category_t<_Traits> operator<=>(
const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept {
return static_cast<_Get_comparison_category_t<_Traits>>(_Left.compare(_Right) <=> 0);
}

template <class _Elem, class _Traits, class _Alloc>
_NODISCARD _Get_comparison_category_t<_Traits> operator<=>(
const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) {
return static_cast<_Get_comparison_category_t<_Traits>>(_Left.compare(_Right) <=> 0);
}
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
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);
}

template <class _Elem, class _Traits, class _Alloc>
Expand Down Expand Up @@ -4600,6 +4654,7 @@ 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);
}
#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
145 changes: 132 additions & 13 deletions tests/std/tests/P1614R2_spaceship/test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Covers:
// * spaceship for containers

#include <array>
#include <cassert>
#include <compare>
Expand All @@ -21,6 +18,7 @@
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <system_error>
#include <thread>
#include <type_traits>
Expand Down Expand Up @@ -433,27 +431,148 @@ 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>);
}
{ // char_traits
static_assert(std::is_same_v<std::char_traits<char>::comparison_category, std::strong_ordering>);
#ifdef __cpp_char8_t
static_assert(std::is_same_v<std::char_traits<char8_t>::comparison_category, std::strong_ordering>);
#endif // __cpp_char8_t
static_assert(std::is_same_v<std::char_traits<char16_t>::comparison_category, std::strong_ordering>);
static_assert(std::is_same_v<std::char_traits<char32_t>::comparison_category, std::strong_ordering>);
static_assert(std::is_same_v<std::char_traits<wchar_t>::comparison_category, std::strong_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);

assert((a1 <=> "aardvark") == std::strong_ordering::greater);
assert((a1 <=> "abcdef") == std::strong_ordering::equivalent);
assert((a1 <=> "zebra") == std::strong_ordering::less);

assert(("aardvark" <=> a1) == std::strong_ordering::less);
assert(("abcdef" <=> a1) == std::strong_ordering::equivalent);
assert(("zebra" <=> a1) == std::strong_ordering::greater);
}
{ // string_view
const std::string_view a1 = "abcdef";
const std::string_view a2 = "abcdef";
const std::string_view a3 = "abcdefg";
const std::string_view a4 = "abcde";
const std::string_view a5 = "abddef";
const std::string_view 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);

assert((a1 <=> "aardvark") == std::strong_ordering::greater);
assert((a1 <=> "abcdef") == std::strong_ordering::equivalent);
assert((a1 <=> "zebra") == std::strong_ordering::less);

assert(("aardvark" <=> a1) == std::strong_ordering::less);
assert(("abcdef" <=> a1) == std::strong_ordering::equivalent);
assert(("zebra" <=> a1) == std::strong_ordering::greater);
}
{ // constexpr string_view
constexpr std::string_view a1 = "abcdef";
constexpr std::string_view a2 = "abcdef";
constexpr std::string_view a3 = "abcdefg";
constexpr std::string_view a4 = "abcde";
constexpr std::string_view a5 = "abddef";
constexpr std::string_view a6 = "abbdef";

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

static_assert(a1 == a2);
static_assert(a1 >= a2);
static_assert(a1 <= a2);
static_assert(a1 < a3);
static_assert(a1 <= a3);
static_assert(a1 != a3);
static_assert(a1 > a4);
static_assert(a1 >= a4);
static_assert(a1 != a4);
static_assert(a1 < a5);
static_assert(a1 <= a5);
static_assert(a1 != a5);
static_assert(a1 > a6);
static_assert(a1 >= a6);
static_assert(a1 != a6);

static_assert((a1 <=> "aardvark") == std::strong_ordering::greater);
static_assert((a1 <=> "abcdef") == std::strong_ordering::equivalent);
static_assert((a1 <=> "zebra") == std::strong_ordering::less);

static_assert(("aardvark" <=> a1) == std::strong_ordering::less);
static_assert(("abcdef" <=> a1) == std::strong_ordering::equivalent);
static_assert(("zebra" <=> a1) == std::strong_ordering::greater);
}
{ // Diagnostics Library
diagnostics_test<std::error_code>();
diagnostics_test<std::error_condition>();
Expand Down