diff options
Diffstat (limited to 'libcxx/include/__string/char_traits.h')
| -rw-r--r-- | libcxx/include/__string/char_traits.h | 549 | 
1 files changed, 229 insertions, 320 deletions
| diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h index 18ad67b28e16..622ee224f1a0 100644 --- a/libcxx/include/__string/char_traits.h +++ b/libcxx/include/__string/char_traits.h @@ -14,14 +14,16 @@  #include <__algorithm/find_end.h>  #include <__algorithm/find_first_of.h>  #include <__algorithm/min.h> +#include <__compare/ordering.h>  #include <__config>  #include <__functional/hash.h>  #include <__iterator/iterator_traits.h> +#include <__type_traits/is_constant_evaluated.h> +#include <cstddef>  #include <cstdint>  #include <cstdio>  #include <cstring>  #include <iosfwd> -#include <type_traits>  #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS  #   include <cwchar> // for wmemcpy @@ -37,35 +39,124 @@ _LIBCPP_PUSH_MACROS  _LIBCPP_BEGIN_NAMESPACE_STD  template <class _CharT> -struct _LIBCPP_TEMPLATE_VIS char_traits +struct char_traits; +/* +The Standard does not define the base template for char_traits because it is impossible to provide +a correct definition for arbitrary character types. Instead, it requires implementations to provide +specializations for predefined character types like `char`, `wchar_t` and others. We provide this as +exposition-only to document what members a char_traits specialization should provide: +{ +    using char_type  = _CharT; +    using int_type   = ...; +    using off_type   = ...; +    using pos_type   = ...; +    using state_type = ...; + +    static void assign(char_type&, const char_type&); +    static bool eq(char_type, char_type); +    static bool lt(char_type, char_type); + +    static int              compare(const char_type*, const char_type*, size_t); +    static size_t           length(const char_type*); +    static const char_type* find(const char_type*, size_t, const char_type&); +    static char_type*       move(char_type*, const char_type*, size_t); +    static char_type*       copy(char_type*, const char_type*, size_t); +    static char_type*       assign(char_type*, size_t, char_type); + +    static int_type  not_eof(int_type); +    static char_type to_char_type(int_type); +    static int_type  to_int_type(char_type); +    static bool      eq_int_type(int_type, int_type); +    static int_type  eof(); +}; +*/ + +// +// Temporary extension to provide a base template for std::char_traits. +// TODO: Remove in LLVM 18. +// +template <class _CharT> +struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided for a temporary period. It will be removed in LLVM 18, so please migrate off of it.") +    char_traits  { -    typedef _CharT    char_type; -    typedef int       int_type; -    typedef streamoff off_type; -    typedef streampos pos_type; -    typedef mbstate_t state_type; +    using char_type  = _CharT; +    using int_type   = int; +    using off_type   = streamoff; +    using pos_type   = streampos; +    using state_type = mbstate_t; -    static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14 +    static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17          assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}      static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 == __c2;}      static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 < __c2;} -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    int compare(const char_type* __s1, const char_type* __s2, size_t __n); -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    size_t length(const char_type* __s); -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    const char_type* find(const char_type* __s, size_t __n, const char_type& __a); -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 -    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n); +    static _LIBCPP_CONSTEXPR_SINCE_CXX17 +    int compare(const char_type* __s1, const char_type* __s2, size_t __n) { +        for (; __n; --__n, ++__s1, ++__s2) +        { +            if (lt(*__s1, *__s2)) +                return -1; +            if (lt(*__s2, *__s1)) +                return 1; +        } +        return 0; +    } +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 +    size_t length(const char_type* __s) { +        size_t __len = 0; +        for (; !eq(*__s, char_type(0)); ++__s) +            ++__len; +        return __len; +    } +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 +    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { +        for (; __n; --__n) +        { +            if (eq(*__s, __a)) +                return __s; +            ++__s; +        } +        return nullptr; +    } +    static _LIBCPP_CONSTEXPR_SINCE_CXX20 +    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) { +        if (__n == 0) return __s1; +        char_type* __r = __s1; +        if (__s1 < __s2) +        { +            for (; __n; --__n, ++__s1, ++__s2) +                assign(*__s1, *__s2); +        } +        else if (__s2 < __s1) +        { +            __s1 += __n; +            __s2 += __n; +            for (; __n; --__n) +                assign(*--__s1, *--__s2); +        } +        return __r; +    }      _LIBCPP_INLINE_VISIBILITY -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 -    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n); +    static _LIBCPP_CONSTEXPR_SINCE_CXX20 +    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) { +        if (!__libcpp_is_constant_evaluated()) { +            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); +        } +        char_type* __r = __s1; +        for (; __n; --__n, ++__s1, ++__s2) +            assign(*__s1, *__s2); +        return __r; +    }      _LIBCPP_INLINE_VISIBILITY -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 -    char_type*       assign(char_type* __s, size_t __n, char_type __a); +    static _LIBCPP_CONSTEXPR_SINCE_CXX20 +    char_type*       assign(char_type* __s, size_t __n, char_type __a) { +        char_type* __r = __s; +        for (; __n; --__n, ++__s) +            assign(*__s, __a); +        return __r; +    }      static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT          {return eq_int_type(__c, eof()) ? ~eof() : __c;} @@ -80,92 +171,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits  };  template <class _CharT> -_LIBCPP_CONSTEXPR_AFTER_CXX14 int -char_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n) -{ -    for (; __n; --__n, ++__s1, ++__s2) -    { -        if (lt(*__s1, *__s2)) -            return -1; -        if (lt(*__s2, *__s1)) -            return 1; -    } -    return 0; -} - -template <class _CharT> -inline -_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t -char_traits<_CharT>::length(const char_type* __s) -{ -    size_t __len = 0; -    for (; !eq(*__s, char_type(0)); ++__s) -        ++__len; -    return __len; -} - -template <class _CharT> -inline -_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT* -char_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a) -{ -    for (; __n; --__n) -    { -        if (eq(*__s, __a)) -            return __s; -        ++__s; -    } -    return nullptr; -} - -template <class _CharT> -_LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT* -char_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n) -{ -    if (__n == 0) return __s1; -    char_type* __r = __s1; -    if (__s1 < __s2) -    { -        for (; __n; --__n, ++__s1, ++__s2) -            assign(*__s1, *__s2); -    } -    else if (__s2 < __s1) -    { -        __s1 += __n; -        __s2 += __n; -        for (; __n; --__n) -            assign(*--__s1, *--__s2); -    } -    return __r; -} - -template <class _CharT> -inline _LIBCPP_CONSTEXPR_AFTER_CXX17 -_CharT* -char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n) -{ -    if (!__libcpp_is_constant_evaluated()) { -        _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); -    } -    char_type* __r = __s1; -    for (; __n; --__n, ++__s1, ++__s2) -        assign(*__s1, *__s2); -    return __r; -} - -template <class _CharT> -inline _LIBCPP_CONSTEXPR_AFTER_CXX17 -_CharT* -char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a) -{ -    char_type* __r = __s; -    for (; __n; --__n, ++__s) -        assign(*__s, __a); -    return __r; -} - -template <class _CharT> -static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +_LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20  _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT  {  #ifdef _LIBCPP_COMPILER_GCC @@ -188,45 +194,45 @@ _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _  template <>  struct _LIBCPP_TEMPLATE_VIS char_traits<char>  { -    typedef char      char_type; -    typedef int       int_type; -    typedef streamoff off_type; -    typedef streampos pos_type; -    typedef mbstate_t state_type; +    using char_type           = char; +    using int_type            = int; +    using off_type            = streamoff; +    using pos_type            = streampos; +    using state_type          = mbstate_t; +#if _LIBCPP_STD_VER > 17 +    using comparison_category = strong_ordering; +#endif -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX17      void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}      static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT              {return __c1 == __c2;}      static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT          {return (unsigned char)__c1 < (unsigned char)__c2;} -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; +  static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { +    if (__n == 0) +      return 0; +    return std::__constexpr_memcmp(__s1, __s2, __n); +  } -    static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14 length(const char_type* __s)  _NOEXCEPT { -      // GCC currently does not support __builtin_strlen during constant evaluation. -      // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 -#ifdef _LIBCPP_COMPILER_GCC -      if (__libcpp_is_constant_evaluated()) { -        size_t __i = 0; -        for (; __s[__i] != char_type('\0'); ++__i) -            ; -        return __i; -      } -#endif -      return __builtin_strlen(__s); -    } +  static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s)  _NOEXCEPT { +    return std::__constexpr_strlen(__s); +  } -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; +  static _LIBCPP_CONSTEXPR_SINCE_CXX17 +  const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { +    if (__n == 0) +        return nullptr; +    return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n); +  } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          return std::__char_traits_move(__s1, __s2, __n);      } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          if (!__libcpp_is_constant_evaluated())              _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); @@ -234,7 +240,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>          return __s1;      } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {          std::fill_n(__s, __n, __a);          return __s; @@ -252,82 +258,51 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>          {return int_type(EOF);}  }; -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 -int -char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ -    if (__n == 0) -        return 0; -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_memcmp(__s1, __s2, __n); -#elif _LIBCPP_STD_VER <= 14 -    return _VSTD::memcmp(__s1, __s2, __n); -#else -    for (; __n; --__n, ++__s1, ++__s2) -    { -        if (lt(*__s1, *__s2)) -            return -1; -        if (lt(*__s2, *__s1)) -            return 1; -    } -    return 0; -#endif -} - -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 -const char* -char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT -{ -    if (__n == 0) -        return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_char_memchr(__s, to_int_type(__a), __n); -#elif _LIBCPP_STD_VER <= 14 -    return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n); -#else -    for (; __n; --__n) -    { -        if (eq(*__s, __a)) -            return __s; -        ++__s; -    } -    return nullptr; -#endif -} - -  // char_traits<wchar_t>  #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS  template <>  struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>  { -    typedef wchar_t   char_type; -    typedef wint_t    int_type; -    typedef streamoff off_type; -    typedef streampos pos_type; -    typedef mbstate_t state_type; +    using char_type           = wchar_t; +    using int_type            = wint_t; +    using off_type            = streamoff; +    using pos_type            = streampos; +    using state_type          = mbstate_t; +#if _LIBCPP_STD_VER > 17 +    using comparison_category = strong_ordering; +#endif -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX17      void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}      static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 == __c2;}      static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 < __c2;} -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    size_t length(const char_type* __s) _NOEXCEPT; -    static _LIBCPP_CONSTEXPR_AFTER_CXX14 -    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; +  static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { +    if (__n == 0) +        return 0; +    return std::__constexpr_wmemcmp(__s1, __s2, __n); +  } + +  static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT { +    return std::__constexpr_wcslen(__s); +  } + +  static _LIBCPP_CONSTEXPR_SINCE_CXX17 +  const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { +    if (__n == 0) +        return nullptr; +    return std::__constexpr_wmemchr(__s, __a, __n); +  } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          return std::__char_traits_move(__s1, __s2, __n);      } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          if (!__libcpp_is_constant_evaluated())              _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); @@ -335,7 +310,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>          return __s1;      } -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {          std::fill_n(__s, __n, __a);          return __s; @@ -352,65 +327,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>      static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT          {return int_type(WEOF);}  }; - -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 -int -char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ -    if (__n == 0) -        return 0; -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_wmemcmp(__s1, __s2, __n); -#elif _LIBCPP_STD_VER <= 14 -    return _VSTD::wmemcmp(__s1, __s2, __n); -#else -    for (; __n; --__n, ++__s1, ++__s2) -    { -        if (lt(*__s1, *__s2)) -            return -1; -        if (lt(*__s2, *__s1)) -            return 1; -    } -    return 0; -#endif -} - -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 -size_t -char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT -{ -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_wcslen(__s); -#elif _LIBCPP_STD_VER <= 14 -    return _VSTD::wcslen(__s); -#else -    size_t __len = 0; -    for (; !eq(*__s, char_type(0)); ++__s) -        ++__len; -    return __len; -#endif -} - -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 -const wchar_t* -char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT -{ -    if (__n == 0) -        return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_wmemchr(__s, __a, __n); -#elif _LIBCPP_STD_VER <= 14 -    return _VSTD::wmemchr(__s, __a, __n); -#else -    for (; __n; --__n) -    { -        if (eq(*__s, __a)) -            return __s; -        ++__s; -    } -    return nullptr; -#endif -}  #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS  #ifndef _LIBCPP_HAS_NO_CHAR8_T @@ -418,11 +334,14 @@ char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __  template <>  struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>  { -    typedef char8_t        char_type; -    typedef unsigned int   int_type; -    typedef streamoff      off_type; -    typedef u8streampos    pos_type; -    typedef mbstate_t      state_type; +    using char_type           = char8_t; +    using int_type            = unsigned int; +    using off_type            = streamoff; +    using pos_type            = u8streampos; +    using state_type          = mbstate_t; +#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;} @@ -431,8 +350,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>      static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept          {return __c1 < __c2;} -    static constexpr -    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; +  static _LIBCPP_HIDE_FROM_ABI constexpr int +  compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { +      return std::__constexpr_memcmp(__s1, __s2, __n); +  }      static constexpr      size_t           length(const char_type* __s) _NOEXCEPT; @@ -440,12 +361,12 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>      _LIBCPP_INLINE_VISIBILITY static constexpr      const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          return std::__char_traits_move(__s1, __s2, __n);      } -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          if (!__libcpp_is_constant_evaluated())              _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); @@ -453,7 +374,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>          return __s1;      } -    static _LIBCPP_CONSTEXPR_AFTER_CXX17 +    static _LIBCPP_CONSTEXPR_SINCE_CXX20      char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {          std::fill_n(__s, __n, __a);          return __s; @@ -482,24 +403,6 @@ char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT      return __len;  } -inline constexpr -int -char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ -#if __has_feature(cxx_constexpr_string_builtins) -    return __builtin_memcmp(__s1, __s2, __n); -#else -    for (; __n; --__n, ++__s1, ++__s2) -    { -        if (lt(*__s1, *__s2)) -            return -1; -        if (lt(*__s2, *__s1)) -            return 1; -    } -    return 0; -#endif -} -  // TODO use '__builtin_char_memchr' if it ever supports char8_t ??  inline constexpr  const char8_t* @@ -519,32 +422,35 @@ char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __  template <>  struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>  { -    typedef char16_t       char_type; -    typedef uint_least16_t int_type; -    typedef streamoff      off_type; -    typedef u16streampos   pos_type; -    typedef mbstate_t      state_type; +    using char_type           = char16_t; +    using int_type            = uint_least16_t; +    using off_type            = streamoff; +    using pos_type            = u16streampos; +    using state_type          = mbstate_t; +#if _LIBCPP_STD_VER > 17 +    using comparison_category = strong_ordering; +#endif -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX17      void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}      static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 == __c2;}      static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 < __c2;} -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      size_t           length(const char_type* __s) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          return std::__char_traits_move(__s1, __s2, __n);      } -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          if (!__libcpp_is_constant_evaluated())              _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); @@ -552,7 +458,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>          return __s1;      } -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {          std::fill_n(__s, __n, __a);          return __s; @@ -570,7 +476,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>          {return int_type(0xFFFF);}  }; -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  int  char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT  { @@ -584,7 +490,7 @@ char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, siz      return 0;  } -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  size_t  char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT  { @@ -594,7 +500,7 @@ char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT      return __len;  } -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  const char16_t*  char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT  { @@ -610,38 +516,41 @@ char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& _  template <>  struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>  { -    typedef char32_t       char_type; -    typedef uint_least32_t int_type; -    typedef streamoff      off_type; -    typedef u32streampos   pos_type; -    typedef mbstate_t      state_type; +    using char_type           = char32_t; +    using int_type            = uint_least32_t; +    using off_type            = streamoff; +    using pos_type            = u32streampos; +    using state_type          = mbstate_t; +#if _LIBCPP_STD_VER > 17 +    using comparison_category = strong_ordering; +#endif -    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +    static inline _LIBCPP_CONSTEXPR_SINCE_CXX17      void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}      static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 == __c2;}      static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT          {return __c1 < __c2;} -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      size_t           length(const char_type* __s) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 +    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17      const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          return std::__char_traits_move(__s1, __s2, __n);      } -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {          std::copy_n(__s2, __n, __s1);          return __s1;      } -    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20      static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {          std::fill_n(__s, __n, __a);          return __s; @@ -659,7 +568,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>          {return int_type(0xFFFFFFFF);}  }; -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  int  char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT  { @@ -673,7 +582,7 @@ char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, siz      return 0;  } -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  size_t  char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT  { @@ -683,7 +592,7 @@ char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT      return __len;  } -inline _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_CONSTEXPR_SINCE_CXX17  const char32_t*  char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT  { @@ -700,7 +609,7 @@ char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& _  // __str_find  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find(const _CharT *__p, _SizeT __sz,               _CharT __c, _SizeT __pos) _NOEXCEPT  { @@ -713,7 +622,7 @@ __str_find(const _CharT *__p, _SizeT __sz,  }  template <class _CharT, class _Traits> -inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT * +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT *  __search_substring(const _CharT *__first1, const _CharT *__last1,                     const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {    // Take advantage of knowing source and pattern lengths. @@ -752,7 +661,7 @@ __search_substring(const _CharT *__first1, const _CharT *__last1,  }  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find(const _CharT *__p, _SizeT __sz,         const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT  { @@ -762,7 +671,7 @@ __str_find(const _CharT *__p, _SizeT __sz,      if (__n == 0) // There is nothing to search, just return __pos.          return __pos; -    const _CharT *__r = __search_substring<_CharT, _Traits>( +    const _CharT *__r = std::__search_substring<_CharT, _Traits>(          __p + __pos, __p + __sz, __s, __s + __n);      if (__r == __p + __sz) @@ -774,7 +683,7 @@ __str_find(const _CharT *__p, _SizeT __sz,  // __str_rfind  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_rfind(const _CharT *__p, _SizeT __sz,                _CharT __c, _SizeT __pos) _NOEXCEPT  { @@ -793,7 +702,7 @@ __str_rfind(const _CharT *__p, _SizeT __sz,  }  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_rfind(const _CharT *__p, _SizeT __sz,          const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT  { @@ -810,7 +719,7 @@ __str_rfind(const _CharT *__p, _SizeT __sz,  // __str_find_first_of  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_first_of(const _CharT *__p, _SizeT __sz,                  const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT  { @@ -826,7 +735,7 @@ __str_find_first_of(const _CharT *__p, _SizeT __sz,  // __str_find_last_of  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_last_of(const _CharT *__p, _SizeT __sz,                 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT      { @@ -849,7 +758,7 @@ __str_find_last_of(const _CharT *__p, _SizeT __sz,  // __str_find_first_not_of  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_first_not_of(const _CharT *__p, _SizeT __sz,                      const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT  { @@ -865,7 +774,7 @@ __str_find_first_not_of(const _CharT *__p, _SizeT __sz,  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_first_not_of(const _CharT *__p, _SizeT __sz,                            _CharT __c, _SizeT __pos) _NOEXCEPT  { @@ -882,7 +791,7 @@ __str_find_first_not_of(const _CharT *__p, _SizeT __sz,  // __str_find_last_not_of  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_last_not_of(const _CharT *__p, _SizeT __sz,                     const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT  { @@ -898,7 +807,7 @@ __str_find_last_not_of(const _CharT *__p, _SizeT __sz,  template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> -inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY  __str_find_last_not_of(const _CharT *__p, _SizeT __sz,                           _CharT __c, _SizeT __pos) _NOEXCEPT  { | 
