[libcxx-commits] [libcxx] 22b5adf - [libc++] Uses operator<=> in string.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 14 05:05:11 PDT 2022


Author: Mark de Wever
Date: 2022-08-14T14:05:05+02:00
New Revision: 22b5adff7189f3ca547f38d5e87a7fa9dda9c509

URL: https://github.com/llvm/llvm-project/commit/22b5adff7189f3ca547f38d5e87a7fa9dda9c509
DIFF: https://github.com/llvm/llvm-project/commit/22b5adff7189f3ca547f38d5e87a7fa9dda9c509.diff

LOG: [libc++] Uses operator<=> in string.

Implements part of:
- P1614R2 The Mothership has Landed

Reviewed By: avogelsgesang, #libc, philnik

Differential Revision: https://reviews.llvm.org/D131421

Added: 
    libcxx/test/std/strings/basic.string/string.nonmembers/string.cmp/comparison.pass.cpp

Modified: 
    libcxx/docs/Status/SpaceshipProjects.csv
    libcxx/include/string

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 5a8efbd9e21c8..efb38b3e662ff 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -33,7 +33,7 @@ Section,Description,Dependencies,Assignee,Complete
 | `[charconv.syn] <https://wg21.link/charconv.syn>`_,| from_chars_result,None,Mark de Wever,|Complete|
 | `[stacktrace.entry.cmp] <https://wg21.link/stacktrace.entry.cmp>`_,| stacktrace_entry,None,Unassigned,|Not Started|
 | `[stacktrace.basic.cmp] <https://wg21.link/stacktrace.basic.cmp>`_,| basic_stacktrace,[alg.three.way],Unassigned,|Not Started|
-| `[string.cmp] <https://wg21.link/string.cmp>`_,| basic_string,None,Mark de Wever,|In Progress|
+| `[string.cmp] <https://wg21.link/string.cmp>`_,| `basic_string <https://reviews.llvm.org/D131421>`,None,Mark de Wever,|Complete|
 | `[string.view.comparison] <https://wg21.link/string.view.comparison>`_,| `basic_string_view <https://reviews.llvm.org/D130295>`_,None,Mark de Wever,|Complete|
 | `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.requirements.general#14>`_),| array,[expos.only.func],Unassigned,|Not Started|
 | `[deque.syn] <https://wg21.link/deque.syn>`_ (`general <https://wg21.link/container.requirements.general#14>`_),| deque,[expos.only.func],Unassigned,|Not Started|

