Skip to content

Commit

Permalink
[libc++] Uses operator<=> in string_view
Browse files Browse the repository at this point in the history
Implements:
- LWG3432 Missing requirement for comparison_category

Implements part of:
- P1614R2 The Mothership has Landed

Reviewed By: #libc, ldionne, jloser, philnik

Differential Revision: https://reviews.llvm.org/D130295
  • Loading branch information
mordante committed Aug 4, 2022
1 parent 5659908 commit 3818b4d
Show file tree
Hide file tree
Showing 14 changed files with 355 additions and 20 deletions.
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2bIssues.csv
Expand Up @@ -7,7 +7,7 @@
"`3236 <https://wg21.link/LWG3236>`__","Random access iterator requirements lack limiting relational operators domain to comparing those from the same range","November 2020","|Nothing To Do|","","|ranges|"
"`3265 <https://wg21.link/LWG3265>`__","``move_iterator``'s conversions are more broken after P1207","November 2020","Fixed by `LWG3435 <https://wg21.link/LWG3435>`__",""
"`3435 <https://wg21.link/LWG3435>`__","``three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>``","November 2020","|Complete|","13.0"
"`3432 <https://wg21.link/LWG3432>`__","Missing requirement for ``comparison_category``","November 2020","","","|spaceship|"
"`3432 <https://wg21.link/LWG3432>`__","Missing requirement for ``comparison_category``","November 2020","|Complete|","16.0","|spaceship|"
"`3447 <https://wg21.link/LWG3447>`__","Deduction guides for ``take_view`` and ``drop_view`` have different constraints","November 2020","|Complete|","14.0"
"`3450 <https://wg21.link/LWG3450>`__","The const overloads of ``take_while_view::begin/end`` are underconstrained","November 2020","","","|ranges|"
"`3464 <https://wg21.link/LWG3464>`__","``istream::gcount()`` can overflow","November 2020","",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/SpaceshipProjects.csv
Expand Up @@ -33,7 +33,7 @@ Section,Description,Dependencies,Assignee,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.view.comparison] <https://wg21.link/string.view.comparison>`_,| `basic_string_view <https://reviews.llvm.org/D130295>`_,None,Mark de Wever,|In Progress|
| `[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|
| `[forward.list.syn] <https://wg21.link/forward.list.syn>`_ (`general <https://wg21.link/container.requirements.general#14>`_),| forward_list,[expos.only.func],Unassigned,|Not Started|
Expand Down
6 changes: 6 additions & 0 deletions libcxx/include/__compare/ordering.h
Expand Up @@ -312,6 +312,12 @@ inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);
inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);
inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);

/// [cmp.categories.pre]/1
/// The types partial_ordering, weak_ordering, and strong_ordering are
/// collectively termed the comparison category types.
template <class _Tp>
concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>;

#endif // _LIBCPP_STD_VER > 17

_LIBCPP_END_NAMESPACE_STD
Expand Down
16 changes: 16 additions & 0 deletions libcxx/include/__string/char_traits.h
Expand Up @@ -17,6 +17,7 @@
#include <__config>
#include <__functional/hash.h>
#include <__iterator/iterator_traits.h>
#include <compare>
#include <cstdint>
#include <cstdio>
#include <cstring>
Expand Down Expand Up @@ -193,6 +194,9 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
#if _LIBCPP_STD_VER > 17
using comparison_category = strong_ordering;
#endif

static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Expand Down Expand Up @@ -307,6 +311,9 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
# if _LIBCPP_STD_VER > 17
using comparison_category = strong_ordering;
# endif

static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Expand Down Expand Up @@ -423,6 +430,9 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
typedef streamoff off_type;
typedef u8streampos pos_type;
typedef mbstate_t state_type;
# if _LIBCPP_STD_VER > 17
using comparison_category = strong_ordering;
# endif

static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
{__c1 = __c2;}
Expand Down Expand Up @@ -524,6 +534,9 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
typedef streamoff off_type;
typedef u16streampos pos_type;
typedef mbstate_t state_type;
#if _LIBCPP_STD_VER > 17
using comparison_category = strong_ordering;
#endif

static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Expand Down Expand Up @@ -615,6 +628,9 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
typedef streamoff off_type;
typedef u32streampos pos_type;
typedef mbstate_t state_type;
#if _LIBCPP_STD_VER > 17
using comparison_category = strong_ordering;
#endif

