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