From 5bf2f2d1d847f20df92d5f2eb42b0d35b25a1c0c Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Tue, 9 Feb 2021 08:29:10 -0800 Subject: [PATCH 01/20] added spaceship string --- stl/inc/xstring | 49 +++++++++++++++------- tests/std/tests/P1614R2_spaceship/test.cpp | 30 +++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 80355987c2c..cac05e1bdad 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -34,11 +34,12 @@ _STD_BEGIN // STRUCT TEMPLATE _Char_traits (FROM ) template struct _Char_traits { // properties of a string or stream element - using char_type = _Elem; - using int_type = _Int_type; - using pos_type = streampos; - using off_type = streamoff; - using state_type = _Mbstatet; + using char_type = _Elem; + using int_type = _Int_type; + using pos_type = streampos; + using off_type = streamoff; + using state_type = _Mbstatet; + using comparison_category = strong_ordering; // For copy/move, we can uniformly call memcpy/memmove (or their builtin versions) for all element types. @@ -212,11 +213,12 @@ private: using _Primary_char_traits = _Char_traits<_Elem, unsigned short>; public: - using char_type = _Elem; - using int_type = unsigned short; - using pos_type = streampos; - using off_type = streamoff; - using state_type = mbstate_t; + using char_type = _Elem; + using int_type = unsigned short; + using pos_type = streampos; + using off_type = streamoff; + using state_type = mbstate_t; + using comparison_category = strong_ordering; using _Primary_char_traits::_Copy_s; using _Primary_char_traits::copy; @@ -350,11 +352,12 @@ private: using _Primary_char_traits = _Char_traits<_Elem, _Int_type>; public: - using char_type = _Elem; - using int_type = _Int_type; - using pos_type = streampos; - using off_type = streamoff; - using state_type = mbstate_t; + using char_type = _Elem; + using int_type = _Int_type; + using pos_type = streampos; + using off_type = streamoff; + using state_type = mbstate_t; + using comparison_category = strong_ordering; using _Primary_char_traits::_Copy_s; using _Primary_char_traits::copy; @@ -4511,16 +4514,19 @@ _NODISCARD bool operator==( return _Left._Equal(_Right); } +#if !_HAS_CXX20 template _NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { return _Right._Equal(_Left); } +#endif // !_HAS_CXX20 template _NODISCARD bool operator==(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return _Left._Equal(_Right); } +#if !_HAS_CXX20 template _NODISCARD bool operator!=( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { @@ -4600,6 +4606,19 @@ template _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 + +#if _HAS_CXX20 +template +_NODISCARD int operator<=>( + const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { + return _Left.compare(_Right); +} +template +_NODISCARD int operator<=>(const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { + return _Left.compare(_Right); +} +#endif // _HAS_CXX20 using string = basic_string, allocator>; using wstring = basic_string, allocator>; diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index c488238b56f..a517a1f2bd2 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -454,6 +454,36 @@ void ordering_test_cases() { static_assert(std::is_same_v, std::weak_ordering>); static_assert(std::is_same_v, std::partial_ordering>); } + { // Strings library + std::string a1 = "abcdef"; + std::string a2 = "abcdef"; + std::string a3 = "abcdefg"; + std::string a4 = "abcde"; + std::string a5 = "abddef"; + std::string a6 = "abbdef"; + + assert((a1 <=> a2) == 0); + assert((a1 <=> a3) == -1); + assert((a1 <=> a4) == 1); + assert((a1 <=> a5) == -1); + assert((a1 <=> a6) == 1); + + 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(); diagnostics_test(); From 512b50950bb0d669c96b3bf5b95a20b10e0a9233 Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Tue, 9 Feb 2021 10:29:54 -0800 Subject: [PATCH 02/20] add compare --- stl/inc/xstring | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index cac05e1bdad..f754d8c4482 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -17,6 +17,10 @@ #include #endif // _HAS_CXX17 +#if _HAS_CXX20 +#include +#endif // _HAS_CXX20 + #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) @@ -34,12 +38,14 @@ _STD_BEGIN // STRUCT TEMPLATE _Char_traits (FROM ) template struct _Char_traits { // properties of a string or stream element - using char_type = _Elem; - using int_type = _Int_type; - using pos_type = streampos; - using off_type = streamoff; - using state_type = _Mbstatet; - using comparison_category = strong_ordering; + using char_type = _Elem; + using int_type = _Int_type; + using pos_type = streampos; + using off_type = streamoff; + using state_type = _Mbstatet; +#if _HAS_CXX20 + using comparison_category = _Comparison_category_strong; +#endif // _HAS_CXX20 // For copy/move, we can uniformly call memcpy/memmove (or their builtin versions) for all element types. @@ -213,12 +219,14 @@ private: using _Primary_char_traits = _Char_traits<_Elem, unsigned short>; public: - using char_type = _Elem; - using int_type = unsigned short; - using pos_type = streampos; - using off_type = streamoff; - using state_type = mbstate_t; - using comparison_category = strong_ordering; + using char_type = _Elem; + using int_type = unsigned short; + using pos_type = streampos; + using off_type = streamoff; + using state_type = mbstate_t; +#if _HAS_CXX20 + using comparison_category = _Comparison_category_strong; +#endif // _HAS_CXX20 using _Primary_char_traits::_Copy_s; using _Primary_char_traits::copy; @@ -352,12 +360,14 @@ private: using _Primary_char_traits = _Char_traits<_Elem, _Int_type>; public: - using char_type = _Elem; - using int_type = _Int_type; - using pos_type = streampos; - using off_type = streamoff; - using state_type = mbstate_t; - using comparison_category = strong_ordering; + using char_type = _Elem; + using int_type = _Int_type; + using pos_type = streampos; + using off_type = streamoff; + using state_type = mbstate_t; +#if _HAS_CXX20 + using comparison_category = _Comparison_category_strong; +#endif // _HAS_CXX20 using _Primary_char_traits::_Copy_s; using _Primary_char_traits::copy; From 75522ebafcf827d1d04aa8ebbd5c6b9f5689b20a Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Tue, 9 Feb 2021 15:56:02 -0800 Subject: [PATCH 03/20] retourn to strong_ordering --- stl/inc/xstring | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index f754d8c4482..e3a61e2f9ed 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -44,7 +44,7 @@ struct _Char_traits { // properties of a string or stream element using off_type = streamoff; using state_type = _Mbstatet; #if _HAS_CXX20 - using comparison_category = _Comparison_category_strong; + 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. @@ -225,7 +225,7 @@ public: using off_type = streamoff; using state_type = mbstate_t; #if _HAS_CXX20 - using comparison_category = _Comparison_category_strong; + using comparison_category = strong_ordering; #endif // _HAS_CXX20 using _Primary_char_traits::_Copy_s; @@ -366,7 +366,7 @@ public: using off_type = streamoff; using state_type = mbstate_t; #if _HAS_CXX20 - using comparison_category = _Comparison_category_strong; + using comparison_category = strong_ordering; #endif // _HAS_CXX20 using _Primary_char_traits::_Copy_s; From 5ec03eb5e172805206e96b5deb9a4eba64e9aed0 Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Tue, 9 Feb 2021 17:47:39 -0800 Subject: [PATCH 04/20] changed type --- stl/inc/xstring | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index e3a61e2f9ed..f5631351261 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4620,12 +4620,12 @@ _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I #if _HAS_CXX20 template -_NODISCARD int operator<=>( +_NODISCARD strong_ordering operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { return _Left.compare(_Right); } template -_NODISCARD int operator<=>(const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { +_NODISCARD strong_ordering operator<=>(const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { return _Left.compare(_Right); } #endif // _HAS_CXX20 From 3197da27e1284829fb435a7da615364ecfef1114 Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Wed, 10 Feb 2021 12:19:08 -0800 Subject: [PATCH 05/20] changed to return strong ordering results --- stl/inc/xstring | 16 ++++++++++++++-- tests/std/tests/P1614R2_spaceship/test.cpp | 10 +++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index f5631351261..251b77e2f79 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4622,11 +4622,23 @@ _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I template _NODISCARD strong_ordering operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { - return _Left.compare(_Right); + int _comparison = _Left.compare(_Right); + if (_comparison == 0) { + return strong_ordering::equivalent; + } else if (_comparison < 0) { + return strong_ordering::less; + } + return strong_ordering::greater; } template _NODISCARD strong_ordering operator<=>(const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { - return _Left.compare(_Right); + int _comparison = _Left.compare(_Right); + if (_comparison == 0) { + return strong_ordering::equivalent; + } else if (_comparison < 0) { + return strong_ordering::less; + } + return strong_ordering::greater; } #endif // _HAS_CXX20 diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index a517a1f2bd2..bbe2959a0f1 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -462,11 +462,11 @@ void ordering_test_cases() { std::string a5 = "abddef"; std::string a6 = "abbdef"; - assert((a1 <=> a2) == 0); - assert((a1 <=> a3) == -1); - assert((a1 <=> a4) == 1); - assert((a1 <=> a5) == -1); - assert((a1 <=> a6) == 1); + 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); From 03d5ecc021a908be762bb2e441564024ac3adf58 Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Thu, 11 Feb 2021 09:50:28 -0800 Subject: [PATCH 06/20] change test to strong order --- tests/std/tests/P1614R2_spaceship/test.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index bbe2959a0f1..e664a2578a8 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -433,14 +433,13 @@ void ordering_test_cases() { std::ssub_match sm3 = m3[0]; std::ssub_match sm4 = m4[0]; - // TRANSITION, std::char_traits doesn't define comparison_category - spaceship_test(sm1, sm1_equal, sm2); - spaceship_test(sm1, s1, s2); - spaceship_test(sm1, s1.c_str(), s2.c_str()); - spaceship_test(sm3, 'c', 'm'); - spaceship_test(s1, sm1, sm2); - spaceship_test(s1.c_str(), sm1, sm2); - spaceship_test('c', sm3, sm4); + spaceship_test(sm1, sm1_equal, sm2); + spaceship_test(sm1, s1, s2); + spaceship_test(sm1, s1.c_str(), s2.c_str()); + spaceship_test(sm3, 'c', 'm'); + spaceship_test(s1, sm1, sm2); + spaceship_test(s1.c_str(), sm1, sm2); + spaceship_test('c', sm3, sm4); using StronglyOrderedMatch = std::ssub_match; using WeaklyOrderedMatch = std::sub_match::const_iterator>; @@ -448,8 +447,7 @@ void ordering_test_cases() { std::sub_match::const_iterator>; using PartiallyOrderedMatch = std::sub_match::const_iterator>; - // TRANSITION, std::char_traits doesn't define comparison_category - static_assert(std::is_same_v, std::weak_ordering>); + static_assert(std::is_same_v, std::strong_ordering>); static_assert(std::is_same_v, std::weak_ordering>); static_assert(std::is_same_v, std::weak_ordering>); static_assert(std::is_same_v, std::partial_ordering>); From 1418c12b05769ab76ef2d202eacd26458e057c2a Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Thu, 11 Feb 2021 17:15:49 -0800 Subject: [PATCH 07/20] _Get_comparison_category --- stl/inc/xstring | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 251b77e2f79..5951c37e2c6 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4619,26 +4619,23 @@ _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I #endif // !_HAS_CXX20 #if _HAS_CXX20 +template +struct _Get_comparison_category { + using comparison_category = weak_ordering; +}; +template +struct _Get_comparison_category<_Traits, void_t> { + using comparison_category = typename _Traits::comparison_category; +}; template -_NODISCARD strong_ordering operator<=>( +_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { - int _comparison = _Left.compare(_Right); - if (_comparison == 0) { - return strong_ordering::equivalent; - } else if (_comparison < 0) { - return strong_ordering::less; - } - return strong_ordering::greater; + return static_cast::comparison_category>(_Left.compare(_Right) <=> 0); } template -_NODISCARD strong_ordering operator<=>(const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { - int _comparison = _Left.compare(_Right); - if (_comparison == 0) { - return strong_ordering::equivalent; - } else if (_comparison < 0) { - return strong_ordering::less; - } - return strong_ordering::greater; +_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( + const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { + return static_cast::comparison_category>(_Left.compare(_Right) <=> 0); } #endif // _HAS_CXX20 From d90c940a66647e3432e5cbedcc15dc3bd6128deb Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Fri, 12 Feb 2021 13:17:00 -0800 Subject: [PATCH 08/20] added and removed more operators --- stl/inc/xstring | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 5951c37e2c6..c891ccff037 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1684,7 +1684,7 @@ _NODISCARD constexpr bool operator==( return _Lhs._Equal(_Rhs); } - +#if !_HAS_CXX20 // FUNCTION TEMPLATES operator!= FOR basic_string_view template _NODISCARD constexpr bool operator!=( @@ -1783,7 +1783,37 @@ _NODISCARD constexpr bool operator>=( const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t> _Rhs) noexcept { return _Lhs.compare(_Rhs) >= 0; } +#endif // !_HAS_CXX20 + +#if _HAS_CXX20 +template +struct _Get_comparison_category { + using comparison_category = weak_ordering; +}; + +template +struct _Get_comparison_category<_Traits, void_t> { + using comparison_category = typename _Traits::comparison_category; +}; + +template +_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::comparison_category>(_Lhs.compare(_Rhs) <=> 0); +} +template // TRANSITION, VSO-409326 +_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( + const _Identity_t> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept { + return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); +} + +template // TRANSITION, VSO-409326 +_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( + const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t> _Rhs) noexcept { + return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); +} +#endif // _HAS_CXX20 // TYPEDEFS FOR basic_string_view using string_view = basic_string_view; @@ -4619,19 +4649,12 @@ _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I #endif // !_HAS_CXX20 #if _HAS_CXX20 -template -struct _Get_comparison_category { - using comparison_category = weak_ordering; -}; -template -struct _Get_comparison_category<_Traits, void_t> { - using comparison_category = typename _Traits::comparison_category; -}; template _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::comparison_category>(_Left.compare(_Right) <=> 0); } + template _NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { From 10886da7e2dcd34d042afe2fde6fb0442a99287d Mon Sep 17 00:00:00 2001 From: Anju Del Moral Gonzalez Date: Tue, 16 Feb 2021 15:38:59 -0800 Subject: [PATCH 09/20] re arrenged for pre procesor --- stl/inc/xstring | 28 ++++++---------------- tests/std/tests/P1614R2_spaceship/test.cpp | 12 +++++----- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index c891ccff037..53e0796255a 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -17,10 +17,6 @@ #include #endif // _HAS_CXX17 -#if _HAS_CXX20 -#include -#endif // _HAS_CXX20 - #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) @@ -224,9 +220,6 @@ 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; @@ -365,9 +358,6 @@ 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; @@ -4554,19 +4544,17 @@ _NODISCARD bool operator==( return _Left._Equal(_Right); } -#if !_HAS_CXX20 -template -_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { - return _Right._Equal(_Left); -} -#endif // !_HAS_CXX20 - template _NODISCARD bool operator==(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return _Left._Equal(_Right); } #if !_HAS_CXX20 +template +_NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { + return _Right._Equal(_Left); +} + template _NODISCARD bool operator!=( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { @@ -4646,9 +4634,7 @@ template _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return !(_Left < _Right); } -#endif // !_HAS_CXX20 - -#if _HAS_CXX20 +#else // !_HAS_CXX20 template _NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { @@ -4660,7 +4646,7 @@ _NODISCARD typename _Get_comparison_category<_Traits>::comparison_category opera const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { return static_cast::comparison_category>(_Left.compare(_Right) <=> 0); } -#endif // _HAS_CXX20 +#endif // !_HAS_CXX20 using string = basic_string, allocator>; using wstring = basic_string, allocator>; diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index e664a2578a8..1270477dd42 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -453,12 +453,12 @@ void ordering_test_cases() { static_assert(std::is_same_v, std::partial_ordering>); } { // Strings library - std::string a1 = "abcdef"; - std::string a2 = "abcdef"; - std::string a3 = "abcdefg"; - std::string a4 = "abcde"; - std::string a5 = "abddef"; - std::string a6 = "abbdef"; + 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); From 8b09b9c8c5ebe1822fa85672da3dfd021e8e2398 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 16 Feb 2021 15:58:52 -0800 Subject: [PATCH 10/20] Update stl/inc/xstring Clarify `#else` comment. --- stl/inc/xstring | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 53e0796255a..ddc236f4fc5 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4634,7 +4634,7 @@ template _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return !(_Left < _Right); } -#else // !_HAS_CXX20 +#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv template _NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) noexcept { From 7b205c5b9b4f4000d2f114be9bea3b28b389d8a3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 19:33:57 -0800 Subject: [PATCH 11/20] Remove outdated test comment (unrelated to other changes) --- tests/std/tests/P1614R2_spaceship/test.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index 1270477dd42..b3a5a44c8a8 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// Covers: -// * spaceship for containers - #include #include #include From 7a79abbc0e7258a65a61f167576407af581fa428 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 19:50:56 -0800 Subject: [PATCH 12/20] Fix/test char_traits::comparison_category. We need to modify _WChar_traits and _Narrow_char_traits. --- stl/inc/xstring | 6 ++++++ tests/std/tests/P1614R2_spaceship/test.cpp | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/stl/inc/xstring b/stl/inc/xstring index ddc236f4fc5..8ee51d14e48 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -220,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 using _Primary_char_traits::_Copy_s; using _Primary_char_traits::copy; @@ -358,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; diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index b3a5a44c8a8..4216b730679 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -449,6 +449,15 @@ void ordering_test_cases() { static_assert(std::is_same_v, std::weak_ordering>); static_assert(std::is_same_v, std::partial_ordering>); } + { // char_traits + static_assert(std::is_same_v::comparison_category, std::strong_ordering>); +#ifdef __cpp_char8_t + static_assert(std::is_same_v::comparison_category, std::strong_ordering>); +#endif // __cpp_char8_t + static_assert(std::is_same_v::comparison_category, std::strong_ordering>); + static_assert(std::is_same_v::comparison_category, std::strong_ordering>); + static_assert(std::is_same_v::comparison_category, std::strong_ordering>); + } { // Strings library const std::string a1 = "abcdef"; const std::string a2 = "abcdef"; From 1068934f98370fb7ca9bf646a205f27001c9f5b2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:18:14 -0800 Subject: [PATCH 13/20] C++20 needs only one _Identity_t overload. --- stl/inc/xstring | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 8ee51d14e48..46fb6c60249 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1668,11 +1668,13 @@ _NODISCARD constexpr bool operator==( return _Lhs._Equal(_Rhs); } +#if !_HAS_CXX20 template // TRANSITION, VSO-409326 _NODISCARD constexpr bool operator==( const _Identity_t> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept { return _Lhs._Equal(_Rhs); } +#endif // !_HAS_CXX20 template // TRANSITION, VSO-409326 _NODISCARD constexpr bool operator==( @@ -1798,12 +1800,6 @@ _NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_cate return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); } -template // TRANSITION, VSO-409326 -_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( - const _Identity_t> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept { - return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); -} - template // TRANSITION, VSO-409326 _NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t> _Rhs) noexcept { From 3b7ff1807893f37a42f4b293b9643dbc61f65735 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:24:58 -0800 Subject: [PATCH 14/20] Spaceship should take basic_string_view by value, like other operators. --- stl/inc/xstring | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 46fb6c60249..ffc2e7da555 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1796,7 +1796,7 @@ struct _Get_comparison_category<_Traits, void_t _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 { + const basic_string_view<_Elem, _Traits> _Lhs, const basic_string_view<_Elem, _Traits> _Rhs) noexcept { return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); } From 197d7f4a4ffbd35b36fec156616aacbcc282f032 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:28:24 -0800 Subject: [PATCH 15/20] Simplify syntax with an alias template. --- stl/inc/xstring | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index ffc2e7da555..07b0bde2267 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1786,24 +1786,27 @@ _NODISCARD constexpr bool operator>=( #if _HAS_CXX20 template struct _Get_comparison_category { - using comparison_category = weak_ordering; + using type = weak_ordering; }; template struct _Get_comparison_category<_Traits, void_t> { - using comparison_category = typename _Traits::comparison_category; + using type = typename _Traits::comparison_category; }; +template +using _Get_comparison_category_t = typename _Get_comparison_category<_Traits>::type; + template -_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( +_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::comparison_category>(_Lhs.compare(_Rhs) <=> 0); + return static_cast<_Get_comparison_category_t<_Traits>>(_Lhs.compare(_Rhs) <=> 0); } template // TRANSITION, VSO-409326 -_NODISCARD constexpr typename _Get_comparison_category<_Traits>::comparison_category operator<=>( +_NODISCARD constexpr _Get_comparison_category_t<_Traits> operator<=>( const basic_string_view<_Elem, _Traits> _Lhs, const _Identity_t> _Rhs) noexcept { - return static_cast::comparison_category>(_Lhs.compare(_Rhs) <=> 0); + return static_cast<_Get_comparison_category_t<_Traits>>(_Lhs.compare(_Rhs) <=> 0); } #endif // _HAS_CXX20 @@ -4638,15 +4641,15 @@ _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I } #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv template -_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( +_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::comparison_category>(_Left.compare(_Right) <=> 0); + return static_cast<_Get_comparison_category_t<_Traits>>(_Left.compare(_Right) <=> 0); } template -_NODISCARD typename _Get_comparison_category<_Traits>::comparison_category operator<=>( +_NODISCARD _Get_comparison_category_t<_Traits> operator<=>( const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { - return static_cast::comparison_category>(_Left.compare(_Right) <=> 0); + return static_cast<_Get_comparison_category_t<_Traits>>(_Left.compare(_Right) <=> 0); } #endif // !_HAS_CXX20 From dd583ae91657e8ee8fdd6a91548455b96d7b6eac Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:33:54 -0800 Subject: [PATCH 16/20] Implement LWG-3432 "Missing requirement for comparison_category". --- stl/inc/xstring | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stl/inc/xstring b/stl/inc/xstring index 07b0bde2267..b8cecd2b2c4 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1792,6 +1792,9 @@ struct _Get_comparison_category { template struct _Get_comparison_category<_Traits, void_t> { using type = typename _Traits::comparison_category; + + static_assert(_Is_any_of_v, + "N4878 [string.view.comparison]/4: Mandates: R denotes a comparison category type."); }; template From bc17fdc7a4b6c15d395812fbaadfbe5fc1a629b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:53:15 -0800 Subject: [PATCH 17/20] Add SAL and top-level const for consistency. --- stl/inc/xstring | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index b8cecd2b2c4..ed5d40c314f 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4651,7 +4651,7 @@ _NODISCARD _Get_comparison_category_t<_Traits> operator<=>( template _NODISCARD _Get_comparison_category_t<_Traits> operator<=>( - const basic_string<_Elem, _Traits, _Alloc>& _Left, const _Elem* _Right) { + 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); } #endif // !_HAS_CXX20 From 6a864dbb9d52e5611f1d1efe8a5af2d3a1452b4b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 20:58:47 -0800 Subject: [PATCH 18/20] Avoid negated _HAS_CXX20 condition. --- stl/inc/xstring | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index ed5d40c314f..c5fc7e1c89f 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4557,7 +4557,19 @@ _NODISCARD bool operator==(const basic_string<_Elem, _Traits, _Alloc>& _Left, _I return _Left._Equal(_Right); } -#if !_HAS_CXX20 +#if _HAS_CXX20 +template +_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 +_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 _NODISCARD bool operator==(_In_z_ const _Elem* const _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { return _Right._Equal(_Left); @@ -4642,19 +4654,7 @@ template _NODISCARD bool operator>=(const basic_string<_Elem, _Traits, _Alloc>& _Left, _In_z_ const _Elem* const _Right) { return !(_Left < _Right); } -#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv -template -_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 -_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); -} -#endif // !_HAS_CXX20 +#endif // ^^^ !_HAS_CXX20 ^^^ using string = basic_string, allocator>; using wstring = basic_string, allocator>; From 5061dabb315b2dd7a21a34cc72b50d3a168d785f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 21:16:21 -0800 Subject: [PATCH 19/20] Test string <=> ptr and ptr <=> string. --- tests/std/tests/P1614R2_spaceship/test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index 4216b730679..770d160cecd 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -487,6 +487,14 @@ void ordering_test_cases() { 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); } { // Diagnostics Library diagnostics_test(); From fa7e5e69ab94a3fd908267561a61145d1c650d3c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 21:23:38 -0800 Subject: [PATCH 20/20] Test string_view at runtime and compiletime. --- tests/std/tests/P1614R2_spaceship/test.cpp | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index 770d160cecd..cd7135057be 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -496,6 +497,82 @@ void ordering_test_cases() { 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(); diagnostics_test();