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