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