diff  --git a/libcxx/include/string b/libcxx/include/string
index c3a213091ef11..bae6884347e03 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -13,6 +13,9 @@
 /*
     string synopsis
 
+#include <compare>
+#include <initializer_list>
+
 namespace std
 {
 
@@ -43,11 +46,13 @@ template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT
 template <class charT>
 struct char_traits
 {
-    typedef charT     char_type;
-    typedef ...       int_type;
-    typedef streamoff off_type;
-    typedef streampos pos_type;
-    typedef mbstate_t state_type;
+    using char_type           = charT;
+    using int_type            = ...;
+    using off_type            = streamoff;
+    using pos_type            = streampos;
+    using state_type          = mbstate_t;
+    using comparison_category = strong_ordering; // Since C++20 only for the specializations
+                                                 // char, wchar_t, char8_t, char16_t, and char32_t.
 
     static void assign(char_type& c1, const char_type& c2) noexcept;
     static constexpr bool eq(char_type c1, char_type c2) noexcept;
@@ -370,60 +375,68 @@ bool operator==(const basic_string<charT, traits, Allocator>& lhs,
                 const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
 bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept;    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator!=(const basic_string<charT,traits,Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
+bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
 bool operator< (const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
+bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
 bool operator> (const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
+bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
 bool operator<=(const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
+bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
 bool operator>=(const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
+bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20, removed in C++20
 
 template<class charT, class traits, class Allocator>
-bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
+bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20, removed in C++20
+
+template<class charT, class traits, class Allocator>                                            // since C++20
+constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+                                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+
+template<class charT, class traits, class Allocator>                                            // since C++20
+constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+                                const charT* rhs) noexcept;
 
 template<class charT, class traits, class Allocator>
 void swap(basic_string<charT, traits, Allocator>& lhs,
@@ -4149,10 +4162,14 @@ bool
 operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
 {
+#if _LIBCPP_STD_VER > 17
+    return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs);
+#else
     size_t __lhs_sz = __lhs.size();
     return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(),
                                                         __rhs.data(),
                                                         __lhs_sz) == 0;
+#endif
 }
 
 template<class _Allocator>
@@ -4174,6 +4191,7 @@ operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs,
     return true;
 }
 
+#if _LIBCPP_STD_VER <= 17
 template<class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
 bool
@@ -4186,6 +4204,7 @@ operator==(const _CharT* __lhs,
     if (__lhs_len != __rhs.size()) return false;
     return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0;
 }
+#endif // _LIBCPP_STD_VER <= 17
 
 template<class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
@@ -4193,13 +4212,34 @@ bool
 operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
 {
+#if _LIBCPP_STD_VER > 17
+    return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs);
+#else
     typedef basic_string<_CharT, _Traits, _Allocator> _String;
     _LIBCPP_ASSERT(__rhs != nullptr, "operator==(basic_string, char*): received nullptr");
     size_t __rhs_len = _Traits::length(__rhs);
     if (__rhs_len != __lhs.size()) return false;
     return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0;
+#endif
 }
 
+#if _LIBCPP_STD_VER > 17
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(
+    const basic_string<_CharT, _Traits, _Allocator>& __lhs,
+    const basic_string<_CharT, _Traits, _Allocator>& __rhs) noexcept {
+    return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs);
+}
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr auto
+operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) {
+    return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs);
+}
+
+#else // _LIBCPP_STD_VER > 17
+
 template<class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
 bool
@@ -4342,6 +4382,7 @@ operator>=(const _CharT* __lhs,
 {
     return !(__lhs < __rhs);
 }
+#endif // _LIBCPP_STD_VER > 17
 
 // operator +
 

diff  --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.cmp/comparison.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.cmp/comparison.pass.cpp
new file mode 100644
index 0000000000000..d9f71bd31e62a
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.cmp/comparison.pass.cpp
@@ -0,0 +1,101 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Starting with C++20 the spaceship operator was included. This tests
+// comparison in that context, thus doesn't support older language versions.
+// These are tested per operator.
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <string>
+
+// template<class charT, class traits, class Allocator>
+//   see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+//                         const basic_string<charT, traits, Allocator>& rhs) noexcept;
+// template<class charT, class traits, class Allocator>
+//   see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+//                         const charT* rhs);
+
+#include <string>
+
+#include <array>
+#include <cassert>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "test_comparisons.h"
+#include "test_macros.h"
+
+#define STR(S) MAKE_STRING(CharT, S)
+
+template <class T, class Ordering = std::strong_ordering>
+constexpr void test() {
+  AssertOrderAreNoexcept<T>();
+  AssertOrderReturn<Ordering, T>();
+
+  using CharT = typename T::value_type;
+  AssertOrderReturn<Ordering, T, const CharT*>();
+
+  // sorted values
+  std::array v{
+      STR(""),
+      STR("abc"),
+      STR("abcdef"),
+      STR("acb"),
+  };
+
+  // sorted values with embedded NUL character
+  std::array vn{
+      STR("abc"),
+      STR("abc\0"),
+      STR("abc\0def"),
+      STR("acb\0"),
+  };
+  static_assert(v.size() == vn.size());
+
+  for (size_t i = 0; i < v.size(); ++i) {
+    for (size_t j = 0; j < v.size(); ++j) {
+      assert(testOrder(v[i], v[j], i == j ? Ordering::equivalent : i < j ? Ordering::less : Ordering::greater));
+
+      assert(testOrder(
+          v[i],
+          std::basic_string<CharT>{v[j]}.c_str(),
+          i == j  ? Ordering::equivalent
+          : i < j ? Ordering::less
+                  : Ordering::greater));
+
+      // NUL test omitted for c-strings since it will fail.
+      assert(testOrder(vn[i], vn[j], i == j ? Ordering::equivalent : i < j ? Ordering::less : Ordering::greater));
+    }
+  }
+}
+
+constexpr bool test_all_types() {
+  test<std::string>();
+  test<std::basic_string<char, constexpr_char_traits<char>>, std::weak_ordering>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<std::wstring>();
+  test<std::basic_string<wchar_t, constexpr_char_traits<wchar_t>>, std::weak_ordering>();
+#endif
+  test<std::u8string>();
+  test<std::basic_string<char8_t, constexpr_char_traits<char8_t>>, std::weak_ordering>();
+  test<std::u16string>();
+  test<std::basic_string<char16_t, constexpr_char_traits<char16_t>>, std::weak_ordering>();
+  test<std::u32string>();
+  test<std::basic_string<char32_t, constexpr_char_traits<char32_t>>, std::weak_ordering>();
+
+  return true;
+}
+
+int main(int, char**) {
+  test_all_types();
+  static_assert(test_all_types());
+
+  return 0;
+}


        


More information about the libcxx-commits mailing list