static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Expand Down
53 changes: 48 additions & 5 deletions libcxx/include/string_view
Expand Up @@ -14,6 +14,8 @@
string_view synopsis
#include <compare>
namespace std {
// 7.2, Class template basic_string_view
Expand All @@ -30,21 +32,25 @@ namespace std {
template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits>
template<class charT, class traits> // Removed in C++20
constexpr bool operator!=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits>
template<class charT, class traits> // Removed in C++20
constexpr bool operator< (basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits>
template<class charT, class traits> // Removed in C++20
constexpr bool operator> (basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits>
template<class charT, class traits> // Removed in C++20
constexpr bool operator<=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits>
template<class charT, class traits> // Removed in C++20
constexpr bool operator>=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
template<class charT, class traits> // Since C++20
constexpr see below operator<=>(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
// see below, sufficient additional overloads of comparison functions
// 7.10, Inserters and extractors
Expand Down Expand Up @@ -770,6 +776,8 @@ bool operator==(basic_string_view<_CharT, _Traits> __lhs,
return __lhs.compare(__rhs) == 0;
}

#if _LIBCPP_STD_VER < 20
// 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,
Expand All @@ -778,7 +786,41 @@ bool operator==(typename common_type<basic_string_view<_CharT, _Traits> >::type
if ( __lhs.size() != __rhs.size()) return false;
return __lhs.compare(__rhs) == 0;
}
#endif // _LIBCPP_STD_VER > 17

// operator <=>

#if _LIBCPP_STD_VER > 17

template <class _CharT, class _Traits>
_LIBCPP_HIDE_FROM_ABI constexpr auto
operator<=>(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) noexcept {
if constexpr (requires { typename _Traits::comparison_category; }) {
// [string.view]/4
static_assert(
__comparison_category<typename _Traits::comparison_category>,
"return type is not a comparison category type");
return static_cast<typename _Traits::comparison_category>(__lhs.compare(__rhs) <=> 0);
} else {
return static_cast<weak_ordering>(__lhs.compare(__rhs) <=> 0);
}
}

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 {
if constexpr (requires { typename _Traits::comparison_category; }) {
// [string.view]/4
static_assert(
__comparison_category<typename _Traits::comparison_category>,
"return type is not a comparison category type");
return static_cast<typename _Traits::comparison_category>(__lhs.compare(__rhs) <=> 0);
} else {
return static_cast<weak_ordering>(__lhs.compare(__rhs) <=> 0);
}
}

#else // _LIBCPP_STD_VER > 17

// operator !=
template<class _CharT, class _Traits>
Expand Down Expand Up @@ -911,6 +953,7 @@ bool operator>=(typename common_type<basic_string_view<_CharT, _Traits> >::type
return __lhs.compare(__rhs) >= 0;
}

#endif // _LIBCPP_STD_VER > 17

template<class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
Expand Down
Expand Up @@ -15,6 +15,7 @@
// typedef streamoff off_type;
// typedef streampos pos_type;
// typedef mbstate_t state_type;
// using comparison_category = strong_ordering;

#include <string>
#include <type_traits>
Expand All @@ -28,6 +29,9 @@ int main(int, char**)
static_assert((std::is_same<std::char_traits<char>::off_type, std::streamoff>::value), "");
static_assert((std::is_same<std::char_traits<char>::pos_type, std::streampos>::value), "");
static_assert((std::is_same<std::char_traits<char>::state_type, std::mbstate_t>::value), "");
#if TEST_STD_VER > 17
static_assert(std::is_same_v<std::char_traits<char>::comparison_category, std::strong_ordering>);
#endif

return 0;
}
Expand Up @@ -15,6 +15,7 @@
// typedef streamoff off_type;
// typedef u16streampos pos_type;
// typedef mbstate_t state_type;
// using comparison_category = strong_ordering;

#include <string>
#include <type_traits>
Expand All @@ -29,6 +30,9 @@ int main(int, char**)
static_assert((std::is_same<std::char_traits<char16_t>::off_type, std::streamoff>::value), "");
static_assert((std::is_same<std::char_traits<char16_t>::pos_type, std::u16streampos>::value), "");
static_assert((std::is_same<std::char_traits<char16_t>::state_type, std::mbstate_t>::value), "");
#if TEST_STD_VER > 17
static_assert(std::is_same_v<std::char_traits<char16_t>::comparison_category, std::strong_ordering>);
#endif

return 0;
}
Expand Up @@ -15,13 +15,19 @@
// typedef streamoff off_type;
// typedef u32streampos pos_type;
// typedef mbstate_t state_type;
// using comparison_category = strong_ordering;

#include <string>
#include <type_traits>
#include <cstdint>

#include "test_macros.h"

static_assert((std::is_same<std::char_traits<char32_t>::char_type, char32_t>::value), "");
static_assert((std::is_same<std::char_traits<char32_t>::int_type, std::uint_least32_t>::value), "");
static_assert((std::is_same<std::char_traits<char32_t>::off_type, std::streamoff>::value), "");
static_assert((std::is_same<std::char_traits<char32_t>::pos_type, std::u32streampos>::value), "");
static_assert((std::is_same<std::char_traits<char32_t>::state_type, std::mbstate_t>::value), "");
#if TEST_STD_VER > 17
static_assert(std::is_same_v<std::char_traits<char32_t>::comparison_category, std::strong_ordering>);
#endif
Expand Up @@ -16,6 +16,7 @@
// typedef streamoff off_type;
// typedef u8streampos pos_type;
// typedef mbstate_t state_type;
// using comparison_category = strong_ordering;

#include <string>
#include <type_traits>
Expand All @@ -31,6 +32,7 @@ int main(int, char**)
static_assert((std::is_same<std::char_traits<char8_t>::off_type, std::streamoff>::value), "");
static_assert((std::is_same<std::char_traits<char8_t>::pos_type, std::u8streampos>::value), "");
static_assert((std::is_same<std::char_traits<char8_t>::state_type, std::mbstate_t>::value), "");
static_assert(std::is_same_v<std::char_traits<char8_t>::comparison_category, std::strong_ordering>);
#endif

return 0;
Expand Down
Expand Up @@ -15,6 +15,7 @@
// typedef streamoff off_type;
// typedef streampos pos_type;
// typedef mbstate_t state_type;
// using comparison_category = strong_ordering;

// UNSUPPORTED: no-wide-characters

Expand All @@ -30,6 +31,9 @@ int main(int, char**)
static_assert((std::is_same<std::char_traits<wchar_t>::off_type, std::streamoff>::value), "");
static_assert((std::is_same<std::char_traits<wchar_t>::pos_type, std::wstreampos>::value), "");
static_assert((std::is_same<std::char_traits<wchar_t>::state_type, std::mbstate_t>::value), "");
#if TEST_STD_VER > 17
static_assert(std::is_same_v<std::char_traits<wchar_t>::comparison_category, std::strong_ordering>);
#endif

return 0;
}

0 comments on commit 3818b4d

Please sign in to comment.