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; + +#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,10 @@ typedef streampos pos_type; typedef mbstate_t state_type; +#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 +600,10 @@ typedef u8streampos pos_type; typedef mbstate_t state_type; +#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 +713,10 @@ typedef u16streampos pos_type; typedef mbstate_t state_type; +#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 +837,10 @@ typedef u32streampos pos_type; typedef mbstate_t state_type; +#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/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 @@ -627,6 +630,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 +802,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; +}