diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -770,7 +770,7 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator==(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { if ( __lhs.size() != __rhs.size()) return false; return __lhs.compare(__rhs) == 0; @@ -780,7 +780,7 @@ // This overload is automatically generated in C++20. template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator==(typename common_type >::type __lhs, +bool operator==(__type_identity_t > __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT { if ( __lhs.size() != __rhs.size()) return false; @@ -808,7 +808,7 @@ template _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>( - basic_string_view<_CharT, _Traits> __lhs, common_type_t> __rhs) noexcept { + basic_string_view<_CharT, _Traits> __lhs, type_identity_t> __rhs) noexcept { if constexpr (requires { typename _Traits::comparison_category; }) { // [string.view]/4 static_assert( @@ -835,7 +835,7 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator!=(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { if ( __lhs.size() != __rhs.size()) return true; @@ -844,7 +844,7 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator!=(typename common_type >::type __lhs, +bool operator!=(__type_identity_t > __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT { if ( __lhs.size() != __rhs.size()) @@ -864,14 +864,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator<(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator<(typename common_type >::type __lhs, +bool operator<(__type_identity_t > __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; @@ -889,14 +889,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator>(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { return __lhs.compare(__rhs) > 0; } template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator>(typename common_type >::type __lhs, +bool operator>(__type_identity_t > __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT { return __lhs.compare(__rhs) > 0; @@ -914,14 +914,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator<=(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { return __lhs.compare(__rhs) <= 0; } template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator<=(typename common_type >::type __lhs, +bool operator<=(__type_identity_t > __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT { return __lhs.compare(__rhs) <= 0; @@ -940,14 +940,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator>=(basic_string_view<_CharT, _Traits> __lhs, - typename common_type >::type __rhs) _NOEXCEPT + __type_identity_t > __rhs) _NOEXCEPT { return __lhs.compare(__rhs) >= 0; } template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY -bool operator>=(typename common_type >::type __lhs, +bool operator>=(__type_identity_t > __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 --- /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. + +// + +#include + +#include +#include + +#include "test_comparisons.h" +#include "test_macros.h" + +struct char_wrapper { + char c; +}; + +template <> +struct std::char_traits { + 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(a)); + } + + static int compare(const char_wrapper* lhs, const char_wrapper* rhs, std::size_t count) { + return std::char_traits::compare( + reinterpret_cast(lhs), reinterpret_cast(rhs), count); + } +}; + +using WrappedSV = std::basic_string_view >; + +// std::common_type can be specialized and not have a typedef-name member type. +template <> +struct std::common_type {}; + +struct convertible_to_string_view { + WrappedSV sv; + convertible_to_string_view(const char_wrapper* a) : sv(a) {} + operator WrappedSV() const { return sv; } +}; + +template +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(); + + return 0; +}