[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
This commit is contained in:
Mark de Wever 2022-08-06 14:27:46 +02:00
parent 486594119d
commit 70074cf397
2 changed files with 86 additions and 13 deletions

View File

@ -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;

View File

@ -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;
}