diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
| commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
| tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /libcxx/include/string | |
| parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) | |
Notes
Diffstat (limited to 'libcxx/include/string')
| -rw-r--r-- | libcxx/include/string | 498 | 
1 files changed, 313 insertions, 185 deletions
diff --git a/libcxx/include/string b/libcxx/include/string index 8a0ac844470ce..2f846eda06c58 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -437,9 +437,11 @@ basic_istream<charT, traits>&  getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);  template<class charT, class traits, class Allocator, class U> -void erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20 +typename basic_string<charT, traits, Allocator>::size_type +erase(basic_string<charT, traits, Allocator>& c, const U& value);    // C++20  template<class charT, class traits, class Allocator, class Predicate> -void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 +typename basic_string<charT, traits, Allocator>::size_type +erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20  typedef basic_string<char>    string;  typedef basic_string<wchar_t> wstring; @@ -643,9 +645,10 @@ struct __libcpp_string_gets_noexcept_iterator      : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value || __libcpp_string_gets_noexcept_iterator_impl<_Iter>::value) {};  template <class _CharT, class _Traits, class _Tp> -struct __can_be_converted_to_string_view : public _LIBCPP_BOOL_CONSTANT( -    ( is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value && -     !is_convertible<const _Tp&, const _CharT*>::value)) {}; +struct __can_be_converted_to_string_view : public _BoolConstant< +      is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value && +     !is_convertible<const _Tp&, const _CharT*>::value +    > {};  #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT @@ -688,13 +691,8 @@ public:      static_assert(( is_same<typename allocator_type::value_type, value_type>::value),                    "Allocator::value_type must be same type as value_type"); -#if defined(_LIBCPP_RAW_ITERATORS) -    typedef pointer                                      iterator; -    typedef const_pointer                                const_iterator; -#else  // defined(_LIBCPP_RAW_ITERATORS)      typedef __wrap_iter<pointer>                         iterator;      typedef __wrap_iter<const_pointer>                   const_iterator; -#endif  // defined(_LIBCPP_RAW_ITERATORS)      typedef _VSTD::reverse_iterator<iterator>             reverse_iterator;      typedef _VSTD::reverse_iterator<const_iterator>       const_reverse_iterator; @@ -784,6 +782,7 @@ private:      __compressed_pair<__rep, allocator_type> __r_;  public: +    _LIBCPP_FUNC_VIS      static const size_type npos = -1;      _LIBCPP_INLINE_VISIBILITY basic_string() @@ -812,7 +811,7 @@ public:      basic_string(basic_string&& __str, const allocator_type& __a);  #endif  // _LIBCPP_CXX03_LANG -    template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +    template <class = _EnableIf<__is_allocator<_Allocator>::value, nullptr_t> >      _LIBCPP_INLINE_VISIBILITY      basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) {        _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); @@ -822,7 +821,7 @@ public:  #   endif      } -    template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +    template <class = _EnableIf<__is_allocator<_Allocator>::value, nullptr_t> >          _LIBCPP_INLINE_VISIBILITY          basic_string(const _CharT* __s, const _Allocator& __a); @@ -833,7 +832,7 @@ public:      _LIBCPP_INLINE_VISIBILITY      basic_string(size_type __n, _CharT __c); -    template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +    template <class = _EnableIf<__is_allocator<_Allocator>::value, nullptr_t> >          _LIBCPP_INLINE_VISIBILITY          basic_string(size_type __n, _CharT __c, const _Allocator& __a); @@ -843,23 +842,24 @@ public:      basic_string(const basic_string& __str, size_type __pos,                   const _Allocator& __a = _Allocator()); -    template<class _Tp, class = typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type> +    template<class _Tp, class = _EnableIf<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >          _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS          basic_string(const _Tp& __t, size_type __pos, size_type __n, -                              const allocator_type& __a = allocator_type()); +                     const allocator_type& __a = allocator_type()); -    template<class _Tp, class = typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type> +    template<class _Tp, class = _EnableIf<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && +                                          !__is_same_uncvref<_Tp, basic_string>::value> >          _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS          explicit basic_string(const _Tp& __t); -    template<class _Tp, class = typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type> +    template<class _Tp, class = _EnableIf<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >          _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS          explicit basic_string(const _Tp& __t, const allocator_type& __a); -    template<class _InputIterator, class = typename enable_if<__is_cpp17_input_iterator<_InputIterator>::value>::type> +    template<class _InputIterator, class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value> >          _LIBCPP_INLINE_VISIBILITY          basic_string(_InputIterator __first, _InputIterator __last); -    template<class _InputIterator, class = typename enable_if<__is_cpp17_input_iterator<_InputIterator>::value>::type> +    template<class _InputIterator, class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value> >          _LIBCPP_INLINE_VISIBILITY          basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);  #ifndef _LIBCPP_CXX03_LANG @@ -876,7 +876,7 @@ public:      basic_string& operator=(const basic_string& __str); -    template <class _Tp, class = typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type> +    template <class _Tp, class = _EnableIf<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >      basic_string& operator=(const _Tp& __t)          {__self_view __sv = __t; return assign(__sv);} @@ -976,11 +976,12 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +            && !__is_same_uncvref<_Tp, basic_string >::value,              basic_string& -        >::type +        >                                              operator+=(const _Tp& __t)            {__self_view __sv = __t; return append(__sv);}      _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const value_type* __s)     {return append(__s);}      _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(value_type __c)            {push_back(__c); return *this;} @@ -993,21 +994,22 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if -        < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +    _EnableIf< +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +            && !__is_same_uncvref<_Tp, basic_string>::value,              basic_string& -        >::type +        >                    append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); }      basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos);      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +            && !__is_same_uncvref<_Tp, basic_string>::value,              basic_string& -        >::type +        >                    append(const _Tp& __t, size_type __pos, size_type __n=npos);      basic_string& append(const value_type* __s, size_type __n);      basic_string& append(const value_type* __s); @@ -1021,12 +1023,12 @@ public:      basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator);      template<class _InputIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __is_exactly_cpp17_input_iterator<_InputIterator>::value                  || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,              basic_string& -        >::type +        >      _LIBCPP_INLINE_VISIBILITY      append(_InputIterator __first, _InputIterator __last) {        const basic_string __temp (__first, __last, __alloc()); @@ -1035,12 +1037,12 @@ public:      }      template<class _ForwardIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __is_cpp17_forward_iterator<_ForwardIterator>::value                  && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,              basic_string& -        >::type +        >      _LIBCPP_INLINE_VISIBILITY      append(_ForwardIterator __first, _ForwardIterator __last) {        return __append_forward_unsafe(__first, __last); @@ -1061,11 +1063,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              basic_string& -        >::type +        >                   assign(const _Tp & __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); }      _LIBCPP_INLINE_VISIBILITY      basic_string& assign(const basic_string& __str) { return *this = __str; } @@ -1078,32 +1080,33 @@ public:      basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos);      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +            && !__is_same_uncvref<_Tp, basic_string>::value,              basic_string& -        >::type +        >                    assign(const _Tp & __t, size_type __pos, size_type __n=npos);      basic_string& assign(const value_type* __s, size_type __n);      basic_string& assign(const value_type* __s);      basic_string& assign(size_type __n, value_type __c);      template<class _InputIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <             __is_exactly_cpp17_input_iterator<_InputIterator>::value                  || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,              basic_string& -        >::type +        >          assign(_InputIterator __first, _InputIterator __last);      template<class _ForwardIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __is_cpp17_forward_iterator<_ForwardIterator>::value                   && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,              basic_string& -        >::type +        >          assign(_ForwardIterator __first, _ForwardIterator __last);  #ifndef _LIBCPP_CXX03_LANG      _LIBCPP_INLINE_VISIBILITY @@ -1115,21 +1118,21 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              basic_string& -        >::type +        >                   insert(size_type __pos1, const _Tp& __t)      { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); }      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value,              basic_string& -        >::type +        >                    insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n=npos);      basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n=npos);      basic_string& insert(size_type __pos, const value_type* __s, size_type __n); @@ -1140,21 +1143,21 @@ public:      iterator      insert(const_iterator __pos, size_type __n, value_type __c);      template<class _InputIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <             __is_exactly_cpp17_input_iterator<_InputIterator>::value                  || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,              iterator -        >::type +        >          insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);      template<class _ForwardIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __is_cpp17_forward_iterator<_ForwardIterator>::value                   && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,              iterator -        >::type +        >          insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);  #ifndef _LIBCPP_CXX03_LANG      _LIBCPP_INLINE_VISIBILITY @@ -1173,20 +1176,20 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              basic_string& -        >::type +        >                    replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); }      basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos);      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string>::value,              basic_string& -        >::type +        >                    replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos);      basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2);      basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); @@ -1196,11 +1199,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              basic_string& -        >::type +        >                    replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); }      _LIBCPP_INLINE_VISIBILITY @@ -1211,11 +1214,11 @@ public:      basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c);      template<class _InputIterator>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __is_cpp17_input_iterator<_InputIterator>::value,              basic_string& -        >::type +        >          replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2);  #ifndef _LIBCPP_CXX03_LANG      _LIBCPP_INLINE_VISIBILITY @@ -1253,11 +1256,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                find(const _Tp& __t, size_type __pos = 0) const;      size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1269,11 +1272,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                rfind(const _Tp& __t, size_type __pos = npos) const;      size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1285,11 +1288,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                find_first_of(const _Tp& __t, size_type __pos = 0) const;      size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1302,11 +1305,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                find_last_of(const _Tp& __t, size_type __pos = npos) const;      size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1319,11 +1322,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                find_first_not_of(const _Tp &__t, size_type __pos = 0) const;      size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1336,11 +1339,11 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              size_type -        >::type +        >                find_last_not_of(const _Tp& __t, size_type __pos = npos) const;      size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;      _LIBCPP_INLINE_VISIBILITY @@ -1353,20 +1356,20 @@ public:      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              int -        >::type +        >          compare(const _Tp &__t) const;      template <class _Tp>      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -    typename enable_if +    _EnableIf          <              __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,              int -        >::type +        >           compare(size_type __pos1, size_type __n1, const _Tp& __t) const;      _LIBCPP_INLINE_VISIBILITY @@ -1375,11 +1378,11 @@ public:      template <class _Tp>      inline _LIBCPP_INLINE_VISIBILITY -        typename enable_if +        _EnableIf          < -            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +            __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string>::value,              int -        >::type +        >          compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos) const;      int compare(const value_type* __s) const _NOEXCEPT;      int compare(size_type __pos1, size_type __n1, const value_type* __s) const; @@ -1543,22 +1546,30 @@ private:      inline      void __init(size_type __n, value_type __c); +    // Slow path for the (inlined) copy constructor for 'long' strings. +    // Always externally instantiated and not inlined. +    // Requires that __s is zero terminated. +    // The main reason for this function to exist is because for unstable, we +    // want to allow inlining of the copy constructor. However, we don't want +    // to call the __init() functions as those are marked as inline which may +    // result in over-aggressive inlining by the compiler, where our aim is +    // to only inline the fast path code directly in the ctor. +    void __init_copy_ctor_external(const value_type* __s, size_type __sz); +      template <class _InputIterator>      inline -    typename enable_if +    _EnableIf      < -        __is_exactly_cpp17_input_iterator<_InputIterator>::value, -        void -    >::type +        __is_exactly_cpp17_input_iterator<_InputIterator>::value +    >      __init(_InputIterator __first, _InputIterator __last);      template <class _ForwardIterator>      inline -    typename enable_if +    _EnableIf      < -        __is_cpp17_forward_iterator<_ForwardIterator>::value, -        void -    >::type +        __is_cpp17_forward_iterator<_ForwardIterator>::value +    >      __init(_ForwardIterator __first, _ForwardIterator __last);      void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, @@ -1567,9 +1578,19 @@ private:                                 size_type __n_copy,  size_type __n_del,                                 size_type __n_add, const value_type* __p_new_stuff); +    // __assign_no_alias is invoked for assignment operations where we +    // have proof that the input does not alias the current instance. +    // For example, operator=(basic_string) performs a 'self' check. +    template <bool __is_short> +    basic_string& __assign_no_alias(const value_type* __s, size_type __n); +      _LIBCPP_INLINE_VISIBILITY      void __erase_to_end(size_type __pos); +    // __erase_external_with_move is invoked for erase() invocations where +    // `n ~= npos`, likely requiring memory moves on the string data. +    void __erase_external_with_move(size_type __pos, size_type __n); +      _LIBCPP_INLINE_VISIBILITY      void __copy_assign_alloc(const basic_string& __str)          {__copy_assign_alloc(__str, integral_constant<bool, @@ -1638,6 +1659,19 @@ private:          _NOEXCEPT          {} +    basic_string& __assign_external(const value_type* __s); +    basic_string& __assign_external(const value_type* __s, size_type __n); + +    // Assigns the value in __s, guaranteed to be __n < __min_cap in length. +    inline basic_string& __assign_short(const value_type* __s, size_type __n) { +      pointer __p = __is_long() +                        ? (__set_long_size(__n), __get_long_pointer()) +                        : (__set_short_size(__n), __get_short_pointer()); +      traits_type::move(_VSTD::__to_address(__p), __s, __n); +      traits_type::assign(__p[__n], value_type()); +      return *this; +    } +      _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();      _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type); @@ -1648,12 +1682,23 @@ private:      friend basic_string operator+<>(const basic_string&, value_type);  }; +// These declarations must appear before any functions are implicitly used +// so that they have the correct visibility specifier. +#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION +_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE, char) +_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE, wchar_t) +#else +_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE, char) +_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE, wchar_t) +#endif + +  #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES  template<class _InputIterator,           class _CharT = typename iterator_traits<_InputIterator>::value_type,           class _Allocator = allocator<_CharT>, -         class = typename enable_if<__is_cpp17_input_iterator<_InputIterator>::value, void>::type, -         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type +         class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>, +         class = _EnableIf<__is_allocator<_Allocator>::value>           >  basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())    -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; @@ -1661,7 +1706,7 @@ basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())  template<class _CharT,           class _Traits,           class _Allocator = allocator<_CharT>, -         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type +         class = _EnableIf<__is_allocator<_Allocator>::value>           >  explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())    -> basic_string<_CharT, _Traits, _Allocator>; @@ -1669,14 +1714,13 @@ explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _A  template<class _CharT,           class _Traits,           class _Allocator = allocator<_CharT>, -         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type, +         class = _EnableIf<__is_allocator<_Allocator>::value>,           class _Sz = typename allocator_traits<_Allocator>::size_type           >  basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator())    -> basic_string<_CharT, _Traits, _Allocator>;  #endif -  template <class _CharT, class _Traits, class _Allocator>  inline  void @@ -1837,7 +1881,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st      if (!__str.__is_long())          __r_.first().__r = __str.__r_.first().__r;      else -        __init(_VSTD::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); +        __init_copy_ctor_external(_VSTD::__to_address(__str.__get_long_pointer()), +                                  __str.__get_long_size()); +  #if _LIBCPP_DEBUG_LEVEL >= 2      __get_db()->__insert_c(this);  #endif @@ -1851,12 +1897,32 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(      if (!__str.__is_long())          __r_.first().__r = __str.__r_.first().__r;      else -        __init(_VSTD::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); +        __init_copy_ctor_external(_VSTD::__to_address(__str.__get_long_pointer()), +                                  __str.__get_long_size());  #if _LIBCPP_DEBUG_LEVEL >= 2      __get_db()->__insert_c(this);  #endif  } +template <class _CharT, class _Traits, class _Allocator> +void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external( +    const value_type* __s, size_type __sz) { +  pointer __p; +  if (__sz < __min_cap) { +    __p = __get_short_pointer(); +    __set_short_size(__sz); +  } else { +    if (__sz > max_size()) +      this->__throw_length_error(); +    size_t __cap = __recommend(__sz); +    __p = __alloc_traits::allocate(__alloc(), __cap + 1); +    __set_long_pointer(__p); +    __set_long_cap(__cap + 1); +    __set_long_size(__sz); +  } +  traits_type::copy(_VSTD::__to_address(__p), __s, __sz + 1); +} +  #ifndef _LIBCPP_CXX03_LANG  template <class _CharT, class _Traits, class _Allocator> @@ -2014,11 +2080,10 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t, const _  template <class _CharT, class _Traits, class _Allocator>  template <class _InputIterator> -typename enable_if +_EnableIf  < -    __is_exactly_cpp17_input_iterator<_InputIterator>::value, -    void ->::type +    __is_exactly_cpp17_input_iterator<_InputIterator>::value +>  basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last)  {      __zero(); @@ -2041,11 +2106,10 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _Input  template <class _CharT, class _Traits, class _Allocator>  template <class _ForwardIterator> -typename enable_if +_EnableIf  < -    __is_cpp17_forward_iterator<_ForwardIterator>::value, -    void ->::type +    __is_cpp17_forward_iterator<_ForwardIterator>::value +>  basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last)  {      size_type __sz = static_cast<size_type>(_VSTD::distance(__first, __last)); @@ -2198,25 +2262,50 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t  // assign  template <class _CharT, class _Traits, class _Allocator> +template <bool __is_short> +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias( +    const value_type* __s, size_type __n) { +  size_type __cap = __is_short ? __min_cap : __get_long_cap(); +  if (__n < __cap) { +    pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); +    __is_short ? __set_short_size(__n) : __set_long_size(__n); +    traits_type::copy(_VSTD::__to_address(__p), __s, __n); +    traits_type::assign(__p[__n], value_type()); +    __invalidate_iterators_past(__n); +  } else { +    size_type __sz = __is_short ? __get_short_size() : __get_long_size(); +    __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); +  } +  return *this; +} + +template <class _CharT, class _Traits, class _Allocator> +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::__assign_external( +    const value_type* __s, size_type __n) { +  size_type __cap = capacity(); +  if (__cap >= __n) { +    value_type* __p = _VSTD::__to_address(__get_pointer()); +    traits_type::move(__p, __s, __n); +    traits_type::assign(__p[__n], value_type()); +    __set_size(__n); +    __invalidate_iterators_past(__n); +  } else { +    size_type __sz = size(); +    __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); +  } +  return *this; +} + +template <class _CharT, class _Traits, class _Allocator>  basic_string<_CharT, _Traits, _Allocator>&  basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)  {      _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr"); -    size_type __cap = capacity(); -    if (__cap >= __n) -    { -        value_type* __p = _VSTD::__to_address(__get_pointer()); -        traits_type::move(__p, __s, __n); -        traits_type::assign(__p[__n], value_type()); -        __set_size(__n); -        __invalidate_iterators_past(__n); -    } -    else -    { -        size_type __sz = size(); -        __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); -    } -    return *this; +    return (_LIBCPP_BUILTIN_CONSTANT_P(__n) && __n < __min_cap) +               ? __assign_short(__s, __n) +               : __assign_external(__s, __n);  }  template <class _CharT, class _Traits, class _Allocator> @@ -2263,12 +2352,19 @@ template <class _CharT, class _Traits, class _Allocator>  basic_string<_CharT, _Traits, _Allocator>&  basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)  { -    if (this != &__str) -    { -        __copy_assign_alloc(__str); -        return assign(__str.data(), __str.size()); +  if (this != &__str) { +    __copy_assign_alloc(__str); +    if (!__is_long()) { +      if (!__str.__is_long()) { +        __r_.first().__r = __str.__r_.first().__r; +      } else { +        return __assign_no_alias<true>(__str.data(), __str.size()); +      } +    } else { +      return __assign_no_alias<false>(__str.data(), __str.size());      } -    return *this; +  } +  return *this;  }  #ifndef _LIBCPP_CXX03_LANG @@ -2326,12 +2422,12 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str)  template <class _CharT, class _Traits, class _Allocator>  template<class _InputIterator> -typename enable_if +_EnableIf  <       __is_exactly_cpp17_input_iterator <_InputIterator>::value            || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)  {      const basic_string __temp(__first, __last, __alloc()); @@ -2341,12 +2437,12 @@ basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _Input  template <class _CharT, class _Traits, class _Allocator>  template<class _ForwardIterator> -typename enable_if +_EnableIf  <      __is_cpp17_forward_iterator<_ForwardIterator>::value           && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)  {      size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); @@ -2378,11 +2474,12 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, siz  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  < -    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +    && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __pos, size_type __n)  {      __self_view __sv = __t; @@ -2395,12 +2492,21 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __p  template <class _CharT, class _Traits, class _Allocator>  basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { +  return __assign_external(__s, traits_type::length(__s)); +} + +template <class _CharT, class _Traits, class _Allocator> +basic_string<_CharT, _Traits, _Allocator>&  basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s)  {      _LIBCPP_ASSERT(__s != nullptr, "string::assign received nullptr"); -    return assign(__s, traits_type::length(__s)); +    return _LIBCPP_BUILTIN_CONSTANT_P(*__s) +               ? (traits_type::length(__s) < __min_cap +                      ? __assign_short(__s, traits_type::length(__s)) +                      : __assign_external(__s, traits_type::length(__s))) +               : __assign_external(__s);  } -  // append  template <class _CharT, class _Traits, class _Allocator> @@ -2565,11 +2671,11 @@ basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, siz  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -    typename enable_if +    _EnableIf      < -        __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +        __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,          basic_string<_CharT, _Traits, _Allocator>& -    >::type +    >  basic_string<_CharT, _Traits, _Allocator>::append(const _Tp & __t, size_type __pos, size_type __n)  {      __self_view __sv = __t; @@ -2654,12 +2760,12 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n  template <class _CharT, class _Traits, class _Allocator>  template<class _InputIterator> -typename enable_if +_EnableIf  <     __is_exactly_cpp17_input_iterator<_InputIterator>::value          || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,     typename basic_string<_CharT, _Traits, _Allocator>::iterator ->::type +>  basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last)  {  #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -2673,12 +2779,12 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIt  template <class _CharT, class _Traits, class _Allocator>  template<class _ForwardIterator> -typename enable_if +_EnableIf  <      __is_cpp17_forward_iterator<_ForwardIterator>::value          && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,      typename basic_string<_CharT, _Traits, _Allocator>::iterator ->::type +>  basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last)  {  #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -2743,11 +2849,11 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  < -    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t,                                                    size_type __pos2, size_type __n)  { @@ -2852,8 +2958,8 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __          }          traits_type::move(__p + __pos, __s, __n2);  __finish: -// __sz += __n2 - __n1; in this and the below function below can cause unsigned integer overflow, -// but this is a safe operation, so we disable the check. +// __sz += __n2 - __n1; in this and the below function below can cause unsigned +// integer overflow, but this is a safe operation, so we disable the check.          __sz += __n2 - __n1;          __set_size(__sz);          __invalidate_iterators_past(__sz); @@ -2900,11 +3006,11 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __  template <class _CharT, class _Traits, class _Allocator>  template<class _InputIterator> -typename enable_if +_EnableIf  <      __is_cpp17_input_iterator<_InputIterator>::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,                                                     _InputIterator __j1, _InputIterator __j2)  { @@ -2933,11 +3039,11 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type _  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  < -    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,      basic_string<_CharT, _Traits, _Allocator>& ->::type +>  basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const _Tp& __t,                                                     size_type __pos2, size_type __n2)  { @@ -2991,15 +3097,16 @@ basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_it  // erase +// 'externally instantiated' erase() implementation, called when __n != npos. +// Does not check __pos against size()  template <class _CharT, class _Traits, class _Allocator> -basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) +void +basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move( +    size_type __pos, size_type __n)  { -    size_type __sz = size(); -    if (__pos > __sz) -        this->__throw_out_of_range();      if (__n)      { +        size_type __sz = size();          value_type* __p = _VSTD::__to_address(__get_pointer());          __n = _VSTD::min(__n, __sz - __pos);          size_type __n_move = __sz - __pos - __n; @@ -3010,7 +3117,19 @@ basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n)          __invalidate_iterators_past(__sz);          traits_type::assign(__p[__sz], value_type());      } -    return *this; +} + +template <class _CharT, class _Traits, class _Allocator> +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, +                                                 size_type __n) { +  if (__pos > size()) this->__throw_out_of_range(); +  if (__n == npos) { +    __erase_to_end(__pos); +  } else { +    __erase_external_with_move(__pos, __n); +  } +  return *this;  }  template <class _CharT, class _Traits, class _Allocator> @@ -3356,11 +3475,11 @@ basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str,  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t,                                                  size_type __pos) const  { @@ -3414,11 +3533,11 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str,  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t,                                                  size_type __pos) const  { @@ -3472,11 +3591,11 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __s  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t,                                                  size_type __pos) const  { @@ -3530,11 +3649,11 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __st  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t,                                                  size_type __pos) const  { @@ -3588,11 +3707,11 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string&  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t,                                                  size_type __pos) const  { @@ -3647,11 +3766,11 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string&  template<class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      typename basic_string<_CharT, _Traits, _Allocator>::size_type ->::type +>  basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t,                                                  size_type __pos) const  { @@ -3685,11 +3804,11 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c,  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      int ->::type +>  basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const  {      __self_view __sv = __t; @@ -3739,11 +3858,11 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  <      __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,      int ->::type +>  basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,                                                     size_type __n1,                                                     const _Tp& __t) const @@ -3764,11 +3883,12 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,  template <class _CharT, class _Traits, class _Allocator>  template <class _Tp> -typename enable_if +_EnableIf  < -    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, +    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value +    && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,      int ->::type +>  basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,                                                     size_type __n1,                                                     const _Tp& __t, @@ -4230,8 +4350,9 @@ _LIBCPP_FUNC_VIS wstring to_wstring(double __val);  _LIBCPP_FUNC_VIS wstring to_wstring(long double __val);  template<class _CharT, class _Traits, class _Allocator> -    const typename basic_string<_CharT, _Traits, _Allocator>::size_type -                   basic_string<_CharT, _Traits, _Allocator>::npos; +_LIBCPP_FUNC_VIS +const typename basic_string<_CharT, _Traits, _Allocator>::size_type +               basic_string<_CharT, _Traits, _Allocator>::npos;  template <class _CharT, class _Allocator>  struct _LIBCPP_TEMPLATE_VIS @@ -4283,15 +4404,25 @@ getline(basic_istream<_CharT, _Traits>&& __is,  #endif  // _LIBCPP_CXX03_LANG  #if _LIBCPP_STD_VER > 17 -template<class _CharT, class _Traits, class _Allocator, class _Up> +template <class _CharT, class _Traits, class _Allocator, class _Up>  inline _LIBCPP_INLINE_VISIBILITY -void erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) -{ __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end()); } +    typename basic_string<_CharT, _Traits, _Allocator>::size_type +    erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) { +  auto __old_size = __str.size(); +  __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end()); +  return __old_size - __str.size(); +} -template<class _CharT, class _Traits, class _Allocator, class _Predicate> +template <class _CharT, class _Traits, class _Allocator, class _Predicate>  inline _LIBCPP_INLINE_VISIBILITY -void erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) -{ __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred), __str.end()); } +    typename basic_string<_CharT, _Traits, _Allocator>::size_type +    erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, +             _Predicate __pred) { +  auto __old_size = __str.size(); +  __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred), +              __str.end()); +  return __old_size - __str.size(); +}  #endif  #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -4330,9 +4461,6 @@ basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator*  #endif  // _LIBCPP_DEBUG_LEVEL >= 2 -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<char>) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<wchar_t>) -  #if _LIBCPP_STD_VER > 11  // Literal suffixes for basic_string [basic.string.literals]  inline namespace literals  | 
