[libcxx-commits] [libcxx] 70074cf - [libc++] Fixes string_view comparison operators.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 10 10:38:55 PDT 2022


Author: Mark de Wever
Date: 2022-08-10T19:38:50+02:00
New Revision: 70074cf3972bc3b3828ee21880aa45fb0b8a56e0

URL: https://github.com/llvm/llvm-project/commit/70074cf3972bc3b3828ee21880aa45fb0b8a56e0
DIFF: https://github.com/llvm/llvm-project/commit/70074cf3972bc3b3828ee21880aa45fb0b8a56e0.diff

LOG: [libc++] Fixes string_view comparison operators.

While implementing `operator<=>` for `string_view` (D130295) @philnik
pointed out `common_type` should be `type_identity`. Since it was an
existing issue that wasn't addressed.

This addresses the issue for both the new and existing equality and
comparison operators. The test is based on the example posted in
D130295.

Reviewed By: philnik, #libc, huixie90

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

Added: 
    libcxx/test/std/strings/string.view/string.view.comparison/common_type_specialization.pass.cpp

Modified: 
    libcxx/include/string_view

Removed: 
    


################################################################################
diff  --git a/libcxx/include/string_view b/libcxx/include/string_view
index 9e954fd649fee..83ad1a367fe25 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -770,7 +770,7 @@ bool operator==(basic_string_view<_CharT, _Traits> __lhs,
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator==(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     if ( __lhs.size() != __rhs.size()) return false;
     return __lhs.compare(__rhs) == 0;
@@ -780,7 +780,7 @@ bool operator==(basic_string_view<_CharT, _Traits> __lhs,
 // This overload is automatically generated in C++20.
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator==(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator==(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     if ( __lhs.size() != __rhs.size()) return false;
@@ -808,7 +808,7 @@ operator<=>(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT,
 
 template <class _CharT, class _Traits, int = 1>
 _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(
-    basic_string_view<_CharT, _Traits> __lhs, common_type_t<basic_string_view<_CharT, _Traits>> __rhs) noexcept {
+    basic_string_view<_CharT, _Traits> __lhs, type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) noexcept {
     if constexpr (requires { typename _Traits::comparison_category; }) {
         // [string.view]/4
         static_assert(
@@ -835,7 +835,7 @@ bool operator!=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_Cha
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator!=(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     if ( __lhs.size() != __rhs.size())
         return true;
@@ -844,7 +844,7 @@ bool operator!=(basic_string_view<_CharT, _Traits> __lhs,
 
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator!=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator!=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     if ( __lhs.size() != __rhs.size())
@@ -864,14 +864,14 @@ bool operator<(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_Char
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator<(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) < 0;
 }
 
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator<(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator<(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) < 0;
@@ -889,14 +889,14 @@ bool operator> (basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_Cha
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator>(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) > 0;
 }
 
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator>(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator>(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) > 0;
@@ -914,14 +914,14 @@ bool operator<=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_Cha
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator<=(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) <= 0;
 }
 
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator<=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator<=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) <= 0;
@@ -940,14 +940,14 @@ bool operator>=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_Cha
 template<class _CharT, class _Traits, int = 1>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
 bool operator>=(basic_string_view<_CharT, _Traits> __lhs,
-                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+                __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) >= 0;
 }
 
 template<class _CharT, class _Traits, int = 2>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
-bool operator>=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs,
+bool operator>=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
 {
     return __lhs.compare(__rhs) >= 0;

diff  --git a/libcxx/test/std/strings/string.view/string.view.comparison/common_type_specialization.pass.cpp b/libcxx/test/std/strings/string.view/string.view.comparison/common_type_specialization.pass.cpp
new file mode 100644
index 0000000000000..248ef567bfa7f
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.comparison/common_type_specialization.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: !stdlib=libc++ && (c++03 || c++11 || c++14)
+
+// During the review D130295 it was noticed libc++'s implementation uses
+// std::common_type. When users specialize this template for their own types the
+// comparisions would fail. This tests with a specialized std::common_type.
+
+// <string_view>
+
+#include <string_view>
+
+#include <cassert>
+#include <cstring>
+
+#include "test_comparisons.h"
+#include "test_macros.h"
+
+struct char_wrapper {
+  char c;
+};
+
+template <>
+struct std::char_traits<char_wrapper> {
+  using char_type = char_wrapper;
+
+  static bool eq(char_wrapper lhs, char_wrapper rhs) { return lhs.c == rhs.c; }
+
+  static size_t length(const char_wrapper* a) {
+    static_assert(sizeof(char_wrapper) == 1, "strlen requires this");
+    return std::strlen(reinterpret_cast<const char*>(a));
+  }
+
+  static int compare(const char_wrapper* lhs, const char_wrapper* rhs, std::size_t count) {
+    return std::char_traits<char>::compare(
+        reinterpret_cast<const char*>(lhs), reinterpret_cast<const char*>(rhs), count);
+  }
+};
+
+using WrappedSV = std::basic_string_view<char_wrapper, std::char_traits<char_wrapper> >;
+
+// std::common_type can be specialized and not have a typedef-name member type.
+template <>
+struct std::common_type<WrappedSV, WrappedSV> {};
+
+struct convertible_to_string_view {
+  WrappedSV sv;
+  convertible_to_string_view(const char_wrapper* a) : sv(a) {}
+  operator WrappedSV() const { return sv; }
+};
+
+template <class T, class U>
+void test() {
+  char_wrapper a[] = {{'a'}, {'b'}, {'c'}, {'\0'}};
+
+  assert((testComparisons(T(a), U(a), true, false)));
+
+#if TEST_STD_VER > 17
+  assert((testOrder(T(a), U(a), std::weak_ordering::equivalent)));
+#endif
+}
+
+int main(int, char**) {
+  test<WrappedSV, convertible_to_string_view>();
+
+  return 0;
+}


        


More information about the libcxx-commits mailing list