diff --git a/libcxx/include/__string b/libcxx/include/__string --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -12,6 +12,7 @@ #include <__config> #include // for search and min +#include // for spaceship support #include // for EOF #include // for memcpy #include // for wmemcpy @@ -315,6 +316,9 @@ typedef streamoff off_type; typedef streampos pos_type; typedef mbstate_t state_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + typedef strong_ordering comparison_category; +#endif static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} @@ -418,6 +422,9 @@ typedef streamoff off_type; typedef streampos pos_type; typedef mbstate_t state_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + typedef strong_ordering comparison_category; +#endif static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} @@ -548,6 +555,9 @@ typedef streamoff off_type; typedef u8streampos pos_type; typedef mbstate_t state_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + typedef strong_ordering comparison_category; +#endif static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept {__c1 = __c2;} @@ -657,6 +667,9 @@ typedef streamoff off_type; typedef u16streampos pos_type; typedef mbstate_t state_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + typedef strong_ordering comparison_category; +#endif static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} @@ -777,6 +790,9 @@ typedef streamoff off_type; typedef u32streampos pos_type; typedef mbstate_t state_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + typedef strong_ordering comparison_category; +#endif static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -28,19 +28,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; + 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 auto 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 @@ -678,6 +681,38 @@ return __lhs.compare(__rhs) == 0; } +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +template +using __test_for_comparison_category = typename _Tp::comparison_category; + +template +constexpr _LIBCPP_INLINE_VISIBILITY +auto operator<=>(const basic_string_view<_CharT, _Traits> __lhs, const 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 +constexpr _LIBCPP_INLINE_VISIBILITY +auto operator<=>(const basic_string_view<_CharT, _Traits> __lhs, + const common_type_t> __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 // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator==(typename common_type >::type __lhs, @@ -819,6 +854,7 @@ return __lhs.compare(__rhs) >= 0; } +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) template basic_ostream<_CharT, _Traits>& diff --git a/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp b/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +constexpr 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); +} + +[[nodiscard]] constexpr bool test_all() { + 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); + return true; +} + +int main(int, char**) { + static_assert(test_all()); + assert(test_all()); + return 0; +} diff --git a/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp b/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 +constexpr void test(const S lhs, const S& rhs, std::strong_ordering x, std::strong_ordering y) { + assert((lhs <=> rhs) == x); + assert((rhs <=> lhs) == y); +} + +[[nodiscard]] constexpr bool test_all() { + 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); + return true; +} + +int main(int, char**) { + static_assert(test_all()); + assert(test_all()); + return 0; +}