Index: libcxx/include/__string =================================================================== --- libcxx/include/__string +++ libcxx/include/__string @@ -55,6 +55,7 @@ #include <__config> #include // for search and min +#include // for spaceship support #include // For EOF. #include // for __murmur2_or_cityhash @@ -357,6 +358,11 @@ typedef streampos pos_type; typedef mbstate_t state_type; + // comparison_category is only available in C++20 on. + #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + using comparison_category = strong_ordering; + #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT @@ -460,6 +466,11 @@ typedef streampos pos_type; typedef mbstate_t state_type; + // comparison_category is only available in C++20 on. + #if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + using comparison_category = strong_ordering; + #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT @@ -590,6 +601,11 @@ typedef u8streampos pos_type; typedef mbstate_t state_type; + // comparison_category is only available in C++20 on. + #if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + using comparison_category = strong_ordering; + #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept {__c1 = __c2;} static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept @@ -699,6 +715,11 @@ typedef u16streampos pos_type; typedef mbstate_t state_type; + // comparison_category is only available in C++20 on. + #if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + using comparison_category = strong_ordering; + #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT @@ -819,6 +840,11 @@ typedef u32streampos pos_type; typedef mbstate_t state_type; + // comparison_category is only available in C++20 on. + #if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + using comparison_category = strong_ordering; + #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR + static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT Index: libcxx/include/compare =================================================================== --- libcxx/include/compare +++ libcxx/include/compare @@ -247,6 +247,8 @@ _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; + #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; @@ -363,6 +365,8 @@ _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; + #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; @@ -489,6 +493,8 @@ _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; + #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; Index: libcxx/include/string_view =================================================================== --- libcxx/include/string_view +++ libcxx/include/string_view @@ -25,19 +25,22 @@ basic_string_view y) noexcept; template constexpr bool operator!=(basic_string_view x, - basic_string_view y) noexcept; + basic_string_view y) noexcept; // C++17 template constexpr bool operator< (basic_string_view x, - basic_string_view y) noexcept; + basic_string_view y) noexcept; // C++17 template - constexpr bool operator> (basic_string_view x, - basic_string_view y) noexcept; + constexpr bool operato> (basic_string_view x, + basic_string_view y) noexcept; // C++17 template constexpr bool operator<=(basic_string_view x, - basic_string_view y) noexcept; + basic_string_view y) noexcept; // C++17 template constexpr bool operator>=(basic_string_view x, - basic_string_view y) noexcept; + basic_string_view y) noexcept; // C++17 + template + constexpr bool operator<=>(basic_string_view x, + basic_string_view y) noexcept; // C++20 // see below, sufficient additional overloads of comparison functions // 7.10, Inserters and extractors @@ -608,6 +611,7 @@ // [string.view.comparison] + // operator == template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY @@ -627,6 +631,38 @@ return __lhs.compare(__rhs) == 0; } +#if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) +template +using __test_for_comparison_category = typename _Tp::comparison_category; + +template +_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +auto operator<=>(basic_string_view<_CharT, _Traits> __lhs, + basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT +{ + const auto result = __lhs.compare(__rhs) <=> 0; + if constexpr (_IsValidExpansion<__test_for_comparison_category, _Traits>::value) { + return static_cast(result); + } + else { + return static_cast(result); + } +} + +template +_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +auto operator<=>(basic_string_view<_CharT, _Traits> __lhs, + typename common_type >::type __rhs) _NOEXCEPT +{ + const auto result = __lhs.compare(__rhs) <=> 0; + if constexpr (_IsValidExpansion<__test_for_comparison_category, _Traits>::value) { + return static_cast(result); + } + else { + return static_cast(result); + } +} +#else template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator==(typename common_type >::type __lhs, @@ -767,6 +803,7 @@ { return __lhs.compare(__rhs) >= 0; } +#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR template Index: libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator<=>(const charT* lhs, basic_string_view rhs); +// template +// constexpr bool operator<=>(basic_string_view lhs, const charT* rhs); + +#include +#include +#include + +#include "test_macros.h" +#include "constexpr_char_traits.h" + +template +void test(const typename S::value_type* lhs, const S& rhs, + std::strong_ordering x, std::strong_ordering y) { + assert((lhs <=> rhs) == x); + assert((rhs <=> lhs) == y); +} + +int main(int, char**) { + { + using std::strong_ordering; + typedef std::string_view S; + test("", S(""), strong_ordering::equal, strong_ordering::equal); + test("", S("abcde"), strong_ordering::less, strong_ordering::greater); + test("", S("abcdefghij"), strong_ordering::less, strong_ordering::greater); + test("", S("abcdefghijklmnopqrst"), strong_ordering::less, + strong_ordering::greater); + test("abcde", S(""), strong_ordering::greater, strong_ordering::less); + test("abcde", S("abcde"), strong_ordering::equal, strong_ordering::equal); + test("abcde", S("abcdefghij"), strong_ordering::less, + strong_ordering::greater); + test("abcde", S("abcdefghijklmnopqrst"), strong_ordering::less, + strong_ordering::greater); + test("abcdefghij", S(""), strong_ordering::greater, strong_ordering::less); + test("abcdefghij", S("abcde"), strong_ordering::greater, + strong_ordering::less); + test("abcdefghij", S("abcdefghij"), strong_ordering::equal, + strong_ordering::equal); + test("abcdefghij", S("abcdefghijklmnopqrst"), strong_ordering::less, + strong_ordering::greater); + test("abcdefghijklmnopqrst", S(""), strong_ordering::greater, + strong_ordering::less); + test("abcdefghijklmnopqrst", S("abcde"), strong_ordering::greater, + strong_ordering::less); + test("abcdefghijklmnopqrst", S("abcdefghij"), strong_ordering::greater, + strong_ordering::less); + test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), + strong_ordering::equal, strong_ordering::equal); + } + + { + typedef std::basic_string_view > SV; + constexpr SV sv1; + constexpr SV sv2{"abcde", 5}; + + static_assert((sv1 <=> "") == std::weak_ordering::equivalent); + static_assert(("" <=> sv1) == std::weak_ordering::equivalent); + static_assert((sv1 <=> "abcde") == std::weak_ordering::less); + static_assert(("abcde" <=> sv1) == std::weak_ordering::greater); + + static_assert((sv2 <=> "") == std::weak_ordering::greater); + static_assert(("" <=> sv2) == std::weak_ordering::less); + static_assert((sv2 <=> "abcde") == std::weak_ordering::equivalent); + static_assert(("abcde" <=> sv2) == std::weak_ordering::equivalent); + static_assert((sv2 <=> "abcde0") == std::weak_ordering::less); + static_assert(("abcde0" <=> sv2) == std::weak_ordering::greater); + } + + return 0; +} Index: libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator<=>(const charT* lhs, basic_string_view rhs); +// template +// constexpr bool operator<=>(basic_string_view lhs, const charT* rhs); + +#include +#include +#include + +#include "test_macros.h" +#include "constexpr_char_traits.h" + +template +void test(const S lhs, const S& rhs, std::strong_ordering x, + std::strong_ordering y) { + assert((lhs <=> rhs) == x); + assert((rhs <=> lhs) == y); +} + +int main(int, char**) { + { + typedef std::string_view S; + test(S(""), S(""), std::strong_ordering::equal, + std::strong_ordering::equal); + test(S(""), S("abcde"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S(""), S("abcdefghij"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S(""), S("abcdefghijklmnopqrst"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S("abcde"), S(""), std::strong_ordering::greater, + std::strong_ordering::less); + test(S("abcde"), S("abcde"), std::strong_ordering::equal, + std::strong_ordering::equal); + test(S("abcde"), S("abcdefghij"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S("abcde"), S("abcdefghijklmnopqrst"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S("abcdefghij"), S(""), std::strong_ordering::greater, + std::strong_ordering::less); + test(S("abcdefghij"), S("abcde"), std::strong_ordering::greater, + std::strong_ordering::less); + test(S("abcdefghij"), S("abcdefghij"), std::strong_ordering::equal, + std::strong_ordering::equal); + test(S("abcdefghij"), S("abcdefghijklmnopqrst"), std::strong_ordering::less, + std::strong_ordering::greater); + test(S("abcdefghijklmnopqrst"), S(""), std::strong_ordering::greater, + std::strong_ordering::less); + test(S("abcdefghijklmnopqrst"), S("abcde"), std::strong_ordering::greater, + std::strong_ordering::less); + test(S("abcdefghijklmnopqrst"), S("abcdefghij"), + std::strong_ordering::greater, std::strong_ordering::less); + test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), + std::strong_ordering::equal, std::strong_ordering::equal); + } + + { + typedef std::basic_string_view > SV; + constexpr SV sv1; + constexpr SV sv2{"abcde", 5}; + + static_assert((sv1 <=> sv2) == std::weak_ordering::less); + static_assert((sv2 <=> sv1) == std::weak_ordering::greater); + + static_assert((sv1 <=> sv1) == std::weak_ordering::equivalent); + static_assert((sv2 <=> sv2) == std::weak_ordering::equivalent); + } + + return 0; +}