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