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