xref: /freebsd/contrib/llvm-project/libcxx/include/string (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_STRING
11#define _LIBCPP_STRING
12
13// clang-format off
14
15/*
16    string synopsis
17
18#include <compare>
19#include <initializer_list>
20
21namespace std
22{
23
24template <class stateT>
25class fpos
26{
27private:
28    stateT st;
29public:
30    fpos(streamoff = streamoff());
31
32    operator streamoff() const;
33
34    stateT state() const;
35    void state(stateT);
36
37    fpos& operator+=(streamoff);
38    fpos  operator+ (streamoff) const;
39    fpos& operator-=(streamoff);
40    fpos  operator- (streamoff) const;
41};
42
43template <class stateT> streamoff operator-(const fpos<stateT>& x, const fpos<stateT>& y);
44
45template <class stateT> bool operator==(const fpos<stateT>& x, const fpos<stateT>& y);
46template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT>& y);
47
48template <class charT>
49struct char_traits
50{
51    using char_type           = charT;
52    using int_type            = ...;
53    using off_type            = streamoff;
54    using pos_type            = streampos;
55    using state_type          = mbstate_t;
56    using comparison_category = strong_ordering; // Since C++20 only for the specializations
57                                                 // char, wchar_t, char8_t, char16_t, and char32_t.
58
59    static void assign(char_type& c1, const char_type& c2) noexcept;
60    static constexpr bool eq(char_type c1, char_type c2) noexcept;
61    static constexpr bool lt(char_type c1, char_type c2) noexcept;
62
63    static int              compare(const char_type* s1, const char_type* s2, size_t n);
64    static size_t           length(const char_type* s);
65    static const char_type* find(const char_type* s, size_t n, const char_type& a);
66    static char_type*       move(char_type* s1, const char_type* s2, size_t n);
67    static char_type*       copy(char_type* s1, const char_type* s2, size_t n);
68    static char_type*       assign(char_type* s, size_t n, char_type a);
69
70    static constexpr int_type  not_eof(int_type c) noexcept;
71    static constexpr char_type to_char_type(int_type c) noexcept;
72    static constexpr int_type  to_int_type(char_type c) noexcept;
73    static constexpr bool      eq_int_type(int_type c1, int_type c2) noexcept;
74    static constexpr int_type  eof() noexcept;
75};
76
77template <> struct char_traits<char>;
78template <> struct char_traits<wchar_t>;
79template <> struct char_traits<char8_t>;  // C++20
80template <> struct char_traits<char16_t>;
81template <> struct char_traits<char32_t>;
82
83template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
84class basic_string
85{
86public:
87// types:
88    typedef traits traits_type;
89    typedef typename traits_type::char_type value_type;
90    typedef Allocator allocator_type;
91    typedef typename allocator_type::size_type size_type;
92    typedef typename allocator_type::difference_type difference_type;
93    typedef typename allocator_type::reference reference;
94    typedef typename allocator_type::const_reference const_reference;
95    typedef typename allocator_type::pointer pointer;
96    typedef typename allocator_type::const_pointer const_pointer;
97    typedef implementation-defined iterator;
98    typedef implementation-defined const_iterator;
99    typedef std::reverse_iterator<iterator> reverse_iterator;
100    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
101
102    static const size_type npos = -1;
103
104    basic_string()
105        noexcept(is_nothrow_default_constructible<allocator_type>::value);                      // constexpr since C++20
106    explicit basic_string(const allocator_type& a);                                             // constexpr since C++20
107    basic_string(const basic_string& str);                                                      // constexpr since C++20
108    basic_string(basic_string&& str)
109        noexcept(is_nothrow_move_constructible<allocator_type>::value);                         // constexpr since C++20
110    basic_string(const basic_string& str, size_type pos,
111                 const allocator_type& a = allocator_type());                                   // constexpr since C++20
112    basic_string(const basic_string& str, size_type pos, size_type n,
113                 const Allocator& a = Allocator());                                             // constexpr since C++20
114    constexpr basic_string(
115        basic_string&& str, size_type pos, const Allocator& a = Allocator());                   // since C++23
116    constexpr basic_string(
117        basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator());      // since C++23
118    template<class T>
119        basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20
120    template <class T>
121        explicit basic_string(const T& t, const Allocator& a = Allocator());                    // C++17, constexpr since C++20
122    basic_string(const value_type* s, const allocator_type& a = allocator_type());              // constexpr since C++20
123    basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20
124    basic_string(nullptr_t) = delete; // C++23
125    basic_string(size_type n, value_type c, const allocator_type& a = allocator_type());        // constexpr since C++20
126    template<class InputIterator>
127        basic_string(InputIterator begin, InputIterator end,
128                     const allocator_type& a = allocator_type());                               // constexpr since C++20
129    template<container-compatible-range<charT> R>
130      constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator());           // since C++23
131    basic_string(initializer_list<value_type>, const Allocator& = Allocator());                 // constexpr since C++20
132    basic_string(const basic_string&, const Allocator&);                                        // constexpr since C++20
133    basic_string(basic_string&&, const Allocator&);                                             // constexpr since C++20
134
135    ~basic_string();                                                                            // constexpr since C++20
136
137    operator basic_string_view<charT, traits>() const noexcept;                                 // constexpr since C++20
138
139    basic_string& operator=(const basic_string& str);                                           // constexpr since C++20
140    template <class T>
141        basic_string& operator=(const T& t);                                                    // C++17, constexpr since C++20
142    basic_string& operator=(basic_string&& str)
143        noexcept(
144             allocator_type::propagate_on_container_move_assignment::value ||
145             allocator_type::is_always_equal::value );                                          // C++17, constexpr since C++20
146    basic_string& operator=(const value_type* s);                                               // constexpr since C++20
147    basic_string& operator=(nullptr_t) = delete; // C++23
148    basic_string& operator=(value_type c);                                                      // constexpr since C++20
149    basic_string& operator=(initializer_list<value_type>);                                      // constexpr since C++20
150
151    iterator       begin() noexcept;                                                            // constexpr since C++20
152    const_iterator begin() const noexcept;                                                      // constexpr since C++20
153    iterator       end() noexcept;                                                              // constexpr since C++20
154    const_iterator end() const noexcept;                                                        // constexpr since C++20
155
156    reverse_iterator       rbegin() noexcept;                                                   // constexpr since C++20
157    const_reverse_iterator rbegin() const noexcept;                                             // constexpr since C++20
158    reverse_iterator       rend() noexcept;                                                     // constexpr since C++20
159    const_reverse_iterator rend() const noexcept;                                               // constexpr since C++20
160
161    const_iterator         cbegin() const noexcept;                                             // constexpr since C++20
162    const_iterator         cend() const noexcept;                                               // constexpr since C++20
163    const_reverse_iterator crbegin() const noexcept;                                            // constexpr since C++20
164    const_reverse_iterator crend() const noexcept;                                              // constexpr since C++20
165
166    size_type size() const noexcept;                                                            // constexpr since C++20
167    size_type length() const noexcept;                                                          // constexpr since C++20
168    size_type max_size() const noexcept;                                                        // constexpr since C++20
169    size_type capacity() const noexcept;                                                        // constexpr since C++20
170
171    void resize(size_type n, value_type c);                                                     // constexpr since C++20
172    void resize(size_type n);                                                                   // constexpr since C++20
173
174    template<class Operation>
175    constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23
176
177    void reserve(size_type res_arg);                                                            // constexpr since C++20
178    void reserve();                                                                             // deprecated in C++20, removed in C++26
179    void shrink_to_fit();                                                                       // constexpr since C++20
180    void clear() noexcept;                                                                      // constexpr since C++20
181    bool empty() const noexcept;                                                                // constexpr since C++20
182
183    const_reference operator[](size_type pos) const;                                            // constexpr since C++20
184    reference       operator[](size_type pos);                                                  // constexpr since C++20
185
186    const_reference at(size_type n) const;                                                      // constexpr since C++20
187    reference       at(size_type n);                                                            // constexpr since C++20
188
189    basic_string& operator+=(const basic_string& str);                                          // constexpr since C++20
190    template <class T>
191        basic_string& operator+=(const T& t);                                                   // C++17, constexpr since C++20
192    basic_string& operator+=(const value_type* s);                                              // constexpr since C++20
193    basic_string& operator+=(value_type c);                                                     // constexpr since C++20
194    basic_string& operator+=(initializer_list<value_type>);                                     // constexpr since C++20
195
196    basic_string& append(const basic_string& str);                                              // constexpr since C++20
197    template <class T>
198        basic_string& append(const T& t);                                                       // C++17, constexpr since C++20
199    basic_string& append(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
200    template <class T>
201        basic_string& append(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
202    basic_string& append(const value_type* s, size_type n);                                     // constexpr since C++20
203    basic_string& append(const value_type* s);                                                  // constexpr since C++20
204    basic_string& append(size_type n, value_type c);                                            // constexpr since C++20
205    template<class InputIterator>
206        basic_string& append(InputIterator first, InputIterator last);                          // constexpr since C++20
207    template<container-compatible-range<charT> R>
208      constexpr basic_string& append_range(R&& rg);                                             // C++23
209    basic_string& append(initializer_list<value_type>);                                         // constexpr since C++20
210
211    void push_back(value_type c);                                                               // constexpr since C++20
212    void pop_back();                                                                            // constexpr since C++20
213    reference       front();                                                                    // constexpr since C++20
214    const_reference front() const;                                                              // constexpr since C++20
215    reference       back();                                                                     // constexpr since C++20
216    const_reference back() const;                                                               // constexpr since C++20
217
218    basic_string& assign(const basic_string& str);                                              // constexpr since C++20
219    template <class T>
220        basic_string& assign(const T& t);                                                       // C++17, constexpr since C++20
221    basic_string& assign(basic_string&& str);                                                   // constexpr since C++20
222    basic_string& assign(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
223    template <class T>
224        basic_string& assign(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
225    basic_string& assign(const value_type* s, size_type n);                                     // constexpr since C++20
226    basic_string& assign(const value_type* s);                                                  // constexpr since C++20
227    basic_string& assign(size_type n, value_type c);                                            // constexpr since C++20
228    template<class InputIterator>
229        basic_string& assign(InputIterator first, InputIterator last);                          // constexpr since C++20
230    template<container-compatible-range<charT> R>
231      constexpr basic_string& assign_range(R&& rg);                                             // C++23
232    basic_string& assign(initializer_list<value_type>);                                         // constexpr since C++20
233
234    basic_string& insert(size_type pos1, const basic_string& str);                              // constexpr since C++20
235    template <class T>
236        basic_string& insert(size_type pos1, const T& t);                                       // constexpr since C++20
237    basic_string& insert(size_type pos1, const basic_string& str,
238                         size_type pos2, size_type n);                                          // constexpr since C++20
239    template <class T>
240        basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n);          // C++17, constexpr since C++20
241    basic_string& insert(size_type pos, const value_type* s, size_type n=npos);                 // C++14, constexpr since C++20
242    basic_string& insert(size_type pos, const value_type* s);                                   // constexpr since C++20
243    basic_string& insert(size_type pos, size_type n, value_type c);                             // constexpr since C++20
244    iterator      insert(const_iterator p, value_type c);                                       // constexpr since C++20
245    iterator      insert(const_iterator p, size_type n, value_type c);                          // constexpr since C++20
246    template<class InputIterator>
247        iterator insert(const_iterator p, InputIterator first, InputIterator last);             // constexpr since C++20
248    template<container-compatible-range<charT> R>
249      constexpr iterator insert_range(const_iterator p, R&& rg);                                // C++23
250    iterator      insert(const_iterator p, initializer_list<value_type>);                       // constexpr since C++20
251
252    basic_string& erase(size_type pos = 0, size_type n = npos);                                 // constexpr since C++20
253    iterator      erase(const_iterator position);                                               // constexpr since C++20
254    iterator      erase(const_iterator first, const_iterator last);                             // constexpr since C++20
255
256    basic_string& replace(size_type pos1, size_type n1, const basic_string& str);               // constexpr since C++20
257    template <class T>
258    basic_string& replace(size_type pos1, size_type n1, const T& t);                            // C++17, constexpr since C++20
259    basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
260                          size_type pos2, size_type n2=npos);                                   // C++14, constexpr since C++20
261    template <class T>
262        basic_string& replace(size_type pos1, size_type n1, const T& t,
263                              size_type pos2, size_type n);                                     // C++17, constexpr since C++20
264    basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2);      // constexpr since C++20
265    basic_string& replace(size_type pos, size_type n1, const value_type* s);                    // constexpr since C++20
266    basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c);             // constexpr since C++20
267    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);       // constexpr since C++20
268    template <class T>
269        basic_string& replace(const_iterator i1, const_iterator i2, const T& t);                // C++17, constexpr since C++20
270    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20
271    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s);           // constexpr since C++20
272    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c);     // constexpr since C++20
273    template<class InputIterator>
274        basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20
275    template<container-compatible-range<charT> R>
276      constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23
277    basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>);  // constexpr since C++20
278
279    size_type copy(value_type* s, size_type n, size_type pos = 0) const;                        // constexpr since C++20
280    basic_string substr(size_type pos = 0, size_type n = npos) const;                           // constexpr in C++20, removed in C++23
281    basic_string substr(size_type pos = 0, size_type n = npos) const&;                          // since C++23
282    constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;                    // since C++23
283    void swap(basic_string& str)
284        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
285                 allocator_traits<allocator_type>::is_always_equal::value);                     // C++17, constexpr since C++20
286
287    const value_type* c_str() const noexcept;                                                   // constexpr since C++20
288    const value_type* data() const noexcept;                                                    // constexpr since C++20
289          value_type* data()       noexcept;                                                    // C++17, constexpr since C++20
290
291    allocator_type get_allocator() const noexcept;                                              // constexpr since C++20
292
293    size_type find(const basic_string& str, size_type pos = 0) const noexcept;                  // constexpr since C++20
294    template <class T>
295        size_type find(const T& t, size_type pos = 0) const noexcept;                           // C++17, noexcept as an extension, constexpr since C++20
296    size_type find(const value_type* s, size_type pos, size_type n) const noexcept;             // constexpr since C++20
297    size_type find(const value_type* s, size_type pos = 0) const noexcept;                      // constexpr since C++20
298    size_type find(value_type c, size_type pos = 0) const noexcept;                             // constexpr since C++20
299
300    size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;              // constexpr since C++20
301    template <class T>
302        size_type rfind(const T& t, size_type pos = npos) const noexcept;                       // C++17, noexcept as an extension, constexpr since C++20
303    size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept;            // constexpr since C++20
304    size_type rfind(const value_type* s, size_type pos = npos) const noexcept;                  // constexpr since C++20
305    size_type rfind(value_type c, size_type pos = npos) const noexcept;                         // constexpr since C++20
306
307    size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;         // constexpr since C++20
308    template <class T>
309        size_type find_first_of(const T& t, size_type pos = 0) const noexcept;                  // C++17, noexcept as an extension, constexpr since C++20
310    size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept;    // constexpr since C++20
311    size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept;             // constexpr since C++20
312    size_type find_first_of(value_type c, size_type pos = 0) const noexcept;                    // constexpr since C++20
313
314    size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept;       // constexpr since C++20
315    template <class T>
316        size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept;       // C++17, noexcept as an extension, constexpr since C++20
317    size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept;     // constexpr since C++20
318    size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept;           // constexpr since C++20
319    size_type find_last_of(value_type c, size_type pos = npos) const noexcept;                  // constexpr since C++20
320
321    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;     // constexpr since C++20
322    template <class T>
323        size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept;              // C++17, noexcept as an extension, constexpr since C++20
324    size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
325    size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept;         // constexpr since C++20
326    size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept;                // constexpr since C++20
327
328    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept;   // constexpr since C++20
329    template <class T>
330        size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept;            // C++17, noexcept as an extension, constexpr since C++20
331    size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
332    size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept;       // constexpr since C++20
333    size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept;              // constexpr since C++20
334
335    int compare(const basic_string& str) const noexcept;                                        // constexpr since C++20
336    template <class T>
337        int compare(const T& t) const noexcept;                                                 // C++17, noexcept as an extension, constexpr since C++20
338    int compare(size_type pos1, size_type n1, const basic_string& str) const;                   // constexpr since C++20
339    template <class T>
340        int compare(size_type pos1, size_type n1, const T& t) const;                            // C++17, constexpr since C++20
341    int compare(size_type pos1, size_type n1, const basic_string& str,
342                size_type pos2, size_type n2=npos) const;                                       // C++14, constexpr since C++20
343    template <class T>
344        int compare(size_type pos1, size_type n1, const T& t,
345                    size_type pos2, size_type n2=npos) const;                                   // C++17, constexpr since C++20
346    int compare(const value_type* s) const noexcept;                                            // constexpr since C++20
347    int compare(size_type pos1, size_type n1, const value_type* s) const;                       // constexpr since C++20
348    int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const;         // constexpr since C++20
349
350    constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept;             // C++20
351    constexpr bool starts_with(charT c) const noexcept;                                         // C++20
352    constexpr bool starts_with(const charT* s) const;                                           // C++20
353    constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept;               // C++20
354    constexpr bool ends_with(charT c) const noexcept;                                           // C++20
355    constexpr bool ends_with(const charT* s) const;                                             // C++20
356
357    constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept;                // C++23
358    constexpr bool contains(charT c) const noexcept;                                            // C++23
359    constexpr bool contains(const charT* s) const;                                              // C++23
360};
361
362template<class InputIterator,
363         class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
364basic_string(InputIterator, InputIterator, Allocator = Allocator())
365   -> basic_string<typename iterator_traits<InputIterator>::value_type,
366                  char_traits<typename iterator_traits<InputIterator>::value_type>,
367                  Allocator>;   // C++17
368
369template<ranges::input_range R,
370         class Allocator = allocator<ranges::range_value_t<R>>>
371  basic_string(from_range_t, R&&, Allocator = Allocator())
372    -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>,
373                    Allocator>; // C++23
374
375template<class charT,
376         class traits,
377         class Allocator = allocator<charT>>
378  explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator())
379    -> basic_string<charT, traits, Allocator>; // C++17
380
381template<class charT,
382         class traits,
383         class Allocator = allocator<charT>>
384  basic_string(basic_string_view<charT, traits>,
385                typename see below::size_type, typename see below::size_type,
386                const Allocator& = Allocator())
387    -> basic_string<charT, traits, Allocator>; // C++17
388
389template<class charT, class traits, class Allocator>
390basic_string<charT, traits, Allocator>
391operator+(const basic_string<charT, traits, Allocator>& lhs,
392          const basic_string<charT, traits, Allocator>& rhs);                                   // constexpr since C++20
393
394template<class charT, class traits, class Allocator>
395basic_string<charT, traits, Allocator>
396operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs);                   // constexpr since C++20
397
398template<class charT, class traits, class Allocator>
399basic_string<charT, traits, Allocator>
400operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs);                          // constexpr since C++20
401
402template<class charT, class traits, class Allocator>
403basic_string<charT, traits, Allocator>
404operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);                 // constexpr since C++20
405
406template<class charT, class traits, class Allocator>
407basic_string<charT, traits, Allocator>
408operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);                        // constexpr since C++20
409
410template<class charT, class traits, class Allocator>
411bool operator==(const basic_string<charT, traits, Allocator>& lhs,
412                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
413
414template<class charT, class traits, class Allocator>
415bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
416
417template<class charT, class traits, class Allocator>
418bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept;    // constexpr since C++20
419
420template<class charT, class traits, class Allocator>
421bool operator!=(const basic_string<charT,traits,Allocator>& lhs,
422                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // removed in C++20
423
424template<class charT, class traits, class Allocator>
425bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
426
427template<class charT, class traits, class Allocator>
428bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // removed in C++20
429
430template<class charT, class traits, class Allocator>
431bool operator< (const basic_string<charT, traits, Allocator>& lhs,
432                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // removed in C++20
433
434template<class charT, class traits, class Allocator>
435bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // removed in C++20
436
437template<class charT, class traits, class Allocator>
438bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
439
440template<class charT, class traits, class Allocator>
441bool operator> (const basic_string<charT, traits, Allocator>& lhs,
442                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // removed in C++20
443
444template<class charT, class traits, class Allocator>
445bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // removed in C++20
446
447template<class charT, class traits, class Allocator>
448bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
449
450template<class charT, class traits, class Allocator>
451bool operator<=(const basic_string<charT, traits, Allocator>& lhs,
452                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // removed in C++20
453
454template<class charT, class traits, class Allocator>
455bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // removed in C++20
456
457template<class charT, class traits, class Allocator>
458bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
459
460template<class charT, class traits, class Allocator>
461bool operator>=(const basic_string<charT, traits, Allocator>& lhs,
462                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // removed in C++20
463
464template<class charT, class traits, class Allocator>
465bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // removed in C++20
466
467template<class charT, class traits, class Allocator>
468bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // removed in C++20
469
470template<class charT, class traits, class Allocator>                                            // since C++20
471constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
472                                const basic_string<charT, traits, Allocator>& rhs) noexcept;
473
474template<class charT, class traits, class Allocator>                                            // since C++20
475constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
476                                const charT* rhs) noexcept;
477
478template<class charT, class traits, class Allocator>
479void swap(basic_string<charT, traits, Allocator>& lhs,
480          basic_string<charT, traits, Allocator>& rhs)
481            noexcept(noexcept(lhs.swap(rhs)));                                                  // constexpr since C++20
482
483template<class charT, class traits, class Allocator>
484basic_istream<charT, traits>&
485operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
486
487template<class charT, class traits, class Allocator>
488basic_ostream<charT, traits>&
489operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
490
491template<class charT, class traits, class Allocator>
492basic_istream<charT, traits>&
493getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str,
494        charT delim);
495
496template<class charT, class traits, class Allocator>
497basic_istream<charT, traits>&
498getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
499
500template<class charT, class traits, class Allocator, class U>
501typename basic_string<charT, traits, Allocator>::size_type
502erase(basic_string<charT, traits, Allocator>& c, const U& value);    // C++20
503template<class charT, class traits, class Allocator, class Predicate>
504typename basic_string<charT, traits, Allocator>::size_type
505erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20
506
507typedef basic_string<char>    string;
508typedef basic_string<wchar_t> wstring;
509typedef basic_string<char8_t> u8string; // C++20
510typedef basic_string<char16_t> u16string;
511typedef basic_string<char32_t> u32string;
512
513int                stoi  (const string& str, size_t* idx = nullptr, int base = 10);
514long               stol  (const string& str, size_t* idx = nullptr, int base = 10);
515unsigned long      stoul (const string& str, size_t* idx = nullptr, int base = 10);
516long long          stoll (const string& str, size_t* idx = nullptr, int base = 10);
517unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10);
518
519float       stof (const string& str, size_t* idx = nullptr);
520double      stod (const string& str, size_t* idx = nullptr);
521long double stold(const string& str, size_t* idx = nullptr);
522
523string to_string(int val);
524string to_string(unsigned val);
525string to_string(long val);
526string to_string(unsigned long val);
527string to_string(long long val);
528string to_string(unsigned long long val);
529string to_string(float val);
530string to_string(double val);
531string to_string(long double val);
532
533int                stoi  (const wstring& str, size_t* idx = nullptr, int base = 10);
534long               stol  (const wstring& str, size_t* idx = nullptr, int base = 10);
535unsigned long      stoul (const wstring& str, size_t* idx = nullptr, int base = 10);
536long long          stoll (const wstring& str, size_t* idx = nullptr, int base = 10);
537unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10);
538
539float       stof (const wstring& str, size_t* idx = nullptr);
540double      stod (const wstring& str, size_t* idx = nullptr);
541long double stold(const wstring& str, size_t* idx = nullptr);
542
543wstring to_wstring(int val);
544wstring to_wstring(unsigned val);
545wstring to_wstring(long val);
546wstring to_wstring(unsigned long val);
547wstring to_wstring(long long val);
548wstring to_wstring(unsigned long long val);
549wstring to_wstring(float val);
550wstring to_wstring(double val);
551wstring to_wstring(long double val);
552
553template <> struct hash<string>;
554template <> struct hash<u8string>; // C++20
555template <> struct hash<u16string>;
556template <> struct hash<u32string>;
557template <> struct hash<wstring>;
558
559basic_string<char>     operator""s( const char *str,     size_t len );           // C++14, constexpr since C++20
560basic_string<wchar_t>  operator""s( const wchar_t *str,  size_t len );           // C++14, constexpr since C++20
561constexpr basic_string<char8_t>  operator""s( const char8_t *str,  size_t len ); // C++20
562basic_string<char16_t> operator""s( const char16_t *str, size_t len );           // C++14, constexpr since C++20
563basic_string<char32_t> operator""s( const char32_t *str, size_t len );           // C++14, constexpr since C++20
564
565}  // std
566
567*/
568
569// clang-format on
570
571#include <__algorithm/max.h>
572#include <__algorithm/min.h>
573#include <__algorithm/remove.h>
574#include <__algorithm/remove_if.h>
575#include <__assert> // all public C++ headers provide the assertion handler
576#include <__config>
577#include <__format/enable_insertable.h>
578#include <__functional/hash.h>
579#include <__functional/unary_function.h>
580#include <__fwd/string.h>
581#include <__ios/fpos.h>
582#include <__iterator/distance.h>
583#include <__iterator/iterator_traits.h>
584#include <__iterator/reverse_iterator.h>
585#include <__iterator/wrap_iter.h>
586#include <__memory/addressof.h>
587#include <__memory/allocate_at_least.h>
588#include <__memory/allocator.h>
589#include <__memory/allocator_traits.h>
590#include <__memory/compressed_pair.h>
591#include <__memory/construct_at.h>
592#include <__memory/pointer_traits.h>
593#include <__memory/swap_allocator.h>
594#include <__memory_resource/polymorphic_allocator.h>
595#include <__ranges/access.h>
596#include <__ranges/concepts.h>
597#include <__ranges/container_compatible_range.h>
598#include <__ranges/from_range.h>
599#include <__ranges/size.h>
600#include <__string/char_traits.h>
601#include <__string/extern_template_lists.h>
602#include <__type_traits/is_allocator.h>
603#include <__type_traits/is_array.h>
604#include <__type_traits/is_convertible.h>
605#include <__type_traits/is_nothrow_default_constructible.h>
606#include <__type_traits/is_nothrow_move_assignable.h>
607#include <__type_traits/is_same.h>
608#include <__type_traits/is_standard_layout.h>
609#include <__type_traits/is_trivial.h>
610#include <__type_traits/noexcept_move_assign_container.h>
611#include <__type_traits/remove_cvref.h>
612#include <__type_traits/void_t.h>
613#include <__utility/auto_cast.h>
614#include <__utility/declval.h>
615#include <__utility/forward.h>
616#include <__utility/is_pointer_in_range.h>
617#include <__utility/move.h>
618#include <__utility/swap.h>
619#include <__utility/unreachable.h>
620#include <climits>
621#include <cstdio>  // EOF
622#include <cstring>
623#include <limits>
624#include <stdexcept>
625#include <string_view>
626#include <version>
627
628#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
629#  include <cwchar>
630#endif
631
632// standard-mandated includes
633
634// [iterator.range]
635#include <__iterator/access.h>
636#include <__iterator/data.h>
637#include <__iterator/empty.h>
638#include <__iterator/reverse_access.h>
639#include <__iterator/size.h>
640
641// [string.syn]
642#include <compare>
643#include <initializer_list>
644
645#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
646#  pragma GCC system_header
647#endif
648
649_LIBCPP_PUSH_MACROS
650#include <__undef_macros>
651
652#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
653#  define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS __attribute__((__no_sanitize__("address")))
654// This macro disables AddressSanitizer (ASan) instrumentation for a specific function,
655// allowing memory accesses that would normally trigger ASan errors to proceed without crashing.
656// This is useful for accessing parts of objects memory, which should not be accessed,
657// such as unused bytes in short strings, that should never be accessed
658// by other parts of the program.
659#else
660#  define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
661#endif
662#define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false
663
664_LIBCPP_BEGIN_NAMESPACE_STD
665
666// basic_string
667
668template<class _CharT, class _Traits, class _Allocator>
669basic_string<_CharT, _Traits, _Allocator>
670_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
671operator+(const basic_string<_CharT, _Traits, _Allocator>& __x,
672          const basic_string<_CharT, _Traits, _Allocator>& __y);
673
674template<class _CharT, class _Traits, class _Allocator>
675_LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20
676basic_string<_CharT, _Traits, _Allocator>
677operator+(const _CharT* __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
678
679template<class _CharT, class _Traits, class _Allocator>
680_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
681basic_string<_CharT, _Traits, _Allocator>
682operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
683
684template<class _CharT, class _Traits, class _Allocator>
685inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
686basic_string<_CharT, _Traits, _Allocator>
687operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y);
688
689template<class _CharT, class _Traits, class _Allocator>
690_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
691basic_string<_CharT, _Traits, _Allocator>
692operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y);
693
694extern template _LIBCPP_EXPORTED_FROM_ABI string operator+
695    <char, char_traits<char>, allocator<char> >(char const*, string const&);
696
697template <class _Iter>
698struct __string_is_trivial_iterator : public false_type {};
699
700template <class _Tp>
701struct __string_is_trivial_iterator<_Tp*>
702    : public is_arithmetic<_Tp> {};
703
704template <class _Iter>
705struct __string_is_trivial_iterator<__wrap_iter<_Iter> >
706    : public __string_is_trivial_iterator<_Iter> {};
707
708template <class _CharT, class _Traits, class _Tp>
709struct __can_be_converted_to_string_view : public _BoolConstant<
710      is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value &&
711     !is_convertible<const _Tp&, const _CharT*>::value
712    > {};
713
714struct __uninitialized_size_tag {};
715struct __init_with_sentinel_tag {};
716
717template<class _CharT, class _Traits, class _Allocator>
718class basic_string
719{
720private:
721  using __default_allocator_type = allocator<_CharT>;
722
723public:
724    typedef basic_string                                 __self;
725    typedef basic_string_view<_CharT, _Traits>           __self_view;
726    typedef _Traits                                      traits_type;
727    typedef _CharT                                       value_type;
728    typedef _Allocator                                   allocator_type;
729    typedef allocator_traits<allocator_type>             __alloc_traits;
730    typedef typename __alloc_traits::size_type           size_type;
731    typedef typename __alloc_traits::difference_type     difference_type;
732    typedef value_type&                                  reference;
733    typedef const value_type&                            const_reference;
734    typedef typename __alloc_traits::pointer             pointer;
735    typedef typename __alloc_traits::const_pointer       const_pointer;
736
737    static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array");
738    static_assert(( is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout");
739    static_assert(( is_trivial<value_type>::value), "Character type of basic_string must be trivial");
740    static_assert(( is_same<_CharT, typename traits_type::char_type>::value),
741                  "traits_type::char_type must be the same type as CharT");
742    static_assert(( is_same<typename allocator_type::value_type, value_type>::value),
743                  "Allocator::value_type must be same type as value_type");
744
745    static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
746                  "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
747                  "original allocator");
748
749    // TODO: Implement iterator bounds checking without requiring the global database.
750    typedef __wrap_iter<pointer>                         iterator;
751    typedef __wrap_iter<const_pointer>                   const_iterator;
752    typedef std::reverse_iterator<iterator>              reverse_iterator;
753    typedef std::reverse_iterator<const_iterator>        const_reverse_iterator;
754
755private:
756    static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits");
757
758#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
759
760    struct __long
761    {
762        pointer   __data_;
763        size_type __size_;
764        size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
765        size_type __is_long_ : 1;
766    };
767
768    enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
769                      (sizeof(__long) - 1)/sizeof(value_type) : 2};
770
771    struct __short
772    {
773        value_type __data_[__min_cap];
774        unsigned char __padding_[sizeof(value_type) - 1];
775        unsigned char __size_ : 7;
776        unsigned char __is_long_ : 1;
777    };
778
779// The __endian_factor is required because the field we use to store the size
780// has one fewer bit than it would if it were not a bitfield.
781//
782// If the LSB is used to store the short-flag in the short string representation,
783// we have to multiply the size by two when it is stored and divide it by two when
784// it is loaded to make sure that we always store an even number. In the long string
785// representation, we can ignore this because we can assume that we always allocate
786// an even amount of value_types.
787//
788// If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2.
789// This does not impact the short string representation, since we never need the MSB
790// for representing the size of a short string anyway.
791
792#ifdef _LIBCPP_BIG_ENDIAN
793    static const size_type __endian_factor = 2;
794#else
795    static const size_type __endian_factor = 1;
796#endif
797
798#else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
799
800#ifdef _LIBCPP_BIG_ENDIAN
801    static const size_type __endian_factor = 1;
802#else
803    static const size_type __endian_factor = 2;
804#endif
805
806    // Attribute 'packed' is used to keep the layout compatible with the
807    // previous definition that did not use bit fields. This is because on
808    // some platforms bit fields have a default size rather than the actual
809    // size used, e.g., it is 4 bytes on AIX. See D128285 for details.
810    struct __long
811    {
812        struct _LIBCPP_PACKED {
813            size_type __is_long_ : 1;
814            size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
815        };
816        size_type __size_;
817        pointer   __data_;
818    };
819
820    enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
821                      (sizeof(__long) - 1)/sizeof(value_type) : 2};
822
823    struct __short
824    {
825        struct _LIBCPP_PACKED {
826            unsigned char __is_long_ : 1;
827            unsigned char __size_ : 7;
828        };
829        char __padding_[sizeof(value_type) - 1];
830        value_type __data_[__min_cap];
831    };
832
833#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
834
835    static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
836
837    union __ulx{__long __lx; __short __lxx;};
838
839    enum {__n_words = sizeof(__ulx) / sizeof(size_type)};
840
841    struct __raw
842    {
843        size_type __words[__n_words];
844    };
845
846    struct __rep
847    {
848        union
849        {
850            __short __s;
851            __long  __l;
852            __raw   __r;
853        };
854    };
855
856    __compressed_pair<__rep, allocator_type> __r_;
857
858    // Construct a string with the given allocator and enough storage to hold `__size` characters, but
859    // don't initialize the characters. The contents of the string, including the null terminator, must be
860    // initialized separately.
861    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
862    explicit basic_string(__uninitialized_size_tag, size_type __size, const allocator_type& __a)
863            : __r_(__default_init_tag(), __a) {
864        if (__size > max_size())
865            __throw_length_error();
866        if (__fits_in_sso(__size)) {
867            __r_.first() = __rep();
868            __set_short_size(__size);
869        } else {
870            auto __capacity = __recommend(__size) + 1;
871            auto __allocation = __alloc_traits::allocate(__alloc(), __capacity);
872            __begin_lifetime(__allocation, __capacity);
873            __set_long_cap(__capacity);
874            __set_long_pointer(__allocation);
875            __set_long_size(__size);
876        }
877        __annotate_new(__size);
878    }
879
880    template <class _Iter, class _Sent>
881    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
882    basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a)
883        : __r_(__default_init_tag(), __a) {
884      __init_with_sentinel(std::move(__first), std::move(__last));
885    }
886
887    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iterator(pointer __p) {
888        return iterator(__p);
889    }
890
891    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_const_iterator(const_pointer __p) const {
892        return const_iterator(__p);
893    }
894
895public:
896  _LIBCPP_TEMPLATE_DATA_VIS static const size_type npos = -1;
897
898  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string()
899      _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
900      : __r_(__value_init_tag(), __default_init_tag()) {
901            __annotate_new(0);
902  }
903
904  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a)
905#if _LIBCPP_STD_VER <= 14
906      _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
907#else
908      _NOEXCEPT
909#endif
910      : __r_(__value_init_tag(), __a) {
911            __annotate_new(0);
912  }
913
914  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str)
915      : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) {
916    if (!__str.__is_long())
917    {
918      __r_.first() = __str.__r_.first();
919      __annotate_new(__get_short_size());
920    }
921    else
922      __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
923  }
924
925  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str, const allocator_type& __a)
926      : __r_(__default_init_tag(), __a) {
927    if (!__str.__is_long())
928    {
929      __r_.first() = __str.__r_.first();
930      __annotate_new(__get_short_size());
931    }
932    else
933      __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
934  }
935
936#ifndef _LIBCPP_CXX03_LANG
937  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
938  basic_string(basic_string&& __str)
939#  if _LIBCPP_STD_VER <= 14
940      _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
941#  else
942      _NOEXCEPT
943#  endif
944      // Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
945      // does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first.
946      // __str's memory needs to be unpoisoned only in the case where it's a short string.
947      : __r_( ( (__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_)) ) {
948    __str.__r_.first() = __rep();
949    __str.__annotate_new(0);
950    if(!__is_long())
951      __annotate_new(size());
952  }
953
954  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
955  basic_string(basic_string&& __str, const allocator_type& __a)
956      : __r_(__default_init_tag(), __a) {
957    if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
958      __init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
959    else {
960      if (__libcpp_is_constant_evaluated())
961        __r_.first() = __rep();
962      if (!__str.__is_long())
963        __str.__annotate_delete();
964      __r_.first() = __str.__r_.first();
965      __str.__r_.first() = __rep();
966      __str.__annotate_new(0);
967      if(!__is_long() && this != &__str)
968        __annotate_new(size());
969    }
970  }
971#endif // _LIBCPP_CXX03_LANG
972
973  template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
974  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s)
975      : __r_(__default_init_tag(), __default_init_tag()) {
976    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*) detected nullptr");
977    __init(__s, traits_type::length(__s));
978  }
979
980  template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
981  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a)
982      : __r_(__default_init_tag(), __a) {
983    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
984    __init(__s, traits_type::length(__s));
985  }
986
987#if _LIBCPP_STD_VER >= 23
988  basic_string(nullptr_t) = delete;
989#endif
990
991  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n)
992      : __r_(__default_init_tag(), __default_init_tag()) {
993    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr");
994    __init(__s, __n);
995  }
996
997  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
998  basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
999      : __r_(__default_init_tag(), __a) {
1000    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
1001    __init(__s, __n);
1002  }
1003
1004  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c)
1005      : __r_(__default_init_tag(), __default_init_tag()) {
1006    __init(__n, __c);
1007  }
1008
1009#if _LIBCPP_STD_VER >= 23
1010  _LIBCPP_HIDE_FROM_ABI constexpr
1011  basic_string(basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator())
1012      : basic_string(std::move(__str), __pos, npos, __alloc) {}
1013
1014  _LIBCPP_HIDE_FROM_ABI constexpr
1015  basic_string(basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator())
1016      : __r_(__default_init_tag(), __alloc) {
1017    if (__pos > __str.size())
1018      __throw_out_of_range();
1019
1020    auto __len = std::min<size_type>(__n, __str.size() - __pos);
1021    if (__alloc_traits::is_always_equal::value || __alloc == __str.__alloc()) {
1022      __move_assign(std::move(__str), __pos, __len);
1023    } else {
1024      // Perform a copy because the allocators are not compatible.
1025      __init(__str.data() + __pos, __len);
1026    }
1027  }
1028#endif
1029
1030  template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
1031  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a)
1032      : __r_(__default_init_tag(), __a) {
1033    __init(__n, __c);
1034  }
1035
1036  _LIBCPP_CONSTEXPR_SINCE_CXX20
1037  basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator())
1038      : __r_(__default_init_tag(), __a) {
1039    size_type __str_sz = __str.size();
1040    if (__pos > __str_sz)
1041      __throw_out_of_range();
1042    __init(__str.data() + __pos, std::min(__n, __str_sz - __pos));
1043  }
1044
1045  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1046  basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator())
1047      : __r_(__default_init_tag(), __a) {
1048    size_type __str_sz = __str.size();
1049    if (__pos > __str_sz)
1050      __throw_out_of_range();
1051    __init(__str.data() + __pos, __str_sz - __pos);
1052  }
1053
1054  template <class _Tp,
1055            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1056                              !__is_same_uncvref<_Tp, basic_string>::value,
1057                          int> = 0>
1058  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
1059  basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type())
1060      : __r_(__default_init_tag(), __a) {
1061    __self_view __sv0 = __t;
1062    __self_view __sv  = __sv0.substr(__pos, __n);
1063    __init(__sv.data(), __sv.size());
1064  }
1065
1066  template <class _Tp,
1067            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1068                              !__is_same_uncvref<_Tp, basic_string>::value,
1069                          int> = 0>
1070  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t)
1071      : __r_(__default_init_tag(), __default_init_tag()) {
1072    __self_view __sv = __t;
1073    __init(__sv.data(), __sv.size());
1074  }
1075
1076  template <class _Tp,
1077            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1078                              !__is_same_uncvref<_Tp, basic_string>::value,
1079                          int> = 0>
1080  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(
1081      const _Tp& __t, const allocator_type& __a)
1082      : __r_(__default_init_tag(), __a) {
1083    __self_view __sv = __t;
1084    __init(__sv.data(), __sv.size());
1085  }
1086
1087  template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
1088  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last)
1089      : __r_(__default_init_tag(), __default_init_tag()) {
1090    __init(__first, __last);
1091  }
1092
1093  template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
1094  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1095  basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
1096      : __r_(__default_init_tag(), __a) {
1097    __init(__first, __last);
1098  }
1099
1100#if _LIBCPP_STD_VER >= 23
1101  template <_ContainerCompatibleRange<_CharT> _Range>
1102  _LIBCPP_HIDE_FROM_ABI constexpr
1103  basic_string(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
1104      : __r_(__default_init_tag(), __a) {
1105    if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
1106      __init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range));
1107    } else {
1108      __init_with_sentinel(ranges::begin(__range), ranges::end(__range));
1109    }
1110  }
1111#endif
1112
1113#ifndef _LIBCPP_CXX03_LANG
1114  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il)
1115      : __r_(__default_init_tag(), __default_init_tag()) {
1116    __init(__il.begin(), __il.end());
1117  }
1118
1119  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a)
1120      : __r_(__default_init_tag(), __a) {
1121    __init(__il.begin(), __il.end());
1122  }
1123#endif // _LIBCPP_CXX03_LANG
1124
1125  inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() {
1126    __annotate_delete();
1127    if (__is_long())
1128      __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
1129  }
1130
1131    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1132    operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); }
1133
1134    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(const basic_string& __str);
1135
1136    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1137                                           !__is_same_uncvref<_Tp, basic_string>::value, int> = 0>
1138    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const _Tp& __t) {
1139      __self_view __sv = __t;
1140      return assign(__sv);
1141    }
1142
1143#ifndef _LIBCPP_CXX03_LANG
1144    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1145    operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) {
1146    __move_assign(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
1147    return *this;
1148  }
1149
1150     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1151    basic_string& operator=(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());}
1152#endif
1153    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1154    basic_string& operator=(const value_type* __s) {return assign(__s);}
1155#if _LIBCPP_STD_VER >= 23
1156    basic_string& operator=(nullptr_t) = delete;
1157#endif
1158    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(value_type __c);
1159
1160    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1161    iterator begin() _NOEXCEPT
1162        {return __make_iterator(__get_pointer());}
1163    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1164    const_iterator begin() const _NOEXCEPT
1165        {return __make_const_iterator(__get_pointer());}
1166    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1167    iterator end() _NOEXCEPT
1168        {return __make_iterator(__get_pointer() + size());}
1169    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1170    const_iterator end() const _NOEXCEPT
1171        {return __make_const_iterator(__get_pointer() + size());}
1172
1173    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1174    reverse_iterator rbegin() _NOEXCEPT
1175        {return reverse_iterator(end());}
1176    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1177    const_reverse_iterator rbegin() const _NOEXCEPT
1178        {return const_reverse_iterator(end());}
1179    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1180    reverse_iterator rend() _NOEXCEPT
1181        {return reverse_iterator(begin());}
1182    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1183    const_reverse_iterator rend() const _NOEXCEPT
1184        {return const_reverse_iterator(begin());}
1185
1186    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1187    const_iterator cbegin() const _NOEXCEPT
1188        {return begin();}
1189    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1190    const_iterator cend() const _NOEXCEPT
1191        {return end();}
1192    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1193    const_reverse_iterator crbegin() const _NOEXCEPT
1194        {return rbegin();}
1195    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1196    const_reverse_iterator crend() const _NOEXCEPT
1197        {return rend();}
1198
1199    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT
1200        {return __is_long() ? __get_long_size() : __get_short_size();}
1201    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT {return size();}
1202
1203  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT {
1204    size_type __m = __alloc_traits::max_size(__alloc());
1205    if (__m <= std::numeric_limits<size_type>::max() / 2) {
1206      return __m - __alignment;
1207    } else {
1208    bool __uses_lsb = __endian_factor == 2;
1209      return __uses_lsb ? __m - __alignment : (__m / 2) - __alignment;
1210    }
1211  }
1212
1213    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT {
1214        return (__is_long() ? __get_long_cap() : static_cast<size_type>(__min_cap)) - 1;
1215    }
1216
1217    _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n, value_type __c);
1218    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n) { resize(__n, value_type()); }
1219
1220    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity);
1221
1222#if _LIBCPP_STD_VER >= 23
1223    template <class _Op>
1224    _LIBCPP_HIDE_FROM_ABI constexpr
1225    void resize_and_overwrite(size_type __n, _Op __op) {
1226      __resize_default_init(__n);
1227      __erase_to_end(std::move(__op)(data(), _LIBCPP_AUTO_CAST(__n)));
1228    }
1229#endif
1230
1231    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __resize_default_init(size_type __n);
1232
1233#if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE)
1234    _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve() _NOEXCEPT { shrink_to_fit(); }
1235#endif
1236    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT;
1237    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT;
1238
1239    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1240    bool empty() const _NOEXCEPT {return size() == 0;}
1241
1242  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT {
1243    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
1244    if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
1245      return *(__get_long_pointer() + __pos);
1246    }
1247    return *(data() + __pos);
1248  }
1249
1250  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT {
1251    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
1252    if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
1253      return *(__get_long_pointer() + __pos);
1254    }
1255    return *(__get_pointer() + __pos);
1256  }
1257
1258    _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const;
1259    _LIBCPP_CONSTEXPR_SINCE_CXX20 reference       at(size_type __n);
1260
1261    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const basic_string& __str) {
1262        return append(__str);
1263    }
1264
1265    template <class _Tp,
1266              __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1267                                !__is_same_uncvref<_Tp, basic_string >::value,
1268                            int> = 0>
1269    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1270    operator+=(const _Tp& __t) {
1271        __self_view __sv = __t; return append(__sv);
1272    }
1273
1274    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const value_type* __s) {
1275        return append(__s);
1276    }
1277
1278    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(value_type __c) {
1279        push_back(__c);
1280        return *this;
1281    }
1282
1283#ifndef _LIBCPP_CXX03_LANG
1284    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1285    basic_string& operator+=(initializer_list<value_type> __il) { return append(__il); }
1286#endif // _LIBCPP_CXX03_LANG
1287
1288  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str) {
1289        return append(__str.data(), __str.size());
1290  }
1291
1292  template <class _Tp,
1293            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1294                              !__is_same_uncvref<_Tp, basic_string>::value,
1295                          int> = 0>
1296  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1297  append(const _Tp& __t) {
1298        __self_view __sv = __t;
1299        return append(__sv.data(), __sv.size());
1300  }
1301
1302    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos);
1303
1304    template <class _Tp,
1305              __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1306                                !__is_same_uncvref<_Tp, basic_string>::value,
1307                            int> = 0>
1308    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
1309
1310        basic_string&
1311        append(const _Tp& __t, size_type __pos, size_type __n = npos);
1312
1313    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n);
1314    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s);
1315    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c);
1316
1317    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1318    void __append_default_init(size_type __n);
1319
1320    template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
1321    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1322    append(_InputIterator __first, _InputIterator __last) {
1323        const basic_string __temp(__first, __last, __alloc());
1324        append(__temp.data(), __temp.size());
1325        return *this;
1326    }
1327
1328    template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
1329    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1330    append(_ForwardIterator __first, _ForwardIterator __last);
1331
1332#if _LIBCPP_STD_VER >= 23
1333    template <_ContainerCompatibleRange<_CharT> _Range>
1334    _LIBCPP_HIDE_FROM_ABI
1335    constexpr basic_string& append_range(_Range&& __range) {
1336      insert_range(end(), std::forward<_Range>(__range));
1337      return *this;
1338    }
1339#endif
1340
1341#ifndef _LIBCPP_CXX03_LANG
1342    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1343    basic_string& append(initializer_list<value_type> __il) {return append(__il.begin(), __il.size());}
1344#endif // _LIBCPP_CXX03_LANG
1345
1346    _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c);
1347    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back();
1348
1349  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT {
1350    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
1351    return *__get_pointer();
1352  }
1353
1354  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT {
1355    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
1356    return *data();
1357  }
1358
1359  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT {
1360    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
1361    return *(__get_pointer() + size() - 1);
1362  }
1363
1364  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT {
1365    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
1366    return *(data() + size() - 1);
1367  }
1368
1369  template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1370  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1371  assign(const _Tp& __t) {
1372    __self_view __sv = __t;
1373    return assign(__sv.data(), __sv.size());
1374  }
1375
1376#if _LIBCPP_STD_VER >= 20
1377  _LIBCPP_HIDE_FROM_ABI constexpr
1378  void __move_assign(basic_string&& __str, size_type __pos, size_type __len) {
1379    // Pilfer the allocation from __str.
1380    _LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator");
1381    size_type __old_sz = __str.size();
1382    if (!__str.__is_long())
1383      __str.__annotate_delete();
1384    __r_.first() = __str.__r_.first();
1385    __str.__r_.first() = __rep();
1386    __str.__annotate_new(0);
1387
1388    _Traits::move(data(), data() + __pos, __len);
1389    __set_size(__len);
1390    _Traits::assign(data()[__len], value_type());
1391
1392    if (!__is_long()) {
1393      __annotate_new(__len);
1394    } else if(__old_sz > __len) {
1395      __annotate_shrink(__old_sz);
1396    }
1397  }
1398#endif
1399
1400    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1401    basic_string& assign(const basic_string& __str) { return *this = __str; }
1402#ifndef _LIBCPP_CXX03_LANG
1403    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1404    basic_string& assign(basic_string&& __str)
1405        _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
1406        {*this = std::move(__str); return *this;}
1407#endif
1408    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos);
1409
1410    template <class _Tp,
1411              __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1412                                !__is_same_uncvref<_Tp, basic_string>::value,
1413                            int> = 0>
1414    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1415    assign(const _Tp& __t, size_type __pos, size_type __n = npos);
1416
1417    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n);
1418    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s);
1419    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c);
1420    template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
1421    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1422    assign(_InputIterator __first, _InputIterator __last);
1423
1424    template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
1425    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1426    assign(_ForwardIterator __first, _ForwardIterator __last);
1427
1428#if _LIBCPP_STD_VER >= 23
1429    template <_ContainerCompatibleRange<_CharT> _Range>
1430    _LIBCPP_HIDE_FROM_ABI
1431    constexpr basic_string& assign_range(_Range&& __range) {
1432      if constexpr (__string_is_trivial_iterator<ranges::iterator_t<_Range>>::value &&
1433          (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) {
1434        size_type __n = static_cast<size_type>(ranges::distance(__range));
1435        __assign_trivial(ranges::begin(__range), ranges::end(__range), __n);
1436
1437      } else {
1438        __assign_with_sentinel(ranges::begin(__range), ranges::end(__range));
1439      }
1440
1441      return *this;
1442    }
1443#endif
1444
1445#ifndef _LIBCPP_CXX03_LANG
1446    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1447    basic_string& assign(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());}
1448#endif // _LIBCPP_CXX03_LANG
1449
1450  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1451  insert(size_type __pos1, const basic_string& __str) {
1452    return insert(__pos1, __str.data(), __str.size());
1453  }
1454
1455  template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1456  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1457  insert(size_type __pos1, const _Tp& __t) {
1458    __self_view __sv = __t;
1459    return insert(__pos1, __sv.data(), __sv.size());
1460  }
1461
1462  template <class _Tp,
1463            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1464                              !__is_same_uncvref<_Tp, basic_string>::value,
1465                          int> = 0>
1466  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1467  insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos);
1468
1469  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1470  insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos);
1471  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n);
1472  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s);
1473  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c);
1474  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c);
1475
1476#if _LIBCPP_STD_VER >= 23
1477    template <_ContainerCompatibleRange<_CharT> _Range>
1478    _LIBCPP_HIDE_FROM_ABI
1479    constexpr iterator insert_range(const_iterator __position, _Range&& __range) {
1480      if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
1481        auto __n = static_cast<size_type>(ranges::distance(__range));
1482        return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n);
1483
1484      } else {
1485        basic_string __temp(from_range, std::forward<_Range>(__range), __alloc());
1486        return insert(__position, __temp.data(), __temp.data() + __temp.size());
1487      }
1488    }
1489#endif
1490
1491  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
1492  insert(const_iterator __pos, size_type __n, value_type __c) {
1493    difference_type __p = __pos - begin();
1494    insert(static_cast<size_type>(__p), __n, __c);
1495    return begin() + __p;
1496  }
1497
1498  template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
1499  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
1500  insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);
1501
1502  template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
1503  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
1504  insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
1505
1506#ifndef _LIBCPP_CXX03_LANG
1507    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1508    iterator insert(const_iterator __pos, initializer_list<value_type> __il)
1509                    {return insert(__pos, __il.begin(), __il.end());}
1510#endif // _LIBCPP_CXX03_LANG
1511
1512    _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& erase(size_type __pos = 0, size_type __n = npos);
1513    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1514    iterator      erase(const_iterator __pos);
1515    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1516    iterator      erase(const_iterator __first, const_iterator __last);
1517
1518  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1519  replace(size_type __pos1, size_type __n1, const basic_string& __str) {
1520    return replace(__pos1, __n1, __str.data(), __str.size());
1521  }
1522
1523  template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1524  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1525  replace(size_type __pos1, size_type __n1, const _Tp& __t) {
1526    __self_view __sv = __t;
1527    return replace(__pos1, __n1, __sv.data(), __sv.size());
1528  }
1529
1530  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1531  replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos);
1532
1533  template <class _Tp,
1534            __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1535                              !__is_same_uncvref<_Tp, basic_string>::value,
1536                          int> = 0>
1537  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1538  replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos);
1539
1540  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1541  replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2);
1542  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s);
1543  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c);
1544
1545  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1546  replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) {
1547    return replace(
1548        static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __str.data(), __str.size());
1549  }
1550
1551  template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1552  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1553  replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) {
1554    __self_view __sv = __t;
1555    return replace(__i1 - begin(), __i2 - __i1, __sv);
1556  }
1557
1558  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1559  replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) {
1560    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s, __n);
1561  }
1562
1563  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1564  replace(const_iterator __i1, const_iterator __i2, const value_type* __s) {
1565    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s);
1566  }
1567
1568  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1569  replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) {
1570    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c);
1571  }
1572
1573  template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
1574  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1575  replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2);
1576
1577#if _LIBCPP_STD_VER >= 23
1578  template <_ContainerCompatibleRange<_CharT> _Range>
1579  _LIBCPP_HIDE_FROM_ABI
1580  constexpr basic_string& replace_with_range(const_iterator __i1, const_iterator __i2, _Range&& __range) {
1581    basic_string __temp(from_range, std::forward<_Range>(__range), __alloc());
1582    return replace(__i1, __i2, __temp);
1583  }
1584#endif
1585
1586#ifndef _LIBCPP_CXX03_LANG
1587    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1588    basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il)
1589        {return replace(__i1, __i2, __il.begin(), __il.end());}
1590#endif // _LIBCPP_CXX03_LANG
1591
1592    _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
1593
1594#if _LIBCPP_STD_VER <= 20
1595    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1596    basic_string substr(size_type __pos = 0, size_type __n = npos) const {
1597      return basic_string(*this, __pos, __n);
1598    }
1599#else
1600    _LIBCPP_HIDE_FROM_ABI constexpr
1601    basic_string substr(size_type __pos = 0, size_type __n = npos) const& {
1602      return basic_string(*this, __pos, __n);
1603    }
1604
1605    _LIBCPP_HIDE_FROM_ABI constexpr
1606    basic_string substr(size_type __pos = 0, size_type __n = npos) && {
1607      return basic_string(std::move(*this), __pos, __n);
1608    }
1609#endif
1610
1611    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1612    void swap(basic_string& __str)
1613#if _LIBCPP_STD_VER >= 14
1614        _NOEXCEPT;
1615#else
1616        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
1617                    __is_nothrow_swappable<allocator_type>::value);
1618#endif
1619
1620    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1621    const value_type* c_str() const _NOEXCEPT {return data();}
1622    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1623    const value_type* data() const _NOEXCEPT  {return std::__to_address(__get_pointer());}
1624#if _LIBCPP_STD_VER >= 17
1625    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1626    value_type* data()             _NOEXCEPT  {return std::__to_address(__get_pointer());}
1627#endif
1628
1629    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1630    allocator_type get_allocator() const _NOEXCEPT {return __alloc();}
1631
1632    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1633    size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
1634
1635    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1636    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1637    find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT;
1638
1639    _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1640    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1641    size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
1642    _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT;
1643
1644    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1645    size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
1646
1647    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1648    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1649    rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
1650
1651    _LIBCPP_CONSTEXPR_SINCE_CXX20
1652    size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1653    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1654    size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
1655    _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT;
1656
1657    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1658    size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
1659
1660    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1661    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1662    find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT;
1663
1664    _LIBCPP_CONSTEXPR_SINCE_CXX20
1665    size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1666    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1667    size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
1668    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1669    size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT;
1670
1671    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1672    size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
1673
1674    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1675    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1676    find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
1677
1678    _LIBCPP_CONSTEXPR_SINCE_CXX20
1679    size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1680    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1681    size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
1682    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1683    size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT;
1684
1685    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1686    size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
1687
1688    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1689    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1690    find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT;
1691
1692    _LIBCPP_CONSTEXPR_SINCE_CXX20
1693    size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1694    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1695    size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
1696    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1697    size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT;
1698
1699    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1700    size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
1701
1702    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1703    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1704    find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
1705
1706    _LIBCPP_CONSTEXPR_SINCE_CXX20
1707    size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
1708    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1709    size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
1710    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1711    size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT;
1712
1713    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1714    int compare(const basic_string& __str) const _NOEXCEPT;
1715
1716    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1717    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int
1718    compare(const _Tp& __t) const _NOEXCEPT;
1719
1720    template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
1721    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int
1722    compare(size_type __pos1, size_type __n1, const _Tp& __t) const;
1723
1724    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1725    int compare(size_type __pos1, size_type __n1, const basic_string& __str) const;
1726    _LIBCPP_CONSTEXPR_SINCE_CXX20
1727    int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2,
1728                size_type __n2 = npos) const;
1729
1730    template <class _Tp,
1731              __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
1732                                !__is_same_uncvref<_Tp, basic_string>::value,
1733                            int> = 0>
1734    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int
1735    compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const;
1736
1737    _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* __s) const _NOEXCEPT;
1738    _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s) const;
1739    _LIBCPP_CONSTEXPR_SINCE_CXX20
1740    int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const;
1741
1742#if _LIBCPP_STD_VER >= 20
1743    constexpr _LIBCPP_HIDE_FROM_ABI
1744    bool starts_with(__self_view __sv) const noexcept
1745    { return __self_view(data(), size()).starts_with(__sv); }
1746
1747    constexpr _LIBCPP_HIDE_FROM_ABI
1748    bool starts_with(value_type __c) const noexcept
1749    { return !empty() && _Traits::eq(front(), __c); }
1750
1751    constexpr _LIBCPP_HIDE_FROM_ABI
1752    bool starts_with(const value_type* __s) const noexcept
1753    { return starts_with(__self_view(__s)); }
1754
1755    constexpr _LIBCPP_HIDE_FROM_ABI
1756    bool ends_with(__self_view __sv) const noexcept
1757    { return __self_view(data(), size()).ends_with( __sv); }
1758
1759    constexpr _LIBCPP_HIDE_FROM_ABI
1760    bool ends_with(value_type __c) const noexcept
1761    { return !empty() && _Traits::eq(back(), __c); }
1762
1763    constexpr _LIBCPP_HIDE_FROM_ABI
1764    bool ends_with(const value_type* __s) const noexcept
1765    { return ends_with(__self_view(__s)); }
1766#endif
1767
1768#if _LIBCPP_STD_VER >= 23
1769    constexpr _LIBCPP_HIDE_FROM_ABI
1770    bool contains(__self_view __sv) const noexcept
1771    { return __self_view(data(), size()).contains(__sv); }
1772
1773    constexpr _LIBCPP_HIDE_FROM_ABI
1774    bool contains(value_type __c) const noexcept
1775    { return __self_view(data(), size()).contains(__c); }
1776
1777    constexpr _LIBCPP_HIDE_FROM_ABI
1778    bool contains(const value_type* __s) const
1779    { return __self_view(data(), size()).contains(__s); }
1780#endif
1781
1782    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const;
1783
1784    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __clear_and_shrink() _NOEXCEPT;
1785
1786private:
1787    template<class _Alloc>
1788    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1789    bool friend operator==(const basic_string<char, char_traits<char>, _Alloc>& __lhs,
1790                           const basic_string<char, char_traits<char>, _Alloc>& __rhs) _NOEXCEPT;
1791
1792    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __shrink_or_extend(size_type __target_capacity);
1793
1794    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
1795    bool __is_long() const _NOEXCEPT {
1796        if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) {
1797            return __r_.first().__l.__is_long_;
1798        }
1799        return __r_.first().__s.__is_long_;
1800    }
1801
1802    static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) {
1803#if _LIBCPP_STD_VER >= 20
1804        if (__libcpp_is_constant_evaluated()) {
1805            for (size_type __i = 0; __i != __n; ++__i)
1806                std::construct_at(std::addressof(__begin[__i]));
1807        }
1808#else
1809        (void)__begin;
1810        (void)__n;
1811#endif // _LIBCPP_STD_VER >= 20
1812    }
1813
1814    _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) {
1815        return __sz < __min_cap;
1816    }
1817
1818    template <class _Iterator, class _Sentinel>
1819    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
1820    void __assign_trivial(_Iterator __first, _Sentinel __last, size_type __n);
1821
1822    template <class _Iterator, class _Sentinel>
1823    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
1824    void __assign_with_sentinel(_Iterator __first, _Sentinel __last);
1825
1826    template <class _ForwardIterator, class _Sentinel>
1827    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
1828    iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) {
1829        size_type __sz = size();
1830        size_type __cap = capacity();
1831        value_type* __p;
1832        if (__cap - __sz >= __n)
1833        {
1834          __annotate_increase(__n);
1835            __p = std::__to_address(__get_pointer());
1836            size_type __n_move = __sz - __ip;
1837            if (__n_move != 0)
1838                traits_type::move(__p + __ip + __n, __p + __ip, __n_move);
1839        }
1840        else
1841        {
1842            __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __ip, 0, __n);
1843            __p = std::__to_address(__get_long_pointer());
1844        }
1845        __sz += __n;
1846        __set_size(__sz);
1847        traits_type::assign(__p[__sz], value_type());
1848        for (__p += __ip; __first != __last; ++__p, ++__first)
1849            traits_type::assign(*__p, *__first);
1850
1851        return begin() + __ip;
1852    }
1853
1854    template<class _Iterator, class _Sentinel>
1855    _LIBCPP_CONSTEXPR_SINCE_CXX20
1856    iterator __insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n);
1857
1858    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
1859    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
1860
1861    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
1862    void __set_short_size(size_type __s) _NOEXCEPT {
1863        _LIBCPP_ASSERT_INTERNAL(
1864            __s < __min_cap, "__s should never be greater than or equal to the short string capacity");
1865        __r_.first().__s.__size_ = __s;
1866        __r_.first().__s.__is_long_ = false;
1867    }
1868
1869    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
1870    size_type __get_short_size() const _NOEXCEPT {
1871        _LIBCPP_ASSERT_INTERNAL(
1872            !__r_.first().__s.__is_long_, "String has to be short when trying to get the short size");
1873        return __r_.first().__s.__size_;
1874    }
1875
1876    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1877    void __set_long_size(size_type __s) _NOEXCEPT
1878        {__r_.first().__l.__size_ = __s;}
1879    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1880    size_type __get_long_size() const _NOEXCEPT
1881        {return __r_.first().__l.__size_;}
1882    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1883    void __set_size(size_type __s) _NOEXCEPT
1884        {if (__is_long()) __set_long_size(__s); else __set_short_size(__s);}
1885
1886    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1887    void __set_long_cap(size_type __s) _NOEXCEPT {
1888        __r_.first().__l.__cap_ = __s / __endian_factor;
1889        __r_.first().__l.__is_long_ = true;
1890    }
1891
1892    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1893    size_type __get_long_cap() const _NOEXCEPT {
1894        return __r_.first().__l.__cap_ * __endian_factor;
1895    }
1896
1897    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1898    void __set_long_pointer(pointer __p) _NOEXCEPT
1899        {__r_.first().__l.__data_ = __p;}
1900    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1901    pointer __get_long_pointer() _NOEXCEPT
1902        {return __r_.first().__l.__data_;}
1903    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1904    const_pointer __get_long_pointer() const _NOEXCEPT
1905        {return __r_.first().__l.__data_;}
1906    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1907    pointer __get_short_pointer() _NOEXCEPT
1908        {return pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]);}
1909    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1910    const_pointer __get_short_pointer() const _NOEXCEPT
1911        {return pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]);}
1912    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1913    pointer __get_pointer() _NOEXCEPT
1914        {return __is_long() ? __get_long_pointer() : __get_short_pointer();}
1915    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1916    const_pointer __get_pointer() const _NOEXCEPT
1917        {return __is_long() ? __get_long_pointer() : __get_short_pointer();}
1918
1919    // The following functions are no-ops outside of AddressSanitizer mode.
1920    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
1921        (void)__old_mid;
1922        (void)__new_mid;
1923#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
1924        const void* __begin = data();
1925        const void* __end = data() + capacity() + 1;
1926        if (!__libcpp_is_constant_evaluated() && __begin != nullptr && is_same<allocator_type, __default_allocator_type>::value)
1927          __sanitizer_annotate_contiguous_container(__begin, __end, __old_mid, __new_mid);
1928#endif
1929    }
1930
1931    // ASan: short string is poisoned if and only if this function returns true.
1932    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __asan_short_string_is_annotated() const _NOEXCEPT {
1933      return _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED && !__libcpp_is_constant_evaluated();
1934    }
1935
1936    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_new(size_type __current_size) const _NOEXCEPT {
1937      if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
1938        __annotate_contiguous_container(data() + capacity() + 1, data() + __current_size + 1);
1939    }
1940
1941    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
1942      if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
1943        __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1);
1944    }
1945
1946    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_increase(size_type __n) const _NOEXCEPT {
1947      if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
1948        __annotate_contiguous_container(data() + size() + 1, data() + size() + 1 + __n);
1949    }
1950
1951    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_shrink(size_type __old_size) const _NOEXCEPT {
1952      if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
1953        __annotate_contiguous_container(data() + __old_size + 1, data() + size() + 1);
1954    }
1955
1956    template <size_type __a> static
1957        _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1958        size_type __align_it(size_type __s) _NOEXCEPT
1959            {return (__s + (__a-1)) & ~(__a-1);}
1960    enum {
1961      __alignment =
1962#ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
1963      8
1964#else
1965      16
1966#endif
1967    };
1968    static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1969    size_type __recommend(size_type __s) _NOEXCEPT
1970    {
1971        if (__s < __min_cap) {
1972            return static_cast<size_type>(__min_cap) - 1;
1973        }
1974        size_type __guess = __align_it<sizeof(value_type) < __alignment ?
1975                     __alignment/sizeof(value_type) : 1 > (__s+1) - 1;
1976        if (__guess == __min_cap) ++__guess;
1977        return __guess;
1978    }
1979
1980    inline _LIBCPP_CONSTEXPR_SINCE_CXX20
1981    void __init(const value_type* __s, size_type __sz, size_type __reserve);
1982    inline _LIBCPP_CONSTEXPR_SINCE_CXX20
1983    void __init(const value_type* __s, size_type __sz);
1984    inline _LIBCPP_CONSTEXPR_SINCE_CXX20
1985    void __init(size_type __n, value_type __c);
1986
1987    // Slow path for the (inlined) copy constructor for 'long' strings.
1988    // Always externally instantiated and not inlined.
1989    // Requires that __s is zero terminated.
1990    // The main reason for this function to exist is because for unstable, we
1991    // want to allow inlining of the copy constructor. However, we don't want
1992    // to call the __init() functions as those are marked as inline which may
1993    // result in over-aggressive inlining by the compiler, where our aim is
1994    // to only inline the fast path code directly in the ctor.
1995    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __init_copy_ctor_external(const value_type* __s, size_type __sz);
1996
1997    template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
1998    inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_InputIterator __first, _InputIterator __last);
1999
2000    template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
2001    inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_ForwardIterator __first, _ForwardIterator __last);
2002
2003    template <class _InputIterator, class _Sentinel>
2004    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2005    void __init_with_sentinel(_InputIterator __first, _Sentinel __last);
2006    template <class _InputIterator, class _Sentinel>
2007    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2008    void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz);
2009
2010    _LIBCPP_CONSTEXPR_SINCE_CXX20
2011#if _LIBCPP_ABI_VERSION >= 2 //  We want to use the function in the dylib in ABIv1
2012    _LIBCPP_HIDE_FROM_ABI
2013#endif
2014    _LIBCPP_DEPRECATED_("use __grow_by_without_replace")
2015    void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2016                   size_type __n_copy,  size_type __n_del,     size_type __n_add = 0);
2017    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
2018    void __grow_by_without_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2019                   size_type __n_copy,  size_type __n_del,     size_type __n_add = 0);
2020    _LIBCPP_CONSTEXPR_SINCE_CXX20
2021    void __grow_by_and_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2022                               size_type __n_copy,  size_type __n_del,
2023                               size_type __n_add, const value_type* __p_new_stuff);
2024
2025    // __assign_no_alias is invoked for assignment operations where we
2026    // have proof that the input does not alias the current instance.
2027    // For example, operator=(basic_string) performs a 'self' check.
2028    template <bool __is_short>
2029    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_no_alias(const value_type* __s, size_type __n);
2030
2031  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) {
2032    __null_terminate_at(std::__to_address(__get_pointer()), __pos);
2033  }
2034
2035    // __erase_external_with_move is invoked for erase() invocations where
2036    // `n ~= npos`, likely requiring memory moves on the string data.
2037    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __erase_external_with_move(size_type __pos, size_type __n);
2038
2039    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2040    void __copy_assign_alloc(const basic_string& __str)
2041        {__copy_assign_alloc(__str, integral_constant<bool,
2042                      __alloc_traits::propagate_on_container_copy_assignment::value>());}
2043
2044    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2045    void __copy_assign_alloc(const basic_string& __str, true_type)
2046        {
2047            if (__alloc() == __str.__alloc())
2048                __alloc() = __str.__alloc();
2049            else
2050            {
2051                if (!__str.__is_long())
2052                {
2053                    __clear_and_shrink();
2054                    __alloc() = __str.__alloc();
2055                }
2056                else
2057                {
2058                    __annotate_delete();
2059                    allocator_type __a = __str.__alloc();
2060                    auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
2061                    __begin_lifetime(__allocation.ptr, __allocation.count);
2062                    if (__is_long())
2063                        __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2064                    __alloc() = std::move(__a);
2065                    __set_long_pointer(__allocation.ptr);
2066                    __set_long_cap(__allocation.count);
2067                    __set_long_size(__str.size());
2068                    __annotate_new(__get_long_size());
2069                }
2070            }
2071        }
2072
2073    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2074    void __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT
2075        {}
2076
2077#ifndef _LIBCPP_CXX03_LANG
2078    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2079    void __move_assign(basic_string& __str, false_type)
2080        _NOEXCEPT_(__alloc_traits::is_always_equal::value);
2081    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
2082    void __move_assign(basic_string& __str, true_type)
2083#if _LIBCPP_STD_VER >= 17
2084        _NOEXCEPT;
2085#else
2086        _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
2087#endif
2088#endif
2089
2090    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2091    void
2092    __move_assign_alloc(basic_string& __str)
2093        _NOEXCEPT_(
2094            !__alloc_traits::propagate_on_container_move_assignment::value ||
2095            is_nothrow_move_assignable<allocator_type>::value)
2096    {__move_assign_alloc(__str, integral_constant<bool,
2097                      __alloc_traits::propagate_on_container_move_assignment::value>());}
2098
2099    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2100    void __move_assign_alloc(basic_string& __c, true_type)
2101        _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
2102        {
2103            __alloc() = std::move(__c.__alloc());
2104        }
2105
2106    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2107    void __move_assign_alloc(basic_string&, false_type)
2108        _NOEXCEPT
2109        {}
2110
2111    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s);
2112    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s, size_type __n);
2113
2114    // Assigns the value in __s, guaranteed to be __n < __min_cap in length.
2115    inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) {
2116      size_type __old_size = size();
2117      if (__n > __old_size)
2118        __annotate_increase(__n - __old_size);
2119      pointer __p = __is_long()
2120                        ? (__set_long_size(__n), __get_long_pointer())
2121                        : (__set_short_size(__n), __get_short_pointer());
2122      traits_type::move(std::__to_address(__p), __s, __n);
2123      traits_type::assign(__p[__n], value_type());
2124      if (__old_size > __n)
2125        __annotate_shrink(__old_size);
2126      return *this;
2127    }
2128
2129    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2130    basic_string& __null_terminate_at(value_type* __p, size_type __newsz) {
2131      size_type __old_size = size();
2132      if (__newsz > __old_size)
2133        __annotate_increase(__newsz - __old_size);
2134      __set_size(__newsz);
2135      traits_type::assign(__p[__newsz], value_type());
2136      if (__old_size > __newsz)
2137        __annotate_shrink(__old_size);
2138      return *this;
2139    }
2140
2141    template <class _Tp>
2142    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const {
2143      return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v));
2144    }
2145
2146    _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
2147    void __throw_length_error() const {
2148        std::__throw_length_error("basic_string");
2149    }
2150
2151    _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
2152    void __throw_out_of_range() const {
2153        std::__throw_out_of_range("basic_string");
2154    }
2155
2156    friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, const basic_string&);
2157    friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const value_type*, const basic_string&);
2158    friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(value_type, const basic_string&);
2159    friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, const value_type*);
2160    friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, value_type);
2161};
2162
2163// These declarations must appear before any functions are implicitly used
2164// so that they have the correct visibility specifier.
2165#define _LIBCPP_DECLARE(...) extern template __VA_ARGS__;
2166#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
2167    _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
2168#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2169        _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
2170#   endif
2171#else
2172    _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
2173#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2174        _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
2175#   endif
2176#endif
2177#undef _LIBCPP_DECLARE
2178
2179
2180#if _LIBCPP_STD_VER >= 17
2181template<class _InputIterator,
2182         class _CharT = __iter_value_type<_InputIterator>,
2183         class _Allocator = allocator<_CharT>,
2184         class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
2185         class = enable_if_t<__is_allocator<_Allocator>::value>
2186         >
2187basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
2188  -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
2189
2190template<class _CharT,
2191         class _Traits,
2192         class _Allocator = allocator<_CharT>,
2193         class = enable_if_t<__is_allocator<_Allocator>::value>
2194         >
2195explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
2196  -> basic_string<_CharT, _Traits, _Allocator>;
2197
2198template<class _CharT,
2199         class _Traits,
2200         class _Allocator = allocator<_CharT>,
2201         class = enable_if_t<__is_allocator<_Allocator>::value>,
2202         class _Sz = typename allocator_traits<_Allocator>::size_type
2203         >
2204basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator())
2205  -> basic_string<_CharT, _Traits, _Allocator>;
2206#endif
2207
2208#if _LIBCPP_STD_VER >= 23
2209template <ranges::input_range _Range,
2210          class _Allocator = allocator<ranges::range_value_t<_Range>>,
2211          class = enable_if_t<__is_allocator<_Allocator>::value>
2212          >
2213basic_string(from_range_t, _Range&&, _Allocator = _Allocator())
2214  -> basic_string<ranges::range_value_t<_Range>, char_traits<ranges::range_value_t<_Range>>, _Allocator>;
2215#endif
2216
2217template <class _CharT, class _Traits, class _Allocator>
2218_LIBCPP_CONSTEXPR_SINCE_CXX20
2219void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
2220                                                       size_type __sz,
2221                                                       size_type __reserve)
2222{
2223    if (__libcpp_is_constant_evaluated())
2224        __r_.first() = __rep();
2225    if (__reserve > max_size())
2226        __throw_length_error();
2227    pointer __p;
2228    if (__fits_in_sso(__reserve))
2229    {
2230        __set_short_size(__sz);
2231        __p = __get_short_pointer();
2232    }
2233    else
2234    {
2235        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1);
2236        __p = __allocation.ptr;
2237        __begin_lifetime(__p, __allocation.count);
2238        __set_long_pointer(__p);
2239        __set_long_cap(__allocation.count);
2240        __set_long_size(__sz);
2241    }
2242    traits_type::copy(std::__to_address(__p), __s, __sz);
2243    traits_type::assign(__p[__sz], value_type());
2244    __annotate_new(__sz);
2245}
2246
2247template <class _CharT, class _Traits, class _Allocator>
2248_LIBCPP_CONSTEXPR_SINCE_CXX20
2249void
2250basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
2251{
2252    if (__libcpp_is_constant_evaluated())
2253        __r_.first() = __rep();
2254    if (__sz > max_size())
2255        __throw_length_error();
2256    pointer __p;
2257    if (__fits_in_sso(__sz))
2258    {
2259        __set_short_size(__sz);
2260        __p = __get_short_pointer();
2261    }
2262    else
2263    {
2264        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
2265        __p = __allocation.ptr;
2266        __begin_lifetime(__p, __allocation.count);
2267        __set_long_pointer(__p);
2268        __set_long_cap(__allocation.count);
2269        __set_long_size(__sz);
2270    }
2271    traits_type::copy(std::__to_address(__p), __s, __sz);
2272    traits_type::assign(__p[__sz], value_type());
2273    __annotate_new(__sz);
2274}
2275
2276template <class _CharT, class _Traits, class _Allocator>
2277_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE
2278void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
2279    const value_type* __s, size_type __sz) {
2280  if (__libcpp_is_constant_evaluated())
2281    __r_.first() = __rep();
2282
2283  pointer __p;
2284  if (__fits_in_sso(__sz)) {
2285    __p = __get_short_pointer();
2286    __set_short_size(__sz);
2287  } else {
2288    if (__sz > max_size())
2289      __throw_length_error();
2290    auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
2291    __p = __allocation.ptr;
2292    __begin_lifetime(__p, __allocation.count);
2293    __set_long_pointer(__p);
2294    __set_long_cap(__allocation.count);
2295    __set_long_size(__sz);
2296  }
2297  traits_type::copy(std::__to_address(__p), __s, __sz + 1);
2298  __annotate_new(__sz);
2299}
2300
2301template <class _CharT, class _Traits, class _Allocator>
2302_LIBCPP_CONSTEXPR_SINCE_CXX20
2303void
2304basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
2305{
2306    if (__libcpp_is_constant_evaluated())
2307        __r_.first() = __rep();
2308
2309    if (__n > max_size())
2310        __throw_length_error();
2311    pointer __p;
2312    if (__fits_in_sso(__n))
2313    {
2314        __set_short_size(__n);
2315        __p = __get_short_pointer();
2316    }
2317    else
2318    {
2319        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1);
2320        __p = __allocation.ptr;
2321        __begin_lifetime(__p, __allocation.count);
2322        __set_long_pointer(__p);
2323        __set_long_cap(__allocation.count);
2324        __set_long_size(__n);
2325    }
2326    traits_type::assign(std::__to_address(__p), __n, __c);
2327    traits_type::assign(__p[__n], value_type());
2328    __annotate_new(__n);
2329}
2330
2331template <class _CharT, class _Traits, class _Allocator>
2332template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
2333_LIBCPP_CONSTEXPR_SINCE_CXX20
2334void basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last)
2335{
2336  __init_with_sentinel(std::move(__first), std::move(__last));
2337}
2338
2339template <class _CharT, class _Traits, class _Allocator>
2340template <class _InputIterator, class _Sentinel>
2341_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2342void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) {
2343    __r_.first() = __rep();
2344    __annotate_new(0);
2345
2346#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2347    try
2348    {
2349#endif // _LIBCPP_HAS_NO_EXCEPTIONS
2350    for (; __first != __last; ++__first)
2351        push_back(*__first);
2352#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2353    }
2354    catch (...)
2355    {
2356        __annotate_delete();
2357        if (__is_long())
2358            __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2359        throw;
2360    }
2361#endif // _LIBCPP_HAS_NO_EXCEPTIONS
2362}
2363
2364template <class _CharT, class _Traits, class _Allocator>
2365template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
2366_LIBCPP_CONSTEXPR_SINCE_CXX20 void
2367basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last)
2368{
2369  size_type __sz = static_cast<size_type>(std::distance(__first, __last));
2370  __init_with_size(__first, __last, __sz);
2371}
2372
2373template <class _CharT, class _Traits, class _Allocator>
2374template <class _InputIterator, class _Sentinel>
2375_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2376void basic_string<_CharT, _Traits, _Allocator>::__init_with_size(
2377    _InputIterator __first, _Sentinel __last, size_type __sz) {
2378    if (__libcpp_is_constant_evaluated())
2379        __r_.first() = __rep();
2380
2381    if (__sz > max_size())
2382        __throw_length_error();
2383
2384    pointer __p;
2385    if (__fits_in_sso(__sz))
2386    {
2387        __set_short_size(__sz);
2388        __p = __get_short_pointer();
2389
2390    }
2391    else
2392    {
2393        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
2394        __p = __allocation.ptr;
2395        __begin_lifetime(__p, __allocation.count);
2396        __set_long_pointer(__p);
2397        __set_long_cap(__allocation.count);
2398        __set_long_size(__sz);
2399    }
2400
2401#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2402    try
2403    {
2404#endif  // _LIBCPP_HAS_NO_EXCEPTIONS
2405    for (; __first != __last; ++__first, (void) ++__p)
2406        traits_type::assign(*__p, *__first);
2407    traits_type::assign(*__p, value_type());
2408#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2409    }
2410    catch (...)
2411    {
2412        if (__is_long())
2413            __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2414        throw;
2415    }
2416#endif  // _LIBCPP_HAS_NO_EXCEPTIONS
2417    __annotate_new(__sz);
2418}
2419
2420template <class _CharT, class _Traits, class _Allocator>
2421_LIBCPP_CONSTEXPR_SINCE_CXX20
2422void
2423basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
2424    (size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2425     size_type __n_copy,  size_type __n_del,     size_type __n_add, const value_type* __p_new_stuff)
2426{
2427    size_type __ms = max_size();
2428    if (__delta_cap > __ms - __old_cap - 1)
2429        __throw_length_error();
2430    pointer __old_p = __get_pointer();
2431    size_type __cap = __old_cap < __ms / 2 - __alignment ?
2432                          __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
2433                          __ms - 1;
2434    __annotate_delete();
2435    auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
2436    pointer __p = __allocation.ptr;
2437    __begin_lifetime(__p, __allocation.count);
2438    if (__n_copy != 0)
2439        traits_type::copy(std::__to_address(__p),
2440                          std::__to_address(__old_p), __n_copy);
2441    if (__n_add != 0)
2442        traits_type::copy(std::__to_address(__p) + __n_copy, __p_new_stuff, __n_add);
2443    size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
2444    if (__sec_cp_sz != 0)
2445        traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
2446                          std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
2447    if (__old_cap+1 != __min_cap)
2448        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
2449    __set_long_pointer(__p);
2450    __set_long_cap(__allocation.count);
2451    __old_sz = __n_copy + __n_add + __sec_cp_sz;
2452    __set_long_size(__old_sz);
2453    traits_type::assign(__p[__old_sz], value_type());
2454    __annotate_new(__old_cap + __delta_cap);
2455}
2456
2457// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
2458// may also not set the size at all when the string was short initially. This leads to unpredictable size value. It is
2459// not removed or changed to avoid breaking the ABI.
2460template <class _CharT, class _Traits, class _Allocator>
2461void
2462_LIBCPP_CONSTEXPR_SINCE_CXX20
2463#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1
2464    _LIBCPP_HIDE_FROM_ABI
2465#endif
2466    _LIBCPP_DEPRECATED_("use __grow_by_without_replace")
2467basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2468                                                     size_type __n_copy,  size_type __n_del,     size_type __n_add)
2469{
2470    size_type __ms = max_size();
2471    if (__delta_cap > __ms - __old_cap)
2472        __throw_length_error();
2473    pointer __old_p = __get_pointer();
2474    size_type __cap = __old_cap < __ms / 2 - __alignment ?
2475                          __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
2476                          __ms - 1;
2477    __annotate_delete();
2478    auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
2479    pointer __p = __allocation.ptr;
2480    __begin_lifetime(__p, __allocation.count);
2481    if (__n_copy != 0)
2482        traits_type::copy(std::__to_address(__p),
2483                          std::__to_address(__old_p), __n_copy);
2484    size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
2485    if (__sec_cp_sz != 0)
2486        traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
2487                          std::__to_address(__old_p) + __n_copy + __n_del,
2488                          __sec_cp_sz);
2489    if (__old_cap + 1 != __min_cap)
2490        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
2491    __set_long_pointer(__p);
2492    __set_long_cap(__allocation.count);
2493}
2494
2495template <class _CharT, class _Traits, class _Allocator>
2496void _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
2497basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
2498    size_type __old_cap,
2499    size_type __delta_cap,
2500    size_type __old_sz,
2501    size_type __n_copy,
2502    size_type __n_del,
2503    size_type __n_add) {
2504    _LIBCPP_SUPPRESS_DEPRECATED_PUSH
2505    __grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
2506    _LIBCPP_SUPPRESS_DEPRECATED_POP
2507    __set_long_size(__old_sz - __n_del + __n_add);
2508    __annotate_new(__old_sz - __n_del + __n_add);
2509}
2510
2511// assign
2512
2513template <class _CharT, class _Traits, class _Allocator>
2514template <bool __is_short>
2515_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE
2516basic_string<_CharT, _Traits, _Allocator>&
2517basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
2518    const value_type* __s, size_type __n) {
2519  size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
2520  if (__n < __cap) {
2521    size_type __old_size = __is_short ? __get_short_size() : __get_long_size();
2522    if (__n > __old_size)
2523      __annotate_increase(__n - __old_size);
2524    pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
2525    __is_short ? __set_short_size(__n) : __set_long_size(__n);
2526    traits_type::copy(std::__to_address(__p), __s, __n);
2527    traits_type::assign(__p[__n], value_type());
2528    if (__old_size > __n)
2529      __annotate_shrink(__old_size);
2530  } else {
2531    size_type __sz = __is_short ? __get_short_size() : __get_long_size();
2532    __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
2533  }
2534  return *this;
2535}
2536
2537template <class _CharT, class _Traits, class _Allocator>
2538_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE
2539basic_string<_CharT, _Traits, _Allocator>&
2540basic_string<_CharT, _Traits, _Allocator>::__assign_external(
2541    const value_type* __s, size_type __n) {
2542  size_type __cap = capacity();
2543  if (__cap >= __n) {
2544    size_type __old_size = size();
2545    if (__n > __old_size)
2546      __annotate_increase(__n - __old_size);
2547    value_type* __p = std::__to_address(__get_pointer());
2548    traits_type::move(__p, __s, __n);
2549    return __null_terminate_at(__p, __n);
2550  } else {
2551    size_type __sz = size();
2552    __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s);
2553    return *this;
2554  }
2555}
2556
2557template <class _CharT, class _Traits, class _Allocator>
2558_LIBCPP_CONSTEXPR_SINCE_CXX20
2559basic_string<_CharT, _Traits, _Allocator>&
2560basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
2561{
2562    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::assign received nullptr");
2563    return (__builtin_constant_p(__n) && __fits_in_sso(__n))
2564               ? __assign_short(__s, __n)
2565               : __assign_external(__s, __n);
2566}
2567
2568template <class _CharT, class _Traits, class _Allocator>
2569_LIBCPP_CONSTEXPR_SINCE_CXX20
2570basic_string<_CharT, _Traits, _Allocator>&
2571basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
2572{
2573    size_type __cap = capacity();
2574    size_type __old_size = size();
2575    if (__cap < __n)
2576    {
2577        size_type __sz = size();
2578        __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
2579        __annotate_increase(__n);
2580    }
2581    else if(__n > __old_size)
2582        __annotate_increase(__n - __old_size);
2583    value_type* __p = std::__to_address(__get_pointer());
2584    traits_type::assign(__p, __n, __c);
2585    return __null_terminate_at(__p, __n);
2586}
2587
2588template <class _CharT, class _Traits, class _Allocator>
2589_LIBCPP_CONSTEXPR_SINCE_CXX20
2590basic_string<_CharT, _Traits, _Allocator>&
2591basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c)
2592{
2593  pointer __p;
2594  size_type __old_size = size();
2595  if (__old_size == 0)
2596    __annotate_increase(1);
2597  if (__is_long()) {
2598    __p = __get_long_pointer();
2599    __set_long_size(1);
2600  } else {
2601    __p = __get_short_pointer();
2602    __set_short_size(1);
2603  }
2604  traits_type::assign(*__p, __c);
2605  traits_type::assign(*++__p, value_type());
2606  if (__old_size > 1)
2607    __annotate_shrink(__old_size);
2608  return *this;
2609}
2610
2611template <class _CharT, class _Traits, class _Allocator>
2612_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
2613basic_string<_CharT, _Traits, _Allocator>&
2614basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
2615{
2616  if (this != std::addressof(__str)) {
2617    __copy_assign_alloc(__str);
2618    if (!__is_long()) {
2619      if (!__str.__is_long()) {
2620        size_type __old_size = __get_short_size();
2621        if (__get_short_size() < __str.__get_short_size())
2622          __annotate_increase(__str.__get_short_size() - __get_short_size());
2623        __r_.first() = __str.__r_.first();
2624        if (__old_size > __get_short_size())
2625          __annotate_shrink(__old_size);
2626      } else {
2627        return __assign_no_alias<true>(__str.data(), __str.size());
2628      }
2629    } else {
2630      return __assign_no_alias<false>(__str.data(), __str.size());
2631    }
2632  }
2633  return *this;
2634}
2635
2636#ifndef _LIBCPP_CXX03_LANG
2637
2638template <class _CharT, class _Traits, class _Allocator>
2639inline _LIBCPP_CONSTEXPR_SINCE_CXX20
2640void
2641basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type)
2642    _NOEXCEPT_(__alloc_traits::is_always_equal::value)
2643{
2644    if (__alloc() != __str.__alloc())
2645        assign(__str);
2646    else
2647        __move_assign(__str, true_type());
2648}
2649
2650template <class _CharT, class _Traits, class _Allocator>
2651inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
2652void
2653basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
2654#if _LIBCPP_STD_VER >= 17
2655    _NOEXCEPT
2656#else
2657    _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
2658#endif
2659{
2660  __annotate_delete();
2661  if (__is_long()) {
2662    __alloc_traits::deallocate(__alloc(), __get_long_pointer(),
2663                               __get_long_cap());
2664#if _LIBCPP_STD_VER <= 14
2665    if (!is_nothrow_move_assignable<allocator_type>::value) {
2666      __set_short_size(0);
2667      traits_type::assign(__get_short_pointer()[0], value_type());
2668      __annotate_new(0);
2669    }
2670#endif
2671  }
2672  size_type __str_old_size = __str.size();
2673  bool __str_was_short   = !__str.__is_long();
2674
2675  __move_assign_alloc(__str);
2676  __r_.first() = __str.__r_.first();
2677  __str.__set_short_size(0);
2678  traits_type::assign(__str.__get_short_pointer()[0], value_type());
2679
2680  if (__str_was_short && this != &__str)
2681    __str.__annotate_shrink(__str_old_size);
2682  else
2683    // ASan annotations: was long, so object memory is unpoisoned as new.
2684    // Or is same as *this, and __annotate_delete() was called.
2685    __str.__annotate_new(0);
2686
2687  // ASan annotations: Guard against `std::string s; s = std::move(s);`
2688  // You can find more here: https://en.cppreference.com/w/cpp/utility/move
2689  // Quote: "Unless otherwise specified, all standard library objects that have been moved
2690  // from are placed in a "valid but unspecified state", meaning the object's class
2691  // invariants hold (so functions without preconditions, such as the assignment operator,
2692  // can be safely used on the object after it was moved from):"
2693  // Quote: "v = std::move(v); // the value of v is unspecified"
2694  if (!__is_long() && &__str != this)
2695    // If it is long string, delete was never called on original __str's buffer.
2696    __annotate_new(__get_short_size());
2697}
2698
2699#endif
2700
2701template <class _CharT, class _Traits, class _Allocator>
2702template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
2703_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
2704basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
2705{
2706  __assign_with_sentinel(__first, __last);
2707  return *this;
2708}
2709
2710template <class _CharT, class _Traits, class _Allocator>
2711template <class _InputIterator, class _Sentinel>
2712_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2713void
2714basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator __first, _Sentinel __last) {
2715  const basic_string __temp(__init_with_sentinel_tag(), std::move(__first), std::move(__last), __alloc());
2716  assign(__temp.data(), __temp.size());
2717}
2718
2719template <class _CharT, class _Traits, class _Allocator>
2720template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
2721_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
2722basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
2723{
2724  if (__string_is_trivial_iterator<_ForwardIterator>::value) {
2725    size_type __n = static_cast<size_type>(std::distance(__first, __last));
2726    __assign_trivial(__first, __last, __n);
2727  } else {
2728    __assign_with_sentinel(__first, __last);
2729  }
2730
2731  return *this;
2732}
2733
2734template <class _CharT, class _Traits, class _Allocator>
2735template <class _Iterator, class _Sentinel>
2736_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
2737void
2738basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) {
2739  _LIBCPP_ASSERT_INTERNAL(
2740      __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial");
2741
2742  size_type __old_size = size();
2743  size_type __cap = capacity();
2744  if (__cap < __n) {
2745    // Unlike `append` functions, if the input range points into the string itself, there is no case that the input
2746    // range could get invalidated by reallocation:
2747    // 1. If the input range is a subset of the string itself, its size cannot exceed the capacity of the string,
2748    //    thus no reallocation would happen.
2749    // 2. In the exotic case where the input range is the byte representation of the string itself, the string
2750    //    object itself stays valid even if reallocation happens.
2751    size_type __sz = size();
2752    __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
2753    __annotate_increase(__n);
2754    }
2755    else if (__n > __old_size)
2756        __annotate_increase(__n - __old_size);
2757    pointer __p = __get_pointer();
2758    for (; __first != __last; ++__p, (void) ++__first)
2759        traits_type::assign(*__p, *__first);
2760    traits_type::assign(*__p, value_type());
2761    __set_size(__n);
2762    if (__n < __old_size)
2763        __annotate_shrink(__old_size);
2764}
2765
2766template <class _CharT, class _Traits, class _Allocator>
2767_LIBCPP_CONSTEXPR_SINCE_CXX20
2768basic_string<_CharT, _Traits, _Allocator>&
2769basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n)
2770{
2771    size_type __sz = __str.size();
2772    if (__pos > __sz)
2773        __throw_out_of_range();
2774    return assign(__str.data() + __pos, std::min(__n, __sz - __pos));
2775}
2776
2777template <class _CharT, class _Traits, class _Allocator>
2778template <class _Tp,
2779          __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
2780                            !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
2781                        int> >
2782_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
2783basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) {
2784    __self_view __sv = __t;
2785    size_type __sz = __sv.size();
2786    if (__pos > __sz)
2787        __throw_out_of_range();
2788    return assign(__sv.data() + __pos, std::min(__n, __sz - __pos));
2789}
2790
2791template <class _CharT, class _Traits, class _Allocator>
2792_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE
2793basic_string<_CharT, _Traits, _Allocator>&
2794basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) {
2795  return __assign_external(__s, traits_type::length(__s));
2796}
2797
2798template <class _CharT, class _Traits, class _Allocator>
2799_LIBCPP_CONSTEXPR_SINCE_CXX20
2800basic_string<_CharT, _Traits, _Allocator>&
2801basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s)
2802{
2803    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr");
2804    return __builtin_constant_p(*__s)
2805               ? (__fits_in_sso(traits_type::length(__s))
2806                      ? __assign_short(__s, traits_type::length(__s))
2807                      : __assign_external(__s, traits_type::length(__s)))
2808               : __assign_external(__s);
2809}
2810// append
2811
2812template <class _CharT, class _Traits, class _Allocator>
2813_LIBCPP_CONSTEXPR_SINCE_CXX20
2814basic_string<_CharT, _Traits, _Allocator>&
2815basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n)
2816{
2817    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::append received nullptr");
2818    size_type __cap = capacity();
2819    size_type __sz = size();
2820    if (__cap - __sz >= __n)
2821    {
2822        if (__n)
2823        {
2824            __annotate_increase(__n);
2825            value_type* __p = std::__to_address(__get_pointer());
2826            traits_type::copy(__p + __sz, __s, __n);
2827            __sz += __n;
2828            __set_size(__sz);
2829            traits_type::assign(__p[__sz], value_type());
2830        }
2831    }
2832    else
2833        __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s);
2834    return *this;
2835}
2836
2837template <class _CharT, class _Traits, class _Allocator>
2838_LIBCPP_CONSTEXPR_SINCE_CXX20
2839basic_string<_CharT, _Traits, _Allocator>&
2840basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c)
2841{
2842    if (__n)
2843    {
2844        size_type __cap = capacity();
2845        size_type __sz = size();
2846        if (__cap - __sz < __n)
2847            __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
2848        __annotate_increase(__n);
2849        pointer __p = __get_pointer();
2850        traits_type::assign(std::__to_address(__p) + __sz, __n, __c);
2851        __sz += __n;
2852        __set_size(__sz);
2853        traits_type::assign(__p[__sz], value_type());
2854    }
2855    return *this;
2856}
2857
2858template <class _CharT, class _Traits, class _Allocator>
2859_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
2860basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n)
2861{
2862    if (__n)
2863    {
2864        size_type __cap = capacity();
2865        size_type __sz = size();
2866        if (__cap - __sz < __n)
2867            __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
2868        __annotate_increase(__n);
2869        pointer __p = __get_pointer();
2870        __sz += __n;
2871        __set_size(__sz);
2872        traits_type::assign(__p[__sz], value_type());
2873    }
2874}
2875
2876template <class _CharT, class _Traits, class _Allocator>
2877_LIBCPP_CONSTEXPR_SINCE_CXX20
2878void
2879basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
2880{
2881    bool __is_short = !__is_long();
2882    size_type __cap;
2883    size_type __sz;
2884    if (__is_short)
2885    {
2886        __cap = __min_cap - 1;
2887        __sz = __get_short_size();
2888    }
2889    else
2890    {
2891        __cap = __get_long_cap() - 1;
2892        __sz = __get_long_size();
2893    }
2894    if (__sz == __cap)
2895    {
2896        __grow_by_without_replace(__cap, 1, __sz, __sz, 0);
2897        __annotate_increase(1);
2898        __is_short = false; // the string is always long after __grow_by
2899    } else
2900        __annotate_increase(1);
2901    pointer __p = __get_pointer();
2902    if (__is_short)
2903    {
2904        __p = __get_short_pointer() + __sz;
2905        __set_short_size(__sz+1);
2906    }
2907    else
2908    {
2909        __p = __get_long_pointer() + __sz;
2910        __set_long_size(__sz+1);
2911    }
2912    traits_type::assign(*__p, __c);
2913    traits_type::assign(*++__p, value_type());
2914}
2915
2916template <class _CharT, class _Traits, class _Allocator>
2917template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
2918_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
2919basic_string<_CharT, _Traits, _Allocator>::append(
2920    _ForwardIterator __first, _ForwardIterator __last)
2921{
2922    size_type __sz = size();
2923    size_type __cap = capacity();
2924    size_type __n = static_cast<size_type>(std::distance(__first, __last));
2925    if (__n)
2926    {
2927        if (__string_is_trivial_iterator<_ForwardIterator>::value &&
2928            !__addr_in_range(*__first))
2929        {
2930            if (__cap - __sz < __n)
2931              __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
2932            __annotate_increase(__n);
2933            pointer __p = __get_pointer() + __sz;
2934            for (; __first != __last; ++__p, (void) ++__first)
2935                traits_type::assign(*__p, *__first);
2936            traits_type::assign(*__p, value_type());
2937            __set_size(__sz + __n);
2938        }
2939        else
2940        {
2941            const basic_string __temp(__first, __last, __alloc());
2942            append(__temp.data(), __temp.size());
2943        }
2944    }
2945    return *this;
2946}
2947
2948template <class _CharT, class _Traits, class _Allocator>
2949_LIBCPP_CONSTEXPR_SINCE_CXX20
2950basic_string<_CharT, _Traits, _Allocator>&
2951basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n)
2952{
2953    size_type __sz = __str.size();
2954    if (__pos > __sz)
2955        __throw_out_of_range();
2956    return append(__str.data() + __pos, std::min(__n, __sz - __pos));
2957}
2958
2959template <class _CharT, class _Traits, class _Allocator>
2960template <class _Tp,
2961          __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
2962                            !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
2963                        int> >
2964_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
2965basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) {
2966    __self_view __sv = __t;
2967    size_type __sz = __sv.size();
2968    if (__pos > __sz)
2969        __throw_out_of_range();
2970    return append(__sv.data() + __pos, std::min(__n, __sz - __pos));
2971}
2972
2973template <class _CharT, class _Traits, class _Allocator>
2974_LIBCPP_CONSTEXPR_SINCE_CXX20
2975basic_string<_CharT, _Traits, _Allocator>&
2976basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s)
2977{
2978    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::append received nullptr");
2979    return append(__s, traits_type::length(__s));
2980}
2981
2982// insert
2983
2984template <class _CharT, class _Traits, class _Allocator>
2985_LIBCPP_CONSTEXPR_SINCE_CXX20
2986basic_string<_CharT, _Traits, _Allocator>&
2987basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n)
2988{
2989    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::insert received nullptr");
2990    size_type __sz = size();
2991    if (__pos > __sz)
2992        __throw_out_of_range();
2993    size_type __cap = capacity();
2994    if (__cap - __sz >= __n)
2995    {
2996        if (__n)
2997        {
2998            __annotate_increase(__n);
2999            value_type* __p = std::__to_address(__get_pointer());
3000            size_type __n_move = __sz - __pos;
3001            if (__n_move != 0)
3002            {
3003                if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s))
3004                    __s += __n;
3005                traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
3006            }
3007            traits_type::move(__p + __pos, __s, __n);
3008            __sz += __n;
3009            __set_size(__sz);
3010            traits_type::assign(__p[__sz], value_type());
3011        }
3012    }
3013    else
3014        __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
3015    return *this;
3016}
3017
3018template <class _CharT, class _Traits, class _Allocator>
3019_LIBCPP_CONSTEXPR_SINCE_CXX20
3020basic_string<_CharT, _Traits, _Allocator>&
3021basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c)
3022{
3023    size_type __sz = size();
3024    if (__pos > __sz)
3025        __throw_out_of_range();
3026    if (__n)
3027    {
3028        size_type __cap = capacity();
3029        value_type* __p;
3030        if (__cap - __sz >= __n)
3031        {
3032            __annotate_increase(__n);
3033            __p = std::__to_address(__get_pointer());
3034            size_type __n_move = __sz - __pos;
3035            if (__n_move != 0)
3036                traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
3037        }
3038        else
3039        {
3040            __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n);
3041            __p = std::__to_address(__get_long_pointer());
3042        }
3043        traits_type::assign(__p + __pos, __n, __c);
3044        __sz += __n;
3045        __set_size(__sz);
3046        traits_type::assign(__p[__sz], value_type());
3047    }
3048    return *this;
3049}
3050
3051template <class _CharT, class _Traits, class _Allocator>
3052template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
3053_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
3054basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last)
3055{
3056  const basic_string __temp(__first, __last, __alloc());
3057  return insert(__pos, __temp.data(), __temp.data() + __temp.size());
3058}
3059
3060template <class _CharT, class _Traits, class _Allocator>
3061template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
3062_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
3063basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last)
3064{
3065    auto __n = static_cast<size_type>(std::distance(__first, __last));
3066    return __insert_with_size(__pos, __first, __last, __n);
3067}
3068
3069template <class _CharT, class _Traits, class _Allocator>
3070template<class _Iterator, class _Sentinel>
3071_LIBCPP_CONSTEXPR_SINCE_CXX20
3072typename basic_string<_CharT, _Traits, _Allocator>::iterator
3073basic_string<_CharT, _Traits, _Allocator>::__insert_with_size(
3074    const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n) {
3075    size_type __ip = static_cast<size_type>(__pos - begin());
3076    if (__n == 0)
3077        return begin() + __ip;
3078
3079    if (__string_is_trivial_iterator<_Iterator>::value && !__addr_in_range(*__first))
3080    {
3081        return __insert_from_safe_copy(__n, __ip, __first, __last);
3082    }
3083    else
3084    {
3085        const basic_string __temp(__init_with_sentinel_tag(), __first, __last, __alloc());
3086        return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end());
3087    }
3088}
3089
3090template <class _CharT, class _Traits, class _Allocator>
3091_LIBCPP_CONSTEXPR_SINCE_CXX20
3092basic_string<_CharT, _Traits, _Allocator>&
3093basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str,
3094                                                  size_type __pos2, size_type __n)
3095{
3096    size_type __str_sz = __str.size();
3097    if (__pos2 > __str_sz)
3098        __throw_out_of_range();
3099    return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2));
3100}
3101
3102template <class _CharT, class _Traits, class _Allocator>
3103template <class _Tp,
3104          __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
3105                            !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
3106                        int> >
3107_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
3108basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) {
3109    __self_view __sv = __t;
3110    size_type __str_sz = __sv.size();
3111    if (__pos2 > __str_sz)
3112        __throw_out_of_range();
3113    return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2));
3114}
3115
3116template <class _CharT, class _Traits, class _Allocator>
3117_LIBCPP_CONSTEXPR_SINCE_CXX20
3118basic_string<_CharT, _Traits, _Allocator>&
3119basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s)
3120{
3121    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::insert received nullptr");
3122    return insert(__pos, __s, traits_type::length(__s));
3123}
3124
3125template <class _CharT, class _Traits, class _Allocator>
3126_LIBCPP_CONSTEXPR_SINCE_CXX20
3127typename basic_string<_CharT, _Traits, _Allocator>::iterator
3128basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c)
3129{
3130    size_type __ip = static_cast<size_type>(__pos - begin());
3131    size_type __sz = size();
3132    size_type __cap = capacity();
3133    value_type* __p;
3134    if (__cap == __sz)
3135    {
3136        __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1);
3137        __p = std::__to_address(__get_long_pointer());
3138    }
3139    else
3140    {
3141        __annotate_increase(1);
3142        __p = std::__to_address(__get_pointer());
3143        size_type __n_move = __sz - __ip;
3144        if (__n_move != 0)
3145            traits_type::move(__p + __ip + 1, __p + __ip, __n_move);
3146    }
3147    traits_type::assign(__p[__ip], __c);
3148    traits_type::assign(__p[++__sz], value_type());
3149    __set_size(__sz);
3150    return begin() + static_cast<difference_type>(__ip);
3151}
3152
3153// replace
3154
3155template <class _CharT, class _Traits, class _Allocator>
3156_LIBCPP_CONSTEXPR_SINCE_CXX20
3157basic_string<_CharT, _Traits, _Allocator>&
3158basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2)
3159    _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
3160{
3161    _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::replace received nullptr");
3162    size_type __sz = size();
3163    if (__pos > __sz)
3164        __throw_out_of_range();
3165    __n1 = std::min(__n1, __sz - __pos);
3166    size_type __cap = capacity();
3167    if (__cap - __sz + __n1 >= __n2)
3168    {
3169        value_type* __p = std::__to_address(__get_pointer());
3170        if (__n1 != __n2)
3171        {
3172            if (__n2 > __n1)
3173                __annotate_increase(__n2 - __n1);
3174            size_type __n_move = __sz - __pos - __n1;
3175            if (__n_move != 0)
3176            {
3177                if (__n1 > __n2)
3178                {
3179                    traits_type::move(__p + __pos, __s, __n2);
3180                    traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3181                    return __null_terminate_at(__p, __sz + (__n2 - __n1));
3182                }
3183                if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s))
3184                {
3185                    if (__p + __pos + __n1 <= __s)
3186                        __s += __n2 - __n1;
3187                    else // __p + __pos < __s < __p + __pos + __n1
3188                    {
3189                        traits_type::move(__p + __pos, __s, __n1);
3190                        __pos += __n1;
3191                        __s += __n2;
3192                        __n2 -= __n1;
3193                        __n1 = 0;
3194                    }
3195                }
3196                traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3197            }
3198        }
3199        traits_type::move(__p + __pos, __s, __n2);
3200        return __null_terminate_at(__p, __sz + (__n2 - __n1));
3201    }
3202    else
3203        __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s);
3204    return *this;
3205}
3206
3207template <class _CharT, class _Traits, class _Allocator>
3208_LIBCPP_CONSTEXPR_SINCE_CXX20
3209basic_string<_CharT, _Traits, _Allocator>&
3210basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c)
3211{
3212    size_type __sz = size();
3213    if (__pos > __sz)
3214        __throw_out_of_range();
3215    __n1 = std::min(__n1, __sz - __pos);
3216    size_type __cap = capacity();
3217    value_type* __p;
3218    if (__cap - __sz + __n1 >= __n2) {
3219      __p = std::__to_address(__get_pointer());
3220      if (__n1 != __n2) {
3221        if (__n2 > __n1)
3222          __annotate_increase(__n2 - __n1);
3223        size_type __n_move = __sz - __pos - __n1;
3224        if (__n_move != 0)
3225          traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3226      }
3227    } else {
3228      __grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2);
3229      __p = std::__to_address(__get_long_pointer());
3230    }
3231    traits_type::assign(__p + __pos, __n2, __c);
3232    return __null_terminate_at(__p, __sz - (__n1 - __n2));
3233}
3234
3235template <class _CharT, class _Traits, class _Allocator>
3236template<class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> >
3237_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
3238basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,
3239                                                   _InputIterator __j1, _InputIterator __j2)
3240{
3241    const basic_string __temp(__j1, __j2, __alloc());
3242    return replace(__i1, __i2, __temp);
3243}
3244
3245template <class _CharT, class _Traits, class _Allocator>
3246_LIBCPP_CONSTEXPR_SINCE_CXX20
3247basic_string<_CharT, _Traits, _Allocator>&
3248basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str,
3249                                                   size_type __pos2, size_type __n2)
3250{
3251    size_type __str_sz = __str.size();
3252    if (__pos2 > __str_sz)
3253        __throw_out_of_range();
3254    return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2));
3255}
3256
3257template <class _CharT, class _Traits, class _Allocator>
3258template <class _Tp,
3259          __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
3260                            !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
3261                        int> >
3262_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
3263basic_string<_CharT, _Traits, _Allocator>::replace(
3264    size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) {
3265    __self_view __sv = __t;
3266    size_type __str_sz = __sv.size();
3267    if (__pos2 > __str_sz)
3268        __throw_out_of_range();
3269    return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2));
3270}
3271
3272template <class _CharT, class _Traits, class _Allocator>
3273_LIBCPP_CONSTEXPR_SINCE_CXX20
3274basic_string<_CharT, _Traits, _Allocator>&
3275basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s)
3276{
3277    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::replace received nullptr");
3278    return replace(__pos, __n1, __s, traits_type::length(__s));
3279}
3280
3281// erase
3282
3283// 'externally instantiated' erase() implementation, called when __n != npos.
3284// Does not check __pos against size()
3285template <class _CharT, class _Traits, class _Allocator>
3286_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE
3287void
3288basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(
3289    size_type __pos, size_type __n)
3290{
3291    if (__n)
3292    {
3293        size_type __sz = size();
3294        value_type* __p = std::__to_address(__get_pointer());
3295        __n = std::min(__n, __sz - __pos);
3296        size_type __n_move = __sz - __pos - __n;
3297        if (__n_move != 0)
3298            traits_type::move(__p + __pos, __p + __pos + __n, __n_move);
3299        __null_terminate_at(__p, __sz - __n);
3300    }
3301}
3302
3303template <class _CharT, class _Traits, class _Allocator>
3304_LIBCPP_CONSTEXPR_SINCE_CXX20
3305basic_string<_CharT, _Traits, _Allocator>&
3306basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos,
3307                                                 size_type __n) {
3308  if (__pos > size())
3309    __throw_out_of_range();
3310  if (__n == npos) {
3311    __erase_to_end(__pos);
3312  } else {
3313    __erase_external_with_move(__pos, __n);
3314  }
3315  return *this;
3316}
3317
3318template <class _CharT, class _Traits, class _Allocator>
3319inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3320typename basic_string<_CharT, _Traits, _Allocator>::iterator
3321basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos)
3322{
3323  _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
3324      __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator");
3325  iterator __b = begin();
3326  size_type __r = static_cast<size_type>(__pos - __b);
3327  erase(__r, 1);
3328  return __b + static_cast<difference_type>(__r);
3329}
3330
3331template <class _CharT, class _Traits, class _Allocator>
3332inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3333typename basic_string<_CharT, _Traits, _Allocator>::iterator
3334basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last)
3335{
3336  _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range");
3337  iterator __b = begin();
3338  size_type __r = static_cast<size_type>(__first - __b);
3339  erase(__r, static_cast<size_type>(__last - __first));
3340  return __b + static_cast<difference_type>(__r);
3341}
3342
3343template <class _CharT, class _Traits, class _Allocator>
3344inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3345void
3346basic_string<_CharT, _Traits, _Allocator>::pop_back()
3347{
3348    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
3349    __erase_to_end(size() - 1);
3350}
3351
3352template <class _CharT, class _Traits, class _Allocator>
3353inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3354void
3355basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT
3356{
3357    size_type __old_size = size();
3358    if (__is_long())
3359    {
3360        traits_type::assign(*__get_long_pointer(), value_type());
3361        __set_long_size(0);
3362    }
3363    else
3364    {
3365        traits_type::assign(*__get_short_pointer(), value_type());
3366        __set_short_size(0);
3367    }
3368    __annotate_shrink(__old_size);
3369}
3370
3371template <class _CharT, class _Traits, class _Allocator>
3372_LIBCPP_CONSTEXPR_SINCE_CXX20
3373void
3374basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c)
3375{
3376    size_type __sz = size();
3377    if (__n > __sz)
3378        append(__n - __sz, __c);
3379    else
3380        __erase_to_end(__n);
3381}
3382
3383template <class _CharT, class _Traits, class _Allocator>
3384_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
3385basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n)
3386{
3387    size_type __sz = size();
3388    if (__n > __sz) {
3389       __append_default_init(__n - __sz);
3390    } else
3391        __erase_to_end(__n);
3392}
3393
3394template <class _CharT, class _Traits, class _Allocator>
3395_LIBCPP_CONSTEXPR_SINCE_CXX20
3396void
3397basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity)
3398{
3399    if (__requested_capacity > max_size())
3400        __throw_length_error();
3401
3402    // Make sure reserve(n) never shrinks. This is technically only required in C++20
3403    // and later (since P0966R1), however we provide consistent behavior in all Standard
3404    // modes because this function is instantiated in the shared library.
3405    if (__requested_capacity <= capacity())
3406        return;
3407
3408    size_type __target_capacity = std::max(__requested_capacity, size());
3409    __target_capacity = __recommend(__target_capacity);
3410    if (__target_capacity == capacity()) return;
3411
3412    __shrink_or_extend(__target_capacity);
3413}
3414
3415template <class _CharT, class _Traits, class _Allocator>
3416inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3417void
3418basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT
3419{
3420    size_type __target_capacity = __recommend(size());
3421    if (__target_capacity == capacity()) return;
3422
3423    __shrink_or_extend(__target_capacity);
3424}
3425
3426template <class _CharT, class _Traits, class _Allocator>
3427inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3428void
3429basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity)
3430{
3431    __annotate_delete();
3432    size_type __cap = capacity();
3433    size_type __sz = size();
3434
3435    pointer __new_data, __p;
3436    bool __was_long, __now_long;
3437    if (__fits_in_sso(__target_capacity))
3438    {
3439        __was_long = true;
3440        __now_long = false;
3441        __new_data = __get_short_pointer();
3442        __p = __get_long_pointer();
3443    }
3444    else
3445    {
3446        if (__target_capacity > __cap) {
3447            auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
3448            __new_data = __allocation.ptr;
3449            __target_capacity = __allocation.count - 1;
3450        }
3451        else
3452        {
3453        #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
3454            try
3455            {
3456        #endif // _LIBCPP_HAS_NO_EXCEPTIONS
3457                auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
3458                __new_data = __allocation.ptr;
3459                __target_capacity = __allocation.count - 1;
3460        #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
3461            }
3462            catch (...)
3463            {
3464                return;
3465            }
3466        #else  // _LIBCPP_HAS_NO_EXCEPTIONS
3467            if (__new_data == nullptr)
3468                return;
3469        #endif // _LIBCPP_HAS_NO_EXCEPTIONS
3470        }
3471        __begin_lifetime(__new_data, __target_capacity + 1);
3472        __now_long = true;
3473        __was_long = __is_long();
3474        __p = __get_pointer();
3475    }
3476    traits_type::copy(std::__to_address(__new_data),
3477                      std::__to_address(__p), size()+1);
3478    if (__was_long)
3479        __alloc_traits::deallocate(__alloc(), __p, __cap+1);
3480    if (__now_long)
3481    {
3482        __set_long_cap(__target_capacity+1);
3483        __set_long_size(__sz);
3484        __set_long_pointer(__new_data);
3485    }
3486    else
3487        __set_short_size(__sz);
3488    __annotate_new(__sz);
3489}
3490
3491template <class _CharT, class _Traits, class _Allocator>
3492_LIBCPP_CONSTEXPR_SINCE_CXX20
3493typename basic_string<_CharT, _Traits, _Allocator>::const_reference
3494basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
3495{
3496    if (__n >= size())
3497        __throw_out_of_range();
3498    return (*this)[__n];
3499}
3500
3501template <class _CharT, class _Traits, class _Allocator>
3502_LIBCPP_CONSTEXPR_SINCE_CXX20
3503typename basic_string<_CharT, _Traits, _Allocator>::reference
3504basic_string<_CharT, _Traits, _Allocator>::at(size_type __n)
3505{
3506    if (__n >= size())
3507        __throw_out_of_range();
3508    return (*this)[__n];
3509}
3510
3511template <class _CharT, class _Traits, class _Allocator>
3512_LIBCPP_CONSTEXPR_SINCE_CXX20
3513typename basic_string<_CharT, _Traits, _Allocator>::size_type
3514basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const
3515{
3516    size_type __sz = size();
3517    if (__pos > __sz)
3518        __throw_out_of_range();
3519    size_type __rlen = std::min(__n, __sz - __pos);
3520    traits_type::copy(__s, data() + __pos, __rlen);
3521    return __rlen;
3522}
3523
3524template <class _CharT, class _Traits, class _Allocator>
3525inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3526void
3527basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
3528#if _LIBCPP_STD_VER >= 14
3529        _NOEXCEPT
3530#else
3531        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
3532                    __is_nothrow_swappable<allocator_type>::value)
3533#endif
3534{
3535    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
3536        __alloc_traits::propagate_on_container_swap::value ||
3537        __alloc_traits::is_always_equal::value ||
3538        __alloc() == __str.__alloc(), "swapping non-equal allocators");
3539    if (!__is_long())
3540      __annotate_delete();
3541    if (this != &__str && !__str.__is_long())
3542      __str.__annotate_delete();
3543    std::swap(__r_.first(), __str.__r_.first());
3544    std::__swap_allocator(__alloc(), __str.__alloc());
3545    if (!__is_long())
3546      __annotate_new(__get_short_size());
3547    if (this != &__str && !__str.__is_long())
3548      __str.__annotate_new(__str.__get_short_size());
3549}
3550
3551// find
3552
3553template <class _Traits>
3554struct _LIBCPP_HIDDEN __traits_eq
3555{
3556    typedef typename _Traits::char_type char_type;
3557    _LIBCPP_HIDE_FROM_ABI
3558    bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT
3559        {return _Traits::eq(__x, __y);}
3560};
3561
3562template<class _CharT, class _Traits, class _Allocator>
3563_LIBCPP_CONSTEXPR_SINCE_CXX20
3564typename basic_string<_CharT, _Traits, _Allocator>::size_type
3565basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
3566                                                size_type __pos,
3567                                                size_type __n) const _NOEXCEPT
3568{
3569    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr");
3570    return std::__str_find<value_type, size_type, traits_type, npos>
3571        (data(), size(), __s, __pos, __n);
3572}
3573
3574template<class _CharT, class _Traits, class _Allocator>
3575inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3576typename basic_string<_CharT, _Traits, _Allocator>::size_type
3577basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str,
3578                                                size_type __pos) const _NOEXCEPT
3579{
3580    return std::__str_find<value_type, size_type, traits_type, npos>
3581        (data(), size(), __str.data(), __pos, __str.size());
3582}
3583
3584template<class _CharT, class _Traits, class _Allocator>
3585template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3586_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3587basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t,
3588                                                size_type __pos) const _NOEXCEPT
3589{
3590    __self_view __sv = __t;
3591    return std::__str_find<value_type, size_type, traits_type, npos>
3592        (data(), size(), __sv.data(), __pos, __sv.size());
3593}
3594
3595template<class _CharT, class _Traits, class _Allocator>
3596inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3597typename basic_string<_CharT, _Traits, _Allocator>::size_type
3598basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
3599                                                size_type __pos) const _NOEXCEPT
3600{
3601    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find(): received nullptr");
3602    return std::__str_find<value_type, size_type, traits_type, npos>
3603        (data(), size(), __s, __pos, traits_type::length(__s));
3604}
3605
3606template<class _CharT, class _Traits, class _Allocator>
3607_LIBCPP_CONSTEXPR_SINCE_CXX20
3608typename basic_string<_CharT, _Traits, _Allocator>::size_type
3609basic_string<_CharT, _Traits, _Allocator>::find(value_type __c,
3610                                                size_type __pos) const _NOEXCEPT
3611{
3612    return std::__str_find<value_type, size_type, traits_type, npos>
3613        (data(), size(), __c, __pos);
3614}
3615
3616// rfind
3617
3618template<class _CharT, class _Traits, class _Allocator>
3619_LIBCPP_CONSTEXPR_SINCE_CXX20
3620typename basic_string<_CharT, _Traits, _Allocator>::size_type
3621basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
3622                                                 size_type __pos,
3623                                                 size_type __n) const _NOEXCEPT
3624{
3625    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr");
3626    return std::__str_rfind<value_type, size_type, traits_type, npos>
3627        (data(), size(), __s, __pos, __n);
3628}
3629
3630template<class _CharT, class _Traits, class _Allocator>
3631inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3632typename basic_string<_CharT, _Traits, _Allocator>::size_type
3633basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str,
3634                                                 size_type __pos) const _NOEXCEPT
3635{
3636    return std::__str_rfind<value_type, size_type, traits_type, npos>
3637        (data(), size(), __str.data(), __pos, __str.size());
3638}
3639
3640template<class _CharT, class _Traits, class _Allocator>
3641template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3642_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3643basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t,
3644                                                size_type __pos) const _NOEXCEPT
3645{
3646    __self_view __sv = __t;
3647    return std::__str_rfind<value_type, size_type, traits_type, npos>
3648        (data(), size(), __sv.data(), __pos, __sv.size());
3649}
3650
3651template<class _CharT, class _Traits, class _Allocator>
3652inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3653typename basic_string<_CharT, _Traits, _Allocator>::size_type
3654basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
3655                                                 size_type __pos) const _NOEXCEPT
3656{
3657    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::rfind(): received nullptr");
3658    return std::__str_rfind<value_type, size_type, traits_type, npos>
3659        (data(), size(), __s, __pos, traits_type::length(__s));
3660}
3661
3662template<class _CharT, class _Traits, class _Allocator>
3663_LIBCPP_CONSTEXPR_SINCE_CXX20
3664typename basic_string<_CharT, _Traits, _Allocator>::size_type
3665basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c,
3666                                                 size_type __pos) const _NOEXCEPT
3667{
3668    return std::__str_rfind<value_type, size_type, traits_type, npos>
3669        (data(), size(), __c, __pos);
3670}
3671
3672// find_first_of
3673
3674template<class _CharT, class _Traits, class _Allocator>
3675_LIBCPP_CONSTEXPR_SINCE_CXX20
3676typename basic_string<_CharT, _Traits, _Allocator>::size_type
3677basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
3678                                                         size_type __pos,
3679                                                         size_type __n) const _NOEXCEPT
3680{
3681    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr");
3682    return std::__str_find_first_of<value_type, size_type, traits_type, npos>
3683        (data(), size(), __s, __pos, __n);
3684}
3685
3686template<class _CharT, class _Traits, class _Allocator>
3687inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3688typename basic_string<_CharT, _Traits, _Allocator>::size_type
3689basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str,
3690                                                         size_type __pos) const _NOEXCEPT
3691{
3692    return std::__str_find_first_of<value_type, size_type, traits_type, npos>
3693        (data(), size(), __str.data(), __pos, __str.size());
3694}
3695
3696template<class _CharT, class _Traits, class _Allocator>
3697template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3698_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3699basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t,
3700                                                size_type __pos) const _NOEXCEPT
3701{
3702    __self_view __sv = __t;
3703    return std::__str_find_first_of<value_type, size_type, traits_type, npos>
3704        (data(), size(), __sv.data(), __pos, __sv.size());
3705}
3706
3707template<class _CharT, class _Traits, class _Allocator>
3708inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3709typename basic_string<_CharT, _Traits, _Allocator>::size_type
3710basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
3711                                                         size_type __pos) const _NOEXCEPT
3712{
3713    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_of(): received nullptr");
3714    return std::__str_find_first_of<value_type, size_type, traits_type, npos>
3715        (data(), size(), __s, __pos, traits_type::length(__s));
3716}
3717
3718template<class _CharT, class _Traits, class _Allocator>
3719inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3720typename basic_string<_CharT, _Traits, _Allocator>::size_type
3721basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c,
3722                                                         size_type __pos) const _NOEXCEPT
3723{
3724    return find(__c, __pos);
3725}
3726
3727// find_last_of
3728
3729template<class _CharT, class _Traits, class _Allocator>
3730inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3731typename basic_string<_CharT, _Traits, _Allocator>::size_type
3732basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
3733                                                        size_type __pos,
3734                                                        size_type __n) const _NOEXCEPT
3735{
3736    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr");
3737    return std::__str_find_last_of<value_type, size_type, traits_type, npos>
3738        (data(), size(), __s, __pos, __n);
3739}
3740
3741template<class _CharT, class _Traits, class _Allocator>
3742inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3743typename basic_string<_CharT, _Traits, _Allocator>::size_type
3744basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str,
3745                                                        size_type __pos) const _NOEXCEPT
3746{
3747    return std::__str_find_last_of<value_type, size_type, traits_type, npos>
3748        (data(), size(), __str.data(), __pos, __str.size());
3749}
3750
3751template<class _CharT, class _Traits, class _Allocator>
3752template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3753_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3754basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t,
3755                                                size_type __pos) const _NOEXCEPT
3756{
3757    __self_view __sv = __t;
3758    return std::__str_find_last_of<value_type, size_type, traits_type, npos>
3759        (data(), size(), __sv.data(), __pos, __sv.size());
3760}
3761
3762template<class _CharT, class _Traits, class _Allocator>
3763inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3764typename basic_string<_CharT, _Traits, _Allocator>::size_type
3765basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
3766                                                        size_type __pos) const _NOEXCEPT
3767{
3768    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_of(): received nullptr");
3769    return std::__str_find_last_of<value_type, size_type, traits_type, npos>
3770        (data(), size(), __s, __pos, traits_type::length(__s));
3771}
3772
3773template<class _CharT, class _Traits, class _Allocator>
3774inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3775typename basic_string<_CharT, _Traits, _Allocator>::size_type
3776basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c,
3777                                                        size_type __pos) const _NOEXCEPT
3778{
3779    return rfind(__c, __pos);
3780}
3781
3782// find_first_not_of
3783
3784template<class _CharT, class _Traits, class _Allocator>
3785_LIBCPP_CONSTEXPR_SINCE_CXX20
3786typename basic_string<_CharT, _Traits, _Allocator>::size_type
3787basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
3788                                                             size_type __pos,
3789                                                             size_type __n) const _NOEXCEPT
3790{
3791    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr");
3792    return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>
3793        (data(), size(), __s, __pos, __n);
3794}
3795
3796template<class _CharT, class _Traits, class _Allocator>
3797inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3798typename basic_string<_CharT, _Traits, _Allocator>::size_type
3799basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str,
3800                                                             size_type __pos) const _NOEXCEPT
3801{
3802    return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>
3803        (data(), size(), __str.data(), __pos, __str.size());
3804}
3805
3806template<class _CharT, class _Traits, class _Allocator>
3807template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3808_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3809basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t,
3810                                                size_type __pos) const _NOEXCEPT
3811{
3812    __self_view __sv = __t;
3813    return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>
3814        (data(), size(), __sv.data(), __pos, __sv.size());
3815}
3816
3817template<class _CharT, class _Traits, class _Allocator>
3818inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3819typename basic_string<_CharT, _Traits, _Allocator>::size_type
3820basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
3821                                                             size_type __pos) const _NOEXCEPT
3822{
3823    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_not_of(): received nullptr");
3824    return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>
3825        (data(), size(), __s, __pos, traits_type::length(__s));
3826}
3827
3828template<class _CharT, class _Traits, class _Allocator>
3829inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3830typename basic_string<_CharT, _Traits, _Allocator>::size_type
3831basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c,
3832                                                             size_type __pos) const _NOEXCEPT
3833{
3834    return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>
3835        (data(), size(), __c, __pos);
3836}
3837
3838// find_last_not_of
3839
3840template<class _CharT, class _Traits, class _Allocator>
3841_LIBCPP_CONSTEXPR_SINCE_CXX20
3842typename basic_string<_CharT, _Traits, _Allocator>::size_type
3843basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
3844                                                            size_type __pos,
3845                                                            size_type __n) const _NOEXCEPT
3846{
3847    _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr");
3848    return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>
3849        (data(), size(), __s, __pos, __n);
3850}
3851
3852template<class _CharT, class _Traits, class _Allocator>
3853inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3854typename basic_string<_CharT, _Traits, _Allocator>::size_type
3855basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str,
3856                                                            size_type __pos) const _NOEXCEPT
3857{
3858    return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>
3859        (data(), size(), __str.data(), __pos, __str.size());
3860}
3861
3862template<class _CharT, class _Traits, class _Allocator>
3863template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3864_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type
3865basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t,
3866                                                size_type __pos) const _NOEXCEPT
3867{
3868    __self_view __sv = __t;
3869    return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>
3870        (data(), size(), __sv.data(), __pos, __sv.size());
3871}
3872
3873template<class _CharT, class _Traits, class _Allocator>
3874inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3875typename basic_string<_CharT, _Traits, _Allocator>::size_type
3876basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
3877                                                            size_type __pos) const _NOEXCEPT
3878{
3879    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_not_of(): received nullptr");
3880    return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>
3881        (data(), size(), __s, __pos, traits_type::length(__s));
3882}
3883
3884template<class _CharT, class _Traits, class _Allocator>
3885inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3886typename basic_string<_CharT, _Traits, _Allocator>::size_type
3887basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c,
3888                                                            size_type __pos) const _NOEXCEPT
3889{
3890    return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>
3891        (data(), size(), __c, __pos);
3892}
3893
3894// compare
3895
3896template <class _CharT, class _Traits, class _Allocator>
3897template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3898_LIBCPP_CONSTEXPR_SINCE_CXX20 int
3899basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT
3900{
3901    __self_view __sv = __t;
3902    size_t __lhs_sz = size();
3903    size_t __rhs_sz = __sv.size();
3904    int __result = traits_type::compare(data(), __sv.data(),
3905                                        std::min(__lhs_sz, __rhs_sz));
3906    if (__result != 0)
3907        return __result;
3908    if (__lhs_sz < __rhs_sz)
3909        return -1;
3910    if (__lhs_sz > __rhs_sz)
3911        return 1;
3912    return 0;
3913}
3914
3915template <class _CharT, class _Traits, class _Allocator>
3916inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3917int
3918basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT
3919{
3920    return compare(__self_view(__str));
3921}
3922
3923template <class _CharT, class _Traits, class _Allocator>
3924inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3925int
3926basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
3927                                                   size_type __n1,
3928                                                   const value_type* __s,
3929                                                   size_type __n2) const
3930{
3931    _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr");
3932    size_type __sz = size();
3933    if (__pos1 > __sz || __n2 == npos)
3934        __throw_out_of_range();
3935    size_type __rlen = std::min(__n1, __sz - __pos1);
3936    int __r = traits_type::compare(data() + __pos1, __s, std::min(__rlen, __n2));
3937    if (__r == 0)
3938    {
3939        if (__rlen < __n2)
3940            __r = -1;
3941        else if (__rlen > __n2)
3942            __r = 1;
3943    }
3944    return __r;
3945}
3946
3947template <class _CharT, class _Traits, class _Allocator>
3948template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
3949_LIBCPP_CONSTEXPR_SINCE_CXX20 int
3950basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
3951                                                   size_type __n1,
3952                                                   const _Tp& __t) const
3953{
3954    __self_view __sv = __t;
3955    return compare(__pos1, __n1, __sv.data(), __sv.size());
3956}
3957
3958template <class _CharT, class _Traits, class _Allocator>
3959inline _LIBCPP_CONSTEXPR_SINCE_CXX20
3960int
3961basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
3962                                                   size_type __n1,
3963                                                   const basic_string& __str) const
3964{
3965    return compare(__pos1, __n1, __str.data(), __str.size());
3966}
3967
3968template <class _CharT, class _Traits, class _Allocator>
3969template <class _Tp,
3970          __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
3971                            !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
3972                        int> >
3973_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(
3974    size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const {
3975    __self_view __sv = __t;
3976    return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
3977}
3978
3979template <class _CharT, class _Traits, class _Allocator>
3980_LIBCPP_CONSTEXPR_SINCE_CXX20
3981int
3982basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
3983                                                   size_type __n1,
3984                                                   const basic_string& __str,
3985                                                   size_type __pos2,
3986                                                   size_type __n2) const
3987{
3988    return compare(__pos1, __n1, __self_view(__str), __pos2, __n2);
3989}
3990
3991template <class _CharT, class _Traits, class _Allocator>
3992_LIBCPP_CONSTEXPR_SINCE_CXX20
3993int
3994basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT
3995{
3996    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr");
3997    return compare(0, npos, __s, traits_type::length(__s));
3998}
3999
4000template <class _CharT, class _Traits, class _Allocator>
4001_LIBCPP_CONSTEXPR_SINCE_CXX20
4002int
4003basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4004                                                   size_type __n1,
4005                                                   const value_type* __s) const
4006{
4007    _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr");
4008    return compare(__pos1, __n1, __s, traits_type::length(__s));
4009}
4010
4011// __invariants
4012
4013template<class _CharT, class _Traits, class _Allocator>
4014inline _LIBCPP_CONSTEXPR_SINCE_CXX20
4015bool
4016basic_string<_CharT, _Traits, _Allocator>::__invariants() const
4017{
4018    if (size() > capacity())
4019        return false;
4020    if (capacity() < __min_cap - 1)
4021        return false;
4022    if (data() == nullptr)
4023        return false;
4024    if (!_Traits::eq(data()[size()], value_type()))
4025        return false;
4026    return true;
4027}
4028
4029// __clear_and_shrink
4030
4031template<class _CharT, class _Traits, class _Allocator>
4032inline _LIBCPP_CONSTEXPR_SINCE_CXX20
4033void
4034basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT
4035{
4036  clear();
4037  if (__is_long()) {
4038    __annotate_delete();
4039    __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
4040    __r_.first() = __rep();
4041  }
4042}
4043
4044// operator==
4045
4046template<class _CharT, class _Traits, class _Allocator>
4047inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
4048bool
4049operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4050           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4051{
4052#if _LIBCPP_STD_VER >= 20
4053    return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs);
4054#else
4055    size_t __lhs_sz = __lhs.size();
4056    return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(),
4057                                                        __rhs.data(),
4058                                                        __lhs_sz) == 0;
4059#endif
4060}
4061
4062template<class _Allocator>
4063inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
4064bool
4065operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs,
4066           const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT
4067{
4068    size_t __lhs_sz = __lhs.size();
4069    if (__lhs_sz != __rhs.size())
4070        return false;
4071    const char* __lp = __lhs.data();
4072    const char* __rp = __rhs.data();
4073    if (__lhs.__is_long())
4074        return char_traits<char>::compare(__lp, __rp, __lhs_sz) == 0;
4075    for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp)
4076        if (*__lp != *__rp)
4077            return false;
4078    return true;
4079}
4080
4081#if _LIBCPP_STD_VER <= 17
4082template<class _CharT, class _Traits, class _Allocator>
4083inline _LIBCPP_HIDE_FROM_ABI
4084bool
4085operator==(const _CharT* __lhs,
4086           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4087{
4088    typedef basic_string<_CharT, _Traits, _Allocator> _String;
4089    _LIBCPP_ASSERT_NON_NULL(__lhs != nullptr, "operator==(char*, basic_string): received nullptr");
4090    size_t __lhs_len = _Traits::length(__lhs);
4091    if (__lhs_len != __rhs.size()) return false;
4092    return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0;
4093}
4094#endif // _LIBCPP_STD_VER <= 17
4095
4096template<class _CharT, class _Traits, class _Allocator>
4097inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
4098bool
4099operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
4100           const _CharT* __rhs) _NOEXCEPT
4101{
4102#if _LIBCPP_STD_VER >= 20
4103    return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs);
4104#else
4105    typedef basic_string<_CharT, _Traits, _Allocator> _String;
4106    _LIBCPP_ASSERT_NON_NULL(__rhs != nullptr, "operator==(basic_string, char*): received nullptr");
4107    size_t __rhs_len = _Traits::length(__rhs);
4108    if (__rhs_len != __lhs.size()) return false;
4109    return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0;
4110#endif
4111}
4112
4113#if _LIBCPP_STD_VER >= 20
4114
4115template <class _CharT, class _Traits, class _Allocator>
4116_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(
4117    const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4118    const basic_string<_CharT, _Traits, _Allocator>& __rhs) noexcept {
4119    return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs);
4120}
4121
4122template <class _CharT, class _Traits, class _Allocator>
4123_LIBCPP_HIDE_FROM_ABI constexpr auto
4124operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) {
4125    return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs);
4126}
4127
4128#else // _LIBCPP_STD_VER >= 20
4129
4130template<class _CharT, class _Traits, class _Allocator>
4131inline _LIBCPP_HIDE_FROM_ABI
4132bool
4133operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
4134           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4135{
4136    return !(__lhs == __rhs);
4137}
4138
4139template<class _CharT, class _Traits, class _Allocator>
4140inline _LIBCPP_HIDE_FROM_ABI
4141bool
4142operator!=(const _CharT* __lhs,
4143           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4144{
4145    return !(__lhs == __rhs);
4146}
4147
4148template<class _CharT, class _Traits, class _Allocator>
4149inline _LIBCPP_HIDE_FROM_ABI
4150bool
4151operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4152           const _CharT* __rhs) _NOEXCEPT
4153{
4154    return !(__lhs == __rhs);
4155}
4156
4157// operator<
4158
4159template<class _CharT, class _Traits, class _Allocator>
4160inline _LIBCPP_HIDE_FROM_ABI
4161bool
4162operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4163           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4164{
4165    return __lhs.compare(__rhs) < 0;
4166}
4167
4168template<class _CharT, class _Traits, class _Allocator>
4169inline _LIBCPP_HIDE_FROM_ABI
4170bool
4171operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4172           const _CharT* __rhs) _NOEXCEPT
4173{
4174    return __lhs.compare(__rhs) < 0;
4175}
4176
4177template<class _CharT, class _Traits, class _Allocator>
4178inline _LIBCPP_HIDE_FROM_ABI
4179bool
4180operator< (const _CharT* __lhs,
4181           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4182{
4183    return __rhs.compare(__lhs) > 0;
4184}
4185
4186// operator>
4187
4188template<class _CharT, class _Traits, class _Allocator>
4189inline _LIBCPP_HIDE_FROM_ABI
4190bool
4191operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4192           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4193{
4194    return __rhs < __lhs;
4195}
4196
4197template<class _CharT, class _Traits, class _Allocator>
4198inline _LIBCPP_HIDE_FROM_ABI
4199bool
4200operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4201           const _CharT* __rhs) _NOEXCEPT
4202{
4203    return __rhs < __lhs;
4204}
4205
4206template<class _CharT, class _Traits, class _Allocator>
4207inline _LIBCPP_HIDE_FROM_ABI
4208bool
4209operator> (const _CharT* __lhs,
4210           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4211{
4212    return __rhs < __lhs;
4213}
4214
4215// operator<=
4216
4217template<class _CharT, class _Traits, class _Allocator>
4218inline _LIBCPP_HIDE_FROM_ABI
4219bool
4220operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4221           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4222{
4223    return !(__rhs < __lhs);
4224}
4225
4226template<class _CharT, class _Traits, class _Allocator>
4227inline _LIBCPP_HIDE_FROM_ABI
4228bool
4229operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4230           const _CharT* __rhs) _NOEXCEPT
4231{
4232    return !(__rhs < __lhs);
4233}
4234
4235template<class _CharT, class _Traits, class _Allocator>
4236inline _LIBCPP_HIDE_FROM_ABI
4237bool
4238operator<=(const _CharT* __lhs,
4239           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4240{
4241    return !(__rhs < __lhs);
4242}
4243
4244// operator>=
4245
4246template<class _CharT, class _Traits, class _Allocator>
4247inline _LIBCPP_HIDE_FROM_ABI
4248bool
4249operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4250           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4251{
4252    return !(__lhs < __rhs);
4253}
4254
4255template<class _CharT, class _Traits, class _Allocator>
4256inline _LIBCPP_HIDE_FROM_ABI
4257bool
4258operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4259           const _CharT* __rhs) _NOEXCEPT
4260{
4261    return !(__lhs < __rhs);
4262}
4263
4264template<class _CharT, class _Traits, class _Allocator>
4265inline _LIBCPP_HIDE_FROM_ABI
4266bool
4267operator>=(const _CharT* __lhs,
4268           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4269{
4270    return !(__lhs < __rhs);
4271}
4272#endif // _LIBCPP_STD_VER >= 20
4273
4274// operator +
4275
4276template<class _CharT, class _Traits, class _Allocator>
4277_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4278basic_string<_CharT, _Traits, _Allocator>
4279operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4280          const basic_string<_CharT, _Traits, _Allocator>& __rhs)
4281{
4282    using _String = basic_string<_CharT, _Traits, _Allocator>;
4283    auto __lhs_sz = __lhs.size();
4284    auto __rhs_sz = __rhs.size();
4285    _String __r(__uninitialized_size_tag(),
4286                __lhs_sz + __rhs_sz,
4287                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4288    auto __ptr = std::__to_address(__r.__get_pointer());
4289    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4290    _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4291    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4292    return __r;
4293}
4294
4295template<class _CharT, class _Traits, class _Allocator>
4296_LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20
4297basic_string<_CharT, _Traits, _Allocator>
4298operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs)
4299{
4300    using _String = basic_string<_CharT, _Traits, _Allocator>;
4301    auto __lhs_sz = _Traits::length(__lhs);
4302    auto __rhs_sz = __rhs.size();
4303    _String __r(__uninitialized_size_tag(),
4304                __lhs_sz + __rhs_sz,
4305                _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
4306    auto __ptr = std::__to_address(__r.__get_pointer());
4307    _Traits::copy(__ptr, __lhs, __lhs_sz);
4308    _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4309    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4310    return __r;
4311}
4312
4313template<class _CharT, class _Traits, class _Allocator>
4314_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4315basic_string<_CharT, _Traits, _Allocator>
4316operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs)
4317{
4318    using _String = basic_string<_CharT, _Traits, _Allocator>;
4319    typename _String::size_type __rhs_sz = __rhs.size();
4320    _String __r(__uninitialized_size_tag(),
4321                __rhs_sz + 1,
4322                _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
4323    auto __ptr = std::__to_address(__r.__get_pointer());
4324    _Traits::assign(__ptr, 1, __lhs);
4325    _Traits::copy(__ptr + 1, __rhs.data(), __rhs_sz);
4326    _Traits::assign(__ptr + 1 + __rhs_sz, 1, _CharT());
4327    return __r;
4328}
4329
4330template<class _CharT, class _Traits, class _Allocator>
4331inline _LIBCPP_CONSTEXPR_SINCE_CXX20
4332basic_string<_CharT, _Traits, _Allocator>
4333operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs)
4334{
4335    using _String = basic_string<_CharT, _Traits, _Allocator>;
4336    typename _String::size_type __lhs_sz = __lhs.size();
4337    typename _String::size_type __rhs_sz = _Traits::length(__rhs);
4338    _String __r(__uninitialized_size_tag(),
4339                __lhs_sz + __rhs_sz,
4340                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4341    auto __ptr = std::__to_address(__r.__get_pointer());
4342    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4343    _Traits::copy(__ptr + __lhs_sz, __rhs, __rhs_sz);
4344    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4345    return __r;
4346}
4347
4348template<class _CharT, class _Traits, class _Allocator>
4349_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4350basic_string<_CharT, _Traits, _Allocator>
4351operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs)
4352{
4353    using _String = basic_string<_CharT, _Traits, _Allocator>;
4354    typename _String::size_type __lhs_sz = __lhs.size();
4355    _String __r(__uninitialized_size_tag(),
4356                __lhs_sz + 1,
4357                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4358    auto __ptr = std::__to_address(__r.__get_pointer());
4359    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4360    _Traits::assign(__ptr + __lhs_sz, 1, __rhs);
4361    _Traits::assign(__ptr + 1 + __lhs_sz, 1, _CharT());
4362    return __r;
4363}
4364
4365#ifndef _LIBCPP_CXX03_LANG
4366
4367template<class _CharT, class _Traits, class _Allocator>
4368inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4369basic_string<_CharT, _Traits, _Allocator>
4370operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs)
4371{
4372    return std::move(__lhs.append(__rhs));
4373}
4374
4375template<class _CharT, class _Traits, class _Allocator>
4376inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4377basic_string<_CharT, _Traits, _Allocator>
4378operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
4379{
4380    return std::move(__rhs.insert(0, __lhs));
4381}
4382
4383template<class _CharT, class _Traits, class _Allocator>
4384inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4385basic_string<_CharT, _Traits, _Allocator>
4386operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
4387{
4388    return std::move(__lhs.append(__rhs));
4389}
4390
4391template<class _CharT, class _Traits, class _Allocator>
4392inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4393basic_string<_CharT, _Traits, _Allocator>
4394operator+(const _CharT* __lhs , basic_string<_CharT,_Traits,_Allocator>&& __rhs)
4395{
4396    return std::move(__rhs.insert(0, __lhs));
4397}
4398
4399template<class _CharT, class _Traits, class _Allocator>
4400inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4401basic_string<_CharT, _Traits, _Allocator>
4402operator+(_CharT __lhs, basic_string<_CharT,_Traits,_Allocator>&& __rhs)
4403{
4404    __rhs.insert(__rhs.begin(), __lhs);
4405    return std::move(__rhs);
4406}
4407
4408template<class _CharT, class _Traits, class _Allocator>
4409inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4410basic_string<_CharT, _Traits, _Allocator>
4411operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs)
4412{
4413    return std::move(__lhs.append(__rhs));
4414}
4415
4416template<class _CharT, class _Traits, class _Allocator>
4417inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4418basic_string<_CharT, _Traits, _Allocator>
4419operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs)
4420{
4421    __lhs.push_back(__rhs);
4422    return std::move(__lhs);
4423}
4424
4425#endif // _LIBCPP_CXX03_LANG
4426
4427// swap
4428
4429template<class _CharT, class _Traits, class _Allocator>
4430inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4431void
4432swap(basic_string<_CharT, _Traits, _Allocator>& __lhs,
4433     basic_string<_CharT, _Traits, _Allocator>& __rhs)
4434     _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs)))
4435{
4436    __lhs.swap(__rhs);
4437}
4438
4439_LIBCPP_EXPORTED_FROM_ABI int                stoi  (const string& __str, size_t* __idx = nullptr, int __base = 10);
4440_LIBCPP_EXPORTED_FROM_ABI long               stol  (const string& __str, size_t* __idx = nullptr, int __base = 10);
4441_LIBCPP_EXPORTED_FROM_ABI unsigned long      stoul (const string& __str, size_t* __idx = nullptr, int __base = 10);
4442_LIBCPP_EXPORTED_FROM_ABI long long          stoll (const string& __str, size_t* __idx = nullptr, int __base = 10);
4443_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10);
4444
4445_LIBCPP_EXPORTED_FROM_ABI float       stof (const string& __str, size_t* __idx = nullptr);
4446_LIBCPP_EXPORTED_FROM_ABI double      stod (const string& __str, size_t* __idx = nullptr);
4447_LIBCPP_EXPORTED_FROM_ABI long double stold(const string& __str, size_t* __idx = nullptr);
4448
4449_LIBCPP_EXPORTED_FROM_ABI string to_string(int __val);
4450_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned __val);
4451_LIBCPP_EXPORTED_FROM_ABI string to_string(long __val);
4452_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long __val);
4453_LIBCPP_EXPORTED_FROM_ABI string to_string(long long __val);
4454_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long long __val);
4455_LIBCPP_EXPORTED_FROM_ABI string to_string(float __val);
4456_LIBCPP_EXPORTED_FROM_ABI string to_string(double __val);
4457_LIBCPP_EXPORTED_FROM_ABI string to_string(long double __val);
4458
4459#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4460_LIBCPP_EXPORTED_FROM_ABI int                stoi  (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4461_LIBCPP_EXPORTED_FROM_ABI long               stol  (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4462_LIBCPP_EXPORTED_FROM_ABI unsigned long      stoul (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4463_LIBCPP_EXPORTED_FROM_ABI long long          stoll (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4464_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4465
4466_LIBCPP_EXPORTED_FROM_ABI float       stof (const wstring& __str, size_t* __idx = nullptr);
4467_LIBCPP_EXPORTED_FROM_ABI double      stod (const wstring& __str, size_t* __idx = nullptr);
4468_LIBCPP_EXPORTED_FROM_ABI long double stold(const wstring& __str, size_t* __idx = nullptr);
4469
4470_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(int __val);
4471_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned __val);
4472_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long __val);
4473_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long __val);
4474_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long long __val);
4475_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long long __val);
4476_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(float __val);
4477_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(double __val);
4478_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long double __val);
4479#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4480
4481template<class _CharT, class _Traits, class _Allocator>
4482_LIBCPP_TEMPLATE_DATA_VIS
4483const typename basic_string<_CharT, _Traits, _Allocator>::size_type
4484               basic_string<_CharT, _Traits, _Allocator>::npos;
4485
4486template <class _CharT, class _Allocator>
4487struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> {
4488    _LIBCPP_HIDE_FROM_ABI size_t
4489    operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT {
4490        return std::__do_string_hash(__val.data(), __val.data() + __val.size());
4491    }
4492};
4493
4494template <class _Allocator>
4495struct hash<basic_string<char, char_traits<char>, _Allocator> > : __string_hash<char, _Allocator> {};
4496
4497#ifndef _LIBCPP_HAS_NO_CHAR8_T
4498template <class _Allocator>
4499struct hash<basic_string<char8_t, char_traits<char8_t>, _Allocator> > : __string_hash<char8_t, _Allocator> {};
4500#endif
4501
4502template <class _Allocator>
4503struct hash<basic_string<char16_t, char_traits<char16_t>, _Allocator> > : __string_hash<char16_t, _Allocator> {};
4504
4505template <class _Allocator>
4506struct hash<basic_string<char32_t, char_traits<char32_t>, _Allocator> > : __string_hash<char32_t, _Allocator> {};
4507
4508#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4509template <class _Allocator>
4510struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Allocator> > : __string_hash<wchar_t, _Allocator> {};
4511#endif
4512
4513template<class _CharT, class _Traits, class _Allocator>
4514_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
4515operator<<(basic_ostream<_CharT, _Traits>& __os,
4516           const basic_string<_CharT, _Traits, _Allocator>& __str);
4517
4518template<class _CharT, class _Traits, class _Allocator>
4519_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
4520operator>>(basic_istream<_CharT, _Traits>& __is,
4521           basic_string<_CharT, _Traits, _Allocator>& __str);
4522
4523template<class _CharT, class _Traits, class _Allocator>
4524_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
4525getline(basic_istream<_CharT, _Traits>& __is,
4526        basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm);
4527
4528template<class _CharT, class _Traits, class _Allocator>
4529inline _LIBCPP_HIDE_FROM_ABI
4530basic_istream<_CharT, _Traits>&
4531getline(basic_istream<_CharT, _Traits>& __is,
4532        basic_string<_CharT, _Traits, _Allocator>& __str);
4533
4534template<class _CharT, class _Traits, class _Allocator>
4535inline _LIBCPP_HIDE_FROM_ABI
4536basic_istream<_CharT, _Traits>&
4537getline(basic_istream<_CharT, _Traits>&& __is,
4538        basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm);
4539
4540template<class _CharT, class _Traits, class _Allocator>
4541inline _LIBCPP_HIDE_FROM_ABI
4542basic_istream<_CharT, _Traits>&
4543getline(basic_istream<_CharT, _Traits>&& __is,
4544        basic_string<_CharT, _Traits, _Allocator>& __str);
4545
4546#if _LIBCPP_STD_VER >= 20
4547template <class _CharT, class _Traits, class _Allocator, class _Up>
4548inline _LIBCPP_HIDE_FROM_ABI
4549    typename basic_string<_CharT, _Traits, _Allocator>::size_type
4550    erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) {
4551  auto __old_size = __str.size();
4552  __str.erase(std::remove(__str.begin(), __str.end(), __v), __str.end());
4553  return __old_size - __str.size();
4554}
4555
4556template <class _CharT, class _Traits, class _Allocator, class _Predicate>
4557inline _LIBCPP_HIDE_FROM_ABI
4558    typename basic_string<_CharT, _Traits, _Allocator>::size_type
4559    erase_if(basic_string<_CharT, _Traits, _Allocator>& __str,
4560             _Predicate __pred) {
4561  auto __old_size = __str.size();
4562  __str.erase(std::remove_if(__str.begin(), __str.end(), __pred),
4563              __str.end());
4564  return __old_size - __str.size();
4565}
4566#endif
4567
4568#if _LIBCPP_STD_VER >= 14
4569// Literal suffixes for basic_string [basic.string.literals]
4570inline namespace literals
4571{
4572  inline namespace string_literals
4573  {
4574    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4575    basic_string<char> operator""s( const char *__str, size_t __len )
4576    {
4577        return basic_string<char> (__str, __len);
4578    }
4579
4580#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4581    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4582    basic_string<wchar_t> operator""s( const wchar_t *__str, size_t __len )
4583    {
4584        return basic_string<wchar_t> (__str, __len);
4585    }
4586#endif
4587
4588#ifndef _LIBCPP_HAS_NO_CHAR8_T
4589    inline _LIBCPP_HIDE_FROM_ABI constexpr
4590    basic_string<char8_t> operator""s(const char8_t *__str, size_t __len)
4591    {
4592        return basic_string<char8_t> (__str, __len);
4593    }
4594#endif
4595
4596    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4597    basic_string<char16_t> operator""s( const char16_t *__str, size_t __len )
4598    {
4599        return basic_string<char16_t> (__str, __len);
4600    }
4601
4602    inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
4603    basic_string<char32_t> operator""s( const char32_t *__str, size_t __len )
4604    {
4605        return basic_string<char32_t> (__str, __len);
4606    }
4607  } // namespace string_literals
4608} // namespace literals
4609
4610#if _LIBCPP_STD_VER >= 20
4611template <>
4612inline constexpr bool __format::__enable_insertable<std::basic_string<char>> = true;
4613#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4614template <>
4615inline constexpr bool __format::__enable_insertable<std::basic_string<wchar_t>> = true;
4616#endif
4617#endif
4618
4619#endif
4620
4621_LIBCPP_END_NAMESPACE_STD
4622
4623_LIBCPP_POP_MACROS
4624
4625#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
4626#  include <algorithm>
4627#  include <concepts>
4628#  include <cstdlib>
4629#  include <iterator>
4630#  include <new>
4631#  include <type_traits>
4632#  include <typeinfo>
4633#  include <utility>
4634#endif
4635
4636#endif // _LIBCPP_STRING
4637