xref: /llvm-project-15.0.7/libcxx/include/string (revision 60f7bdfd)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_STRING
11#define _LIBCPP_STRING
12
13/*
14    string synopsis
15
16namespace std
17{
18
19template <class stateT>
20class fpos
21{
22private:
23    stateT st;
24public:
25    fpos(streamoff = streamoff());
26
27    operator streamoff() const;
28
29    stateT state() const;
30    void state(stateT);
31
32    fpos& operator+=(streamoff);
33    fpos  operator+ (streamoff) const;
34    fpos& operator-=(streamoff);
35    fpos  operator- (streamoff) const;
36};
37
38template <class stateT> streamoff operator-(const fpos<stateT>& x, const fpos<stateT>& y);
39
40template <class stateT> bool operator==(const fpos<stateT>& x, const fpos<stateT>& y);
41template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT>& y);
42
43template <class charT>
44struct char_traits
45{
46    typedef charT     char_type;
47    typedef ...       int_type;
48    typedef streamoff off_type;
49    typedef streampos pos_type;
50    typedef mbstate_t state_type;
51
52    static void assign(char_type& c1, const char_type& c2) noexcept;
53    static constexpr bool eq(char_type c1, char_type c2) noexcept;
54    static constexpr bool lt(char_type c1, char_type c2) noexcept;
55
56    static int              compare(const char_type* s1, const char_type* s2, size_t n);
57    static size_t           length(const char_type* s);
58    static const char_type* find(const char_type* s, size_t n, const char_type& a);
59    static char_type*       move(char_type* s1, const char_type* s2, size_t n);
60    static char_type*       copy(char_type* s1, const char_type* s2, size_t n);
61    static char_type*       assign(char_type* s, size_t n, char_type a);
62
63    static constexpr int_type  not_eof(int_type c) noexcept;
64    static constexpr char_type to_char_type(int_type c) noexcept;
65    static constexpr int_type  to_int_type(char_type c) noexcept;
66    static constexpr bool      eq_int_type(int_type c1, int_type c2) noexcept;
67    static constexpr int_type  eof() noexcept;
68};
69
70template <> struct char_traits<char>;
71template <> struct char_traits<wchar_t>;
72template <> struct char_traits<char8_t>;  // C++20
73template <> struct char_traits<char16_t>;
74template <> struct char_traits<char32_t>;
75
76template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
77class basic_string
78{
79public:
80// types:
81    typedef traits traits_type;
82    typedef typename traits_type::char_type value_type;
83    typedef Allocator allocator_type;
84    typedef typename allocator_type::size_type size_type;
85    typedef typename allocator_type::difference_type difference_type;
86    typedef typename allocator_type::reference reference;
87    typedef typename allocator_type::const_reference const_reference;
88    typedef typename allocator_type::pointer pointer;
89    typedef typename allocator_type::const_pointer const_pointer;
90    typedef implementation-defined iterator;
91    typedef implementation-defined const_iterator;
92    typedef std::reverse_iterator<iterator> reverse_iterator;
93    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
94
95    static const size_type npos = -1;
96
97    basic_string()
98        noexcept(is_nothrow_default_constructible<allocator_type>::value);                      // constexpr since C++20
99    explicit basic_string(const allocator_type& a);                                             // constexpr since C++20
100    basic_string(const basic_string& str);                                                      // constexpr since C++20
101    basic_string(basic_string&& str)
102        noexcept(is_nothrow_move_constructible<allocator_type>::value);                         // constexpr since C++20
103    basic_string(const basic_string& str, size_type pos,
104                 const allocator_type& a = allocator_type());                                   // constexpr since C++20
105    basic_string(const basic_string& str, size_type pos, size_type n,
106                 const Allocator& a = Allocator());                                             // constexpr since C++20
107    template<class T>
108        basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20
109    template <class T>
110        explicit basic_string(const T& t, const Allocator& a = Allocator());                    // C++17, constexpr since C++20
111    basic_string(const value_type* s, const allocator_type& a = allocator_type());              // constexpr since C++20
112    basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20
113    basic_string(nullptr_t) = delete; // C++2b
114    basic_string(size_type n, value_type c, const allocator_type& a = allocator_type());        // constexpr since C++20
115    template<class InputIterator>
116        basic_string(InputIterator begin, InputIterator end,
117                     const allocator_type& a = allocator_type());                               // constexpr since C++20
118    basic_string(initializer_list<value_type>, const Allocator& = Allocator());                 // constexpr since C++20
119    basic_string(const basic_string&, const Allocator&);                                        // constexpr since C++20
120    basic_string(basic_string&&, const Allocator&);                                             // constexpr since C++20
121
122    ~basic_string();                                                                            // constexpr since C++20
123
124    operator basic_string_view<charT, traits>() const noexcept;                                 // constexpr since C++20
125
126    basic_string& operator=(const basic_string& str);                                           // constexpr since C++20
127    template <class T>
128        basic_string& operator=(const T& t);                                                    // C++17, constexpr since C++20
129    basic_string& operator=(basic_string&& str)
130        noexcept(
131             allocator_type::propagate_on_container_move_assignment::value ||
132             allocator_type::is_always_equal::value );                                          // C++17, constexpr since C++20
133    basic_string& operator=(const value_type* s);                                               // constexpr since C++20
134    basic_string& operator=(nullptr_t) = delete; // C++2b
135    basic_string& operator=(value_type c);                                                      // constexpr since C++20
136    basic_string& operator=(initializer_list<value_type>);                                      // constexpr since C++20
137
138    iterator       begin() noexcept;                                                            // constexpr since C++20
139    const_iterator begin() const noexcept;                                                      // constexpr since C++20
140    iterator       end() noexcept;                                                              // constexpr since C++20
141    const_iterator end() const noexcept;                                                        // constexpr since C++20
142
143    reverse_iterator       rbegin() noexcept;                                                   // constexpr since C++20
144    const_reverse_iterator rbegin() const noexcept;                                             // constexpr since C++20
145    reverse_iterator       rend() noexcept;                                                     // constexpr since C++20
146    const_reverse_iterator rend() const noexcept;                                               // constexpr since C++20
147
148    const_iterator         cbegin() const noexcept;                                             // constexpr since C++20
149    const_iterator         cend() const noexcept;                                               // constexpr since C++20
150    const_reverse_iterator crbegin() const noexcept;                                            // constexpr since C++20
151    const_reverse_iterator crend() const noexcept;                                              // constexpr since C++20
152
153    size_type size() const noexcept;                                                            // constexpr since C++20
154    size_type length() const noexcept;                                                          // constexpr since C++20
155    size_type max_size() const noexcept;                                                        // constexpr since C++20
156    size_type capacity() const noexcept;                                                        // constexpr since C++20
157
158    void resize(size_type n, value_type c);                                                     // constexpr since C++20
159    void resize(size_type n);                                                                   // constexpr since C++20
160
161    template<class Operation>
162    constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23
163
164    void reserve(size_type res_arg);                                                            // constexpr since C++20
165    void reserve(); // deprecated in C++20
166    void shrink_to_fit();                                                                       // constexpr since C++20
167    void clear() noexcept;                                                                      // constexpr since C++20
168    bool empty() const noexcept;                                                                // constexpr since C++20
169
170    const_reference operator[](size_type pos) const;                                            // constexpr since C++20
171    reference       operator[](size_type pos);                                                  // constexpr since C++20
172
173    const_reference at(size_type n) const;                                                      // constexpr since C++20
174    reference       at(size_type n);                                                            // constexpr since C++20
175
176    basic_string& operator+=(const basic_string& str);                                          // constexpr since C++20
177    template <class T>
178        basic_string& operator+=(const T& t);                                                   // C++17, constexpr since C++20
179    basic_string& operator+=(const value_type* s);                                              // constexpr since C++20
180    basic_string& operator+=(value_type c);                                                     // constexpr since C++20
181    basic_string& operator+=(initializer_list<value_type>);                                     // constexpr since C++20
182
183    basic_string& append(const basic_string& str);                                              // constexpr since C++20
184    template <class T>
185        basic_string& append(const T& t);                                                       // C++17, constexpr since C++20
186    basic_string& append(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
187    template <class T>
188        basic_string& append(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
189    basic_string& append(const value_type* s, size_type n);                                     // constexpr since C++20
190    basic_string& append(const value_type* s);                                                  // constexpr since C++20
191    basic_string& append(size_type n, value_type c);                                            // constexpr since C++20
192    template<class InputIterator>
193        basic_string& append(InputIterator first, InputIterator last);                          // constexpr since C++20
194    basic_string& append(initializer_list<value_type>);                                         // constexpr since C++20
195
196    void push_back(value_type c);                                                               // constexpr since C++20
197    void pop_back();                                                                            // constexpr since C++20
198    reference       front();                                                                    // constexpr since C++20
199    const_reference front() const;                                                              // constexpr since C++20
200    reference       back();                                                                     // constexpr since C++20
201    const_reference back() const;                                                               // constexpr since C++20
202
203    basic_string& assign(const basic_string& str);                                              // constexpr since C++20
204    template <class T>
205        basic_string& assign(const T& t);                                                       // C++17, constexpr since C++20
206    basic_string& assign(basic_string&& str);                                                   // constexpr since C++20
207    basic_string& assign(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
208    template <class T>
209        basic_string& assign(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
210    basic_string& assign(const value_type* s, size_type n);                                     // constexpr since C++20
211    basic_string& assign(const value_type* s);                                                  // constexpr since C++20
212    basic_string& assign(size_type n, value_type c);                                            // constexpr since C++20
213    template<class InputIterator>
214        basic_string& assign(InputIterator first, InputIterator last);                          // constexpr since C++20
215    basic_string& assign(initializer_list<value_type>);                                         // constexpr since C++20
216
217    basic_string& insert(size_type pos1, const basic_string& str);                              // constexpr since C++20
218    template <class T>
219        basic_string& insert(size_type pos1, const T& t);                                       // constexpr since C++20
220    basic_string& insert(size_type pos1, const basic_string& str,
221                         size_type pos2, size_type n);                                          // constexpr since C++20
222    template <class T>
223        basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n);          // C++17, constexpr since C++20
224    basic_string& insert(size_type pos, const value_type* s, size_type n=npos);                 // C++14, constexpr since C++20
225    basic_string& insert(size_type pos, const value_type* s);                                   // constexpr since C++20
226    basic_string& insert(size_type pos, size_type n, value_type c);                             // constexpr since C++20
227    iterator      insert(const_iterator p, value_type c);                                       // constexpr since C++20
228    iterator      insert(const_iterator p, size_type n, value_type c);                          // constexpr since C++20
229    template<class InputIterator>
230        iterator insert(const_iterator p, InputIterator first, InputIterator last);             // constexpr since C++20
231    iterator      insert(const_iterator p, initializer_list<value_type>);                       // constexpr since C++20
232
233    basic_string& erase(size_type pos = 0, size_type n = npos);                                 // constexpr since C++20
234    iterator      erase(const_iterator position);                                               // constexpr since C++20
235    iterator      erase(const_iterator first, const_iterator last);                             // constexpr since C++20
236
237    basic_string& replace(size_type pos1, size_type n1, const basic_string& str);               // constexpr since C++20
238    template <class T>
239    basic_string& replace(size_type pos1, size_type n1, const T& t);                            // C++17, constexpr since C++20
240    basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
241                          size_type pos2, size_type n2=npos);                                   // C++14, constexpr since C++20
242    template <class T>
243        basic_string& replace(size_type pos1, size_type n1, const T& t,
244                              size_type pos2, size_type n);                                     // C++17, constexpr since C++20
245    basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2);      // constexpr since C++20
246    basic_string& replace(size_type pos, size_type n1, const value_type* s);                    // constexpr since C++20
247    basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c);             // constexpr since C++20
248    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);       // constexpr since C++20
249    template <class T>
250        basic_string& replace(const_iterator i1, const_iterator i2, const T& t);                // C++17, constexpr since C++20
251    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20
252    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s);           // constexpr since C++20
253    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c);     // constexpr since C++20
254    template<class InputIterator>
255        basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20
256    basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>);  // constexpr since C++20
257
258    size_type copy(value_type* s, size_type n, size_type pos = 0) const;                        // constexpr since C++20
259    basic_string substr(size_type pos = 0, size_type n = npos) const;                           // constexpr since C++20
260
261    void swap(basic_string& str)
262        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
263                 allocator_traits<allocator_type>::is_always_equal::value);                     // C++17, constexpr since C++20
264
265    const value_type* c_str() const noexcept;                                                   // constexpr since C++20
266    const value_type* data() const noexcept;                                                    // constexpr since C++20
267          value_type* data()       noexcept;                                                    // C++17, constexpr since C++20
268
269    allocator_type get_allocator() const noexcept;                                              // constexpr since C++20
270
271    size_type find(const basic_string& str, size_type pos = 0) const noexcept;                  // constexpr since C++20
272    template <class T>
273        size_type find(const T& t, size_type pos = 0) const noexcept;                           // C++17, noexcept as an extension, constexpr since C++20
274    size_type find(const value_type* s, size_type pos, size_type n) const noexcept;             // constexpr since C++20
275    size_type find(const value_type* s, size_type pos = 0) const noexcept;                      // constexpr since C++20
276    size_type find(value_type c, size_type pos = 0) const noexcept;                             // constexpr since C++20
277
278    size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;              // constexpr since C++20
279    template <class T>
280        size_type rfind(const T& t, size_type pos = npos) const noexcept;                       // C++17, noexcept as an extension, constexpr since C++20
281    size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept;            // constexpr since C++20
282    size_type rfind(const value_type* s, size_type pos = npos) const noexcept;                  // constexpr since C++20
283    size_type rfind(value_type c, size_type pos = npos) const noexcept;                         // constexpr since C++20
284
285    size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;         // constexpr since C++20
286    template <class T>
287        size_type find_first_of(const T& t, size_type pos = 0) const noexcept;                  // C++17, noexcept as an extension, constexpr since C++20
288    size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept;    // constexpr since C++20
289    size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept;             // constexpr since C++20
290    size_type find_first_of(value_type c, size_type pos = 0) const noexcept;                    // constexpr since C++20
291
292    size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept;       // constexpr since C++20
293    template <class T>
294        size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept;       // C++17, noexcept as an extension, constexpr since C++20
295    size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept;     // constexpr since C++20
296    size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept;           // constexpr since C++20
297    size_type find_last_of(value_type c, size_type pos = npos) const noexcept;                  // constexpr since C++20
298
299    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;     // constexpr since C++20
300    template <class T>
301        size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept;              // C++17, noexcept as an extension, constexpr since C++20
302    size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
303    size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept;         // constexpr since C++20
304    size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept;                // constexpr since C++20
305
306    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept;   // constexpr since C++20
307    template <class T>
308        size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept;            // C++17, noexcept as an extension, constexpr since C++20
309    size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
310    size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept;       // constexpr since C++20
311    size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept;              // constexpr since C++20
312
313    int compare(const basic_string& str) const noexcept;                                        // constexpr since C++20
314    template <class T>
315        int compare(const T& t) const noexcept;                                                 // C++17, noexcept as an extension, constexpr since C++20
316    int compare(size_type pos1, size_type n1, const basic_string& str) const;                   // constexpr since C++20
317    template <class T>
318        int compare(size_type pos1, size_type n1, const T& t) const;                            // C++17, constexpr since C++20
319    int compare(size_type pos1, size_type n1, const basic_string& str,
320                size_type pos2, size_type n2=npos) const;                                       // C++14, constexpr since C++20
321    template <class T>
322        int compare(size_type pos1, size_type n1, const T& t,
323                    size_type pos2, size_type n2=npos) const;                                   // C++17, constexpr since C++20
324    int compare(const value_type* s) const noexcept;                                            // constexpr since C++20
325    int compare(size_type pos1, size_type n1, const value_type* s) const;                       // constexpr since C++20
326    int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const;         // constexpr since C++20
327
328    constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept;             // C++20
329    constexpr bool starts_with(charT c) const noexcept;                                         // C++20
330    constexpr bool starts_with(const charT* s) const;                                           // C++20
331    constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept;               // C++20
332    constexpr bool ends_with(charT c) const noexcept;                                           // C++20
333    constexpr bool ends_with(const charT* s) const;                                             // C++20
334
335    constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept;                // C++2b
336    constexpr bool contains(charT c) const noexcept;                                            // C++2b
337    constexpr bool contains(const charT* s) const;                                              // C++2b
338};
339
340template<class InputIterator,
341         class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
342basic_string(InputIterator, InputIterator, Allocator = Allocator())
343   -> basic_string<typename iterator_traits<InputIterator>::value_type,
344                  char_traits<typename iterator_traits<InputIterator>::value_type>,
345                  Allocator>;   // C++17
346
347template<class charT, class traits, class Allocator>
348basic_string<charT, traits, Allocator>
349operator+(const basic_string<charT, traits, Allocator>& lhs,
350          const basic_string<charT, traits, Allocator>& rhs);                                   // constexpr since C++20
351
352template<class charT, class traits, class Allocator>
353basic_string<charT, traits, Allocator>
354operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs);                   // constexpr since C++20
355
356template<class charT, class traits, class Allocator>
357basic_string<charT, traits, Allocator>
358operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs);                          // constexpr since C++20
359
360template<class charT, class traits, class Allocator>
361basic_string<charT, traits, Allocator>
362operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);                 // constexpr since C++20
363
364template<class charT, class traits, class Allocator>
365basic_string<charT, traits, Allocator>
366operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);                        // constexpr since C++20
367
368template<class charT, class traits, class Allocator>
369bool operator==(const basic_string<charT, traits, Allocator>& lhs,
370                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
371
372template<class charT, class traits, class Allocator>
373bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
374
375template<class charT, class traits, class Allocator>
376bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept;    // constexpr since C++20
377
378template<class charT, class traits, class Allocator>
379bool operator!=(const basic_string<charT,traits,Allocator>& lhs,
380                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
381
382template<class charT, class traits, class Allocator>
383bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
384
385template<class charT, class traits, class Allocator>
386bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
387
388template<class charT, class traits, class Allocator>
389bool operator< (const basic_string<charT, traits, Allocator>& lhs,
390                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
391
392template<class charT, class traits, class Allocator>
393bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
394
395template<class charT, class traits, class Allocator>
396bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
397
398template<class charT, class traits, class Allocator>
399bool operator> (const basic_string<charT, traits, Allocator>& lhs,
400                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
401
402template<class charT, class traits, class Allocator>
403bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
404
405template<class charT, class traits, class Allocator>
406bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
407
408template<class charT, class traits, class Allocator>
409bool operator<=(const basic_string<charT, traits, Allocator>& lhs,
410                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
411
412template<class charT, class traits, class Allocator>
413bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
414
415template<class charT, class traits, class Allocator>
416bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
417
418template<class charT, class traits, class Allocator>
419bool operator>=(const basic_string<charT, traits, Allocator>& lhs,
420                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
421
422template<class charT, class traits, class Allocator>
423bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
424
425template<class charT, class traits, class Allocator>
426bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
427
428template<class charT, class traits, class Allocator>
429void swap(basic_string<charT, traits, Allocator>& lhs,
430          basic_string<charT, traits, Allocator>& rhs)
431            noexcept(noexcept(lhs.swap(rhs)));                                                  // constexpr since C++20
432
433template<class charT, class traits, class Allocator>
434basic_istream<charT, traits>&
435operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
436
437template<class charT, class traits, class Allocator>
438basic_ostream<charT, traits>&
439operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
440
441template<class charT, class traits, class Allocator>
442basic_istream<charT, traits>&
443getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str,
444        charT delim);
445
446template<class charT, class traits, class Allocator>
447basic_istream<charT, traits>&
448getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
449
450template<class charT, class traits, class Allocator, class U>
451typename basic_string<charT, traits, Allocator>::size_type
452erase(basic_string<charT, traits, Allocator>& c, const U& value);    // C++20
453template<class charT, class traits, class Allocator, class Predicate>
454typename basic_string<charT, traits, Allocator>::size_type
455erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20
456
457typedef basic_string<char>    string;
458typedef basic_string<wchar_t> wstring;
459typedef basic_string<char8_t> u8string; // C++20
460typedef basic_string<char16_t> u16string;
461typedef basic_string<char32_t> u32string;
462
463int                stoi  (const string& str, size_t* idx = nullptr, int base = 10);
464long               stol  (const string& str, size_t* idx = nullptr, int base = 10);
465unsigned long      stoul (const string& str, size_t* idx = nullptr, int base = 10);
466long long          stoll (const string& str, size_t* idx = nullptr, int base = 10);
467unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10);
468
469float       stof (const string& str, size_t* idx = nullptr);
470double      stod (const string& str, size_t* idx = nullptr);
471long double stold(const string& str, size_t* idx = nullptr);
472
473string to_string(int val);
474string to_string(unsigned val);
475string to_string(long val);
476string to_string(unsigned long val);
477string to_string(long long val);
478string to_string(unsigned long long val);
479string to_string(float val);
480string to_string(double val);
481string to_string(long double val);
482
483int                stoi  (const wstring& str, size_t* idx = nullptr, int base = 10);
484long               stol  (const wstring& str, size_t* idx = nullptr, int base = 10);
485unsigned long      stoul (const wstring& str, size_t* idx = nullptr, int base = 10);
486long long          stoll (const wstring& str, size_t* idx = nullptr, int base = 10);
487unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10);
488
489float       stof (const wstring& str, size_t* idx = nullptr);
490double      stod (const wstring& str, size_t* idx = nullptr);
491long double stold(const wstring& str, size_t* idx = nullptr);
492
493wstring to_wstring(int val);
494wstring to_wstring(unsigned val);
495wstring to_wstring(long val);
496wstring to_wstring(unsigned long val);
497wstring to_wstring(long long val);
498wstring to_wstring(unsigned long long val);
499wstring to_wstring(float val);
500wstring to_wstring(double val);
501wstring to_wstring(long double val);
502
503template <> struct hash<string>;
504template <> struct hash<u8string>; // C++20
505template <> struct hash<u16string>;
506template <> struct hash<u32string>;
507template <> struct hash<wstring>;
508
509basic_string<char>     operator "" s( const char *str,     size_t len );           // C++14, constexpr since C++20
510basic_string<wchar_t>  operator "" s( const wchar_t *str,  size_t len );           // C++14, constexpr since C++20
511constexpr basic_string<char8_t>  operator "" s( const char8_t *str,  size_t len ); // C++20
512basic_string<char16_t> operator "" s( const char16_t *str, size_t len );           // C++14, constexpr since C++20
513basic_string<char32_t> operator "" s( const char32_t *str, size_t len );           // C++14, constexpr since C++20
514
515}  // std
516
517*/
518
519#include <__algorithm/max.h>
520#include <__algorithm/min.h>
521#include <__algorithm/remove.h>
522#include <__algorithm/remove_if.h>
523#include <__assert> // all public C++ headers provide the assertion handler
524#include <__config>
525#include <__debug>
526#include <__format/enable_insertable.h>
527#include <__functional/hash.h>
528#include <__functional/unary_function.h>
529#include <__ios/fpos.h>
530#include <__iterator/distance.h>
531#include <__iterator/iterator_traits.h>
532#include <__iterator/reverse_iterator.h>
533#include <__iterator/wrap_iter.h>
534#include <__memory/allocate_at_least.h>
535#include <__string/char_traits.h>
536#include <__string/extern_template_lists.h>
537#include <__utility/auto_cast.h>
538#include <__utility/move.h>
539#include <__utility/swap.h>
540#include <__utility/unreachable.h>
541#include <climits>
542#include <cstdint>
543#include <cstdio>  // EOF
544#include <cstdlib>
545#include <cstring>
546#include <iosfwd>
547#include <limits>
548#include <memory>
549#include <stdexcept>
550#include <string_view>
551#include <type_traits>
552#include <version>
553
554#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
555#  include <cwchar>
556#endif
557
558// standard-mandated includes
559
560// [iterator.range]
561#include <__iterator/access.h>
562#include <__iterator/data.h>
563#include <__iterator/empty.h>
564#include <__iterator/reverse_access.h>
565#include <__iterator/size.h>
566
567// [string.syn]
568#include <compare>
569#include <initializer_list>
570
571#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
572#  pragma GCC system_header
573#endif
574
575_LIBCPP_PUSH_MACROS
576#include <__undef_macros>
577
578
579_LIBCPP_BEGIN_NAMESPACE_STD
580
581// basic_string
582
583template<class _CharT, class _Traits, class _Allocator>
584basic_string<_CharT, _Traits, _Allocator>
585_LIBCPP_CONSTEXPR_AFTER_CXX17
586operator+(const basic_string<_CharT, _Traits, _Allocator>& __x,
587          const basic_string<_CharT, _Traits, _Allocator>& __y);
588
589template<class _CharT, class _Traits, class _Allocator>
590_LIBCPP_CONSTEXPR_AFTER_CXX17
591basic_string<_CharT, _Traits, _Allocator>
592operator+(const _CharT* __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
593
594template<class _CharT, class _Traits, class _Allocator>
595_LIBCPP_CONSTEXPR_AFTER_CXX17
596basic_string<_CharT, _Traits, _Allocator>
597operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
598
599template<class _CharT, class _Traits, class _Allocator>
600inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
601basic_string<_CharT, _Traits, _Allocator>
602operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y);
603
604template<class _CharT, class _Traits, class _Allocator>
605_LIBCPP_CONSTEXPR_AFTER_CXX17
606basic_string<_CharT, _Traits, _Allocator>
607operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y);
608
609extern template _LIBCPP_FUNC_VIS string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
610
611template <class _Iter>
612struct __string_is_trivial_iterator : public false_type {};
613
614template <class _Tp>
615struct __string_is_trivial_iterator<_Tp*>
616    : public is_arithmetic<_Tp> {};
617
618template <class _Iter>
619struct __string_is_trivial_iterator<__wrap_iter<_Iter> >
620    : public __string_is_trivial_iterator<_Iter> {};
621
622template <class _CharT, class _Traits, class _Tp>
623struct __can_be_converted_to_string_view : public _BoolConstant<
624      is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value &&
625     !is_convertible<const _Tp&, const _CharT*>::value
626    > {};
627
628#ifndef _LIBCPP_HAS_NO_CHAR8_T
629typedef basic_string<char8_t> u8string;
630#endif
631typedef basic_string<char16_t> u16string;
632typedef basic_string<char32_t> u32string;
633
634struct __uninitialized_size_tag {};
635
636template<class _CharT, class _Traits, class _Allocator>
637class
638    _LIBCPP_TEMPLATE_VIS
639#ifndef _LIBCPP_HAS_NO_CHAR8_T
640    _LIBCPP_PREFERRED_NAME(u8string)
641#endif
642    _LIBCPP_PREFERRED_NAME(u16string)
643    _LIBCPP_PREFERRED_NAME(u32string)
644    basic_string
645{
646public:
647    typedef basic_string                                 __self;
648    typedef basic_string_view<_CharT, _Traits>           __self_view;
649    typedef _Traits                                      traits_type;
650    typedef _CharT                                       value_type;
651    typedef _Allocator                                   allocator_type;
652    typedef allocator_traits<allocator_type>             __alloc_traits;
653    typedef typename __alloc_traits::size_type           size_type;
654    typedef typename __alloc_traits::difference_type     difference_type;
655    typedef value_type&                                  reference;
656    typedef const value_type&                            const_reference;
657    typedef typename __alloc_traits::pointer             pointer;
658    typedef typename __alloc_traits::const_pointer       const_pointer;
659
660    static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array");
661    static_assert(( is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout");
662    static_assert(( is_trivial<value_type>::value), "Character type of basic_string must be trivial");
663    static_assert(( is_same<_CharT, typename traits_type::char_type>::value),
664                  "traits_type::char_type must be the same type as CharT");
665    static_assert(( is_same<typename allocator_type::value_type, value_type>::value),
666                  "Allocator::value_type must be same type as value_type");
667
668    typedef __wrap_iter<pointer>                         iterator;
669    typedef __wrap_iter<const_pointer>                   const_iterator;
670    typedef std::reverse_iterator<iterator>              reverse_iterator;
671    typedef std::reverse_iterator<const_iterator>        const_reverse_iterator;
672
673private:
674    static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits");
675
676#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
677
678    struct __long
679    {
680        pointer   __data_;
681        size_type __size_;
682        size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
683        size_type __is_long_ : 1;
684    };
685
686    enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
687                      (sizeof(__long) - 1)/sizeof(value_type) : 2};
688
689    struct __short
690    {
691        value_type __data_[__min_cap];
692        unsigned char __padding_[sizeof(value_type) - 1];
693        unsigned char __size_ : 7;
694        unsigned char __is_long_ : 1;
695    };
696
697// The __endian_factor is required because the field we use to store the size
698// has one fewer bit than it would if it were not a bitfield.
699//
700// If the LSB is used to store the short-flag in the short string representation,
701// we have to multiply the size by two when it is stored and divide it by two when
702// it is loaded to make sure that we always store an even number. In the long string
703// representation, we can ignore this because we can assume that we always allocate
704// an even amount of value_types.
705//
706// If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2.
707// This does not impact the short string representation, since we never need the MSB
708// for representing the size of a short string anyway.
709
710#ifdef _LIBCPP_BIG_ENDIAN
711    static const size_type __endian_factor = 2;
712#else
713    static const size_type __endian_factor = 1;
714#endif
715
716#else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
717
718#ifdef _LIBCPP_BIG_ENDIAN
719    static const size_type __endian_factor = 1;
720#else
721    static const size_type __endian_factor = 2;
722#endif
723
724    // Attribute 'packed' is used to keep the layout compatible with the
725    // previous definition that did not use bit fields. This is because on
726    // some platforms bit fields have a default size rather than the actual
727    // size used, e.g., it is 4 bytes on AIX. See D128285 for details.
728    struct __long
729    {
730        struct _LIBCPP_PACKED {
731            size_type __is_long_ : 1;
732            size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
733        };
734        size_type __size_;
735        pointer   __data_;
736    };
737
738    enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
739                      (sizeof(__long) - 1)/sizeof(value_type) : 2};
740
741    struct __short
742    {
743        struct _LIBCPP_PACKED {
744            unsigned char __is_long_ : 1;
745            unsigned char __size_ : 7;
746        };
747        char __padding_[sizeof(value_type) - 1];
748        value_type __data_[__min_cap];
749    };
750
751#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
752
753    static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
754
755    union __ulx{__long __lx; __short __lxx;};
756
757    enum {__n_words = sizeof(__ulx) / sizeof(size_type)};
758
759    struct __raw
760    {
761        size_type __words[__n_words];
762    };
763
764    struct __rep
765    {
766        union
767        {
768            __long  __l;
769            __short __s;
770            __raw   __r;
771        };
772    };
773
774    __compressed_pair<__rep, allocator_type> __r_;
775
776    // Construct a string with the given allocator and enough storage to hold `__size` characters, but
777    // don't initialize the characters. The contents of the string, including the null terminator, must be
778    // initialized separately.
779    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
780    explicit basic_string(__uninitialized_size_tag, size_type __size, const allocator_type& __a)
781            : __r_(__default_init_tag(), __a) {
782        if (__size > max_size())
783            __throw_length_error();
784        if (__fits_in_sso(__size)) {
785            __zero();
786            __set_short_size(__size);
787        } else {
788            auto __capacity = __recommend(__size) + 1;
789            auto __allocation = __alloc_traits::allocate(__alloc(), __capacity);
790            __begin_lifetime(__allocation, __capacity);
791            __set_long_cap(__capacity);
792            __set_long_pointer(__allocation);
793            __set_long_size(__size);
794        }
795        std::__debug_db_insert_c(this);
796    }
797
798public:
799    _LIBCPP_TEMPLATE_DATA_VIS
800    static const size_type npos = -1;
801
802    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string()
803        _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value);
804
805    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit basic_string(const allocator_type& __a)
806#if _LIBCPP_STD_VER <= 14
807        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
808#else
809        _NOEXCEPT;
810#endif
811
812    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string(const basic_string& __str);
813    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string(const basic_string& __str, const allocator_type& __a);
814
815#ifndef _LIBCPP_CXX03_LANG
816    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
817    basic_string(basic_string&& __str)
818#if _LIBCPP_STD_VER <= 14
819        _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
820#else
821        _NOEXCEPT;
822#endif
823
824    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
825    basic_string(basic_string&& __str, const allocator_type& __a);
826#endif // _LIBCPP_CXX03_LANG
827
828    template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
829    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
830    basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) {
831      _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr");
832      __init(__s, traits_type::length(__s));
833      std::__debug_db_insert_c(this);
834    }
835
836    template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
837        _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
838        basic_string(const _CharT* __s, const _Allocator& __a);
839
840#if _LIBCPP_STD_VER > 20
841    basic_string(nullptr_t) = delete;
842#endif
843
844    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
845    basic_string(const _CharT* __s, size_type __n);
846    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
847    basic_string(const _CharT* __s, size_type __n, const _Allocator& __a);
848    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
849    basic_string(size_type __n, _CharT __c);
850
851    template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
852        _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
853        basic_string(size_type __n, _CharT __c, const _Allocator& __a);
854
855    _LIBCPP_CONSTEXPR_AFTER_CXX17
856    basic_string(const basic_string& __str, size_type __pos, size_type __n,
857                 const _Allocator& __a = _Allocator());
858    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
859    basic_string(const basic_string& __str, size_type __pos,
860                 const _Allocator& __a = _Allocator());
861
862    template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >
863        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
864        basic_string(const _Tp& __t, size_type __pos, size_type __n,
865                     const allocator_type& __a = allocator_type());
866
867    template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
868                                          !__is_same_uncvref<_Tp, basic_string>::value> >
869        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
870        explicit basic_string(const _Tp& __t);
871
872    template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >
873        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
874        explicit basic_string(const _Tp& __t, const allocator_type& __a);
875
876    template<class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> >
877        _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
878        basic_string(_InputIterator __first, _InputIterator __last);
879    template<class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> >
880        _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
881        basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
882#ifndef _LIBCPP_CXX03_LANG
883    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
884    basic_string(initializer_list<_CharT> __il);
885    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
886    basic_string(initializer_list<_CharT> __il, const _Allocator& __a);
887#endif // _LIBCPP_CXX03_LANG
888
889    inline _LIBCPP_CONSTEXPR_AFTER_CXX17 ~basic_string();
890
891    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
892    operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); }
893
894    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(const basic_string& __str);
895
896    template <class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
897                                               !__is_same_uncvref<_Tp, basic_string>::value> >
898    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(const _Tp& __t) {
899      __self_view __sv = __t;
900      return assign(__sv);
901    }
902
903#ifndef _LIBCPP_CXX03_LANG
904    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
905    basic_string& operator=(basic_string&& __str)
906        _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
907     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
908    basic_string& operator=(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());}
909#endif
910    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
911    basic_string& operator=(const value_type* __s) {return assign(__s);}
912#if _LIBCPP_STD_VER > 20
913    basic_string& operator=(nullptr_t) = delete;
914#endif
915    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(value_type __c);
916
917    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
918    iterator begin() _NOEXCEPT
919        {return iterator(this, __get_pointer());}
920    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
921    const_iterator begin() const _NOEXCEPT
922        {return const_iterator(this, __get_pointer());}
923    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
924    iterator end() _NOEXCEPT
925        {return iterator(this, __get_pointer() + size());}
926    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
927    const_iterator end() const _NOEXCEPT
928        {return const_iterator(this, __get_pointer() + size());}
929
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#ifdef _LIBCPP_ENABLE_DEBUG_MODE
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_ENABLE_DEBUG_MODE
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#define _LIBCPP_DECLARE(...) extern template __VA_ARGS__;
1812#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
1813    _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
1814#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1815        _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
1816#   endif
1817#else
1818    _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
1819#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1820        _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
1821#   endif
1822#endif
1823#undef _LIBCPP_DECLARE
1824
1825
1826#if _LIBCPP_STD_VER >= 17
1827template<class _InputIterator,
1828         class _CharT = __iter_value_type<_InputIterator>,
1829         class _Allocator = allocator<_CharT>,
1830         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
1831         class = enable_if_t<__is_allocator<_Allocator>::value>
1832         >
1833basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
1834  -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
1835
1836template<class _CharT,
1837         class _Traits,
1838         class _Allocator = allocator<_CharT>,
1839         class = enable_if_t<__is_allocator<_Allocator>::value>
1840         >
1841explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
1842  -> basic_string<_CharT, _Traits, _Allocator>;
1843
1844template<class _CharT,
1845         class _Traits,
1846         class _Allocator = allocator<_CharT>,
1847         class = enable_if_t<__is_allocator<_Allocator>::value>,
1848         class _Sz = typename allocator_traits<_Allocator>::size_type
1849         >
1850basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator())
1851  -> basic_string<_CharT, _Traits, _Allocator>;
1852#endif
1853
1854template <class _CharT, class _Traits, class _Allocator>
1855inline _LIBCPP_CONSTEXPR_AFTER_CXX17
1856void
1857basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type __pos)
1858{
1859#ifdef _LIBCPP_ENABLE_DEBUG_MODE
1860    if (!__libcpp_is_constant_evaluated()) {
1861        __c_node* __c = __get_db()->__find_c_and_lock(this);
1862        if (__c)
1863        {
1864            const_pointer __new_last = __get_pointer() + __pos;
1865            for (__i_node** __p = __c->end_; __p != __c->beg_; )
1866            {
1867                --__p;
1868                const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_);
1869                if (__i->base() > __new_last)
1870                {
1871                    (*__p)->__c_ = nullptr;
1872                    if (--__c->end_ != __p)
1873                        std::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1874                }
1875            }
1876            __get_db()->unlock();
1877        }
1878    }
1879#else
1880    (void)__pos;
1881#endif // _LIBCPP_ENABLE_DEBUG_MODE
1882}
1883
1884template <class _CharT, class _Traits, class _Allocator>
1885inline _LIBCPP_CONSTEXPR_AFTER_CXX17
1886basic_string<_CharT, _Traits, _Allocator>::basic_string()
1887    _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
1888     : __r_(__default_init_tag(), __default_init_tag())
1889{
1890    std::__debug_db_insert_c(this);
1891    __default_init();
1892}
1893
1894template <class _CharT, class _Traits, class _Allocator>
1895inline _LIBCPP_CONSTEXPR_AFTER_CXX17
1896basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
1897#if _LIBCPP_STD_VER <= 14
1898        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
1899#else
1900        _NOEXCEPT
1901#endif
1902: __r_(__default_init_tag(), __a)
1903{
1904    std::__debug_db_insert_c(this);
1905    __default_init();
1906}
1907
1908template <class _CharT, class _Traits, class _Allocator>
1909_LIBCPP_CONSTEXPR_AFTER_CXX17
1910void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
1911                                                       size_type __sz,
1912                                                       size_type __reserve)
1913{
1914    if (__libcpp_is_constant_evaluated())
1915        __zero();
1916    if (__reserve > max_size())
1917        __throw_length_error();
1918    pointer __p;
1919    if (__fits_in_sso(__reserve))
1920    {
1921        __set_short_size(__sz);
1922        __p = __get_short_pointer();
1923    }
1924    else
1925    {
1926        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1);
1927        __p = __allocation.ptr;
1928        __begin_lifetime(__p, __allocation.count);
1929        __set_long_pointer(__p);
1930        __set_long_cap(__allocation.count);
1931        __set_long_size(__sz);
1932    }
1933    traits_type::copy(std::__to_address(__p), __s, __sz);
1934    traits_type::assign(__p[__sz], value_type());
1935}
1936
1937template <class _CharT, class _Traits, class _Allocator>
1938_LIBCPP_CONSTEXPR_AFTER_CXX17
1939void
1940basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
1941{
1942    if (__libcpp_is_constant_evaluated())
1943        __zero();
1944    if (__sz > max_size())
1945        __throw_length_error();
1946    pointer __p;
1947    if (__fits_in_sso(__sz))
1948    {
1949        __set_short_size(__sz);
1950        __p = __get_short_pointer();
1951    }
1952    else
1953    {
1954        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
1955        __p = __allocation.ptr;
1956        __begin_lifetime(__p, __allocation.count);
1957        __set_long_pointer(__p);
1958        __set_long_cap(__allocation.count);
1959        __set_long_size(__sz);
1960    }
1961    traits_type::copy(std::__to_address(__p), __s, __sz);
1962    traits_type::assign(__p[__sz], value_type());
1963}
1964
1965template <class _CharT, class _Traits, class _Allocator>
1966template <class>
1967_LIBCPP_CONSTEXPR_AFTER_CXX17
1968basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a)
1969    : __r_(__default_init_tag(), __a)
1970{
1971    _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
1972    __init(__s, traits_type::length(__s));
1973    std::__debug_db_insert_c(this);
1974}
1975
1976template <class _CharT, class _Traits, class _Allocator>
1977inline _LIBCPP_CONSTEXPR_AFTER_CXX17
1978basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n)
1979     : __r_(__default_init_tag(), __default_init_tag())
1980{
1981    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr");
1982    __init(__s, __n);
1983    std::__debug_db_insert_c(this);
1984}
1985
1986template <class _CharT, class _Traits, class _Allocator>
1987inline _LIBCPP_CONSTEXPR_AFTER_CXX17
1988basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
1989    : __r_(__default_init_tag(), __a)
1990{
1991    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
1992    __init(__s, __n);
1993    std::__debug_db_insert_c(this);
1994}
1995
1996template <class _CharT, class _Traits, class _Allocator>
1997_LIBCPP_CONSTEXPR_AFTER_CXX17
1998basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str)
1999    : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc()))
2000{
2001    if (!__str.__is_long())
2002        __r_.first().__r = __str.__r_.first().__r;
2003    else
2004        __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()),
2005                                  __str.__get_long_size());
2006    std::__debug_db_insert_c(this);
2007}
2008
2009template <class _CharT, class _Traits, class _Allocator>
2010_LIBCPP_CONSTEXPR_AFTER_CXX17
2011basic_string<_CharT, _Traits, _Allocator>::basic_string(
2012    const basic_string& __str, const allocator_type& __a)
2013    : __r_(__default_init_tag(), __a)
2014{
2015    if (!__str.__is_long())
2016        __r_.first().__r = __str.__r_.first().__r;
2017    else
2018        __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()),
2019                                  __str.__get_long_size());
2020    std::__debug_db_insert_c(this);
2021}
2022
2023template <class _CharT, class _Traits, class _Allocator>
2024_LIBCPP_CONSTEXPR_AFTER_CXX17
2025void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
2026    const value_type* __s, size_type __sz) {
2027  if (__libcpp_is_constant_evaluated())
2028    __zero();
2029  pointer __p;
2030  if (__fits_in_sso(__sz)) {
2031    __p = __get_short_pointer();
2032    __set_short_size(__sz);
2033  } else {
2034    if (__sz > max_size())
2035      __throw_length_error();
2036    auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
2037    __p = __allocation.ptr;
2038    __begin_lifetime(__p, __allocation.count);
2039    __set_long_pointer(__p);
2040    __set_long_cap(__allocation.count);
2041    __set_long_size(__sz);
2042  }
2043  traits_type::copy(std::__to_address(__p), __s, __sz + 1);
2044}
2045
2046#ifndef _LIBCPP_CXX03_LANG
2047
2048template <class _CharT, class _Traits, class _Allocator>
2049inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2050basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str)
2051#if _LIBCPP_STD_VER <= 14
2052        _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
2053#else
2054        _NOEXCEPT
2055#endif
2056    : __r_(std::move(__str.__r_))
2057{
2058    __str.__default_init();
2059    std::__debug_db_insert_c(this);
2060    if (__is_long())
2061        std::__debug_db_swap(this, &__str);
2062}
2063
2064template <class _CharT, class _Traits, class _Allocator>
2065inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2066basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a)
2067    : __r_(__default_init_tag(), __a)
2068{
2069    if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
2070        __init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
2071    else
2072    {
2073        if (__libcpp_is_constant_evaluated()) {
2074            __zero();
2075            __r_.first().__l = __str.__r_.first().__l;
2076        } else {
2077            __r_.first().__r = __str.__r_.first().__r;
2078        }
2079        __str.__default_init();
2080    }
2081    std::__debug_db_insert_c(this);
2082    if (__is_long())
2083        std::__debug_db_swap(this, &__str);
2084}
2085
2086#endif // _LIBCPP_CXX03_LANG
2087
2088template <class _CharT, class _Traits, class _Allocator>
2089_LIBCPP_CONSTEXPR_AFTER_CXX17
2090void
2091basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
2092{
2093    if (__libcpp_is_constant_evaluated())
2094        __zero();
2095    if (__n > max_size())
2096        __throw_length_error();
2097    pointer __p;
2098    if (__fits_in_sso(__n))
2099    {
2100        __set_short_size(__n);
2101        __p = __get_short_pointer();
2102    }
2103    else
2104    {
2105        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1);
2106        __p = __allocation.ptr;
2107        __begin_lifetime(__p, __allocation.count);
2108        __set_long_pointer(__p);
2109        __set_long_cap(__allocation.count);
2110        __set_long_size(__n);
2111    }
2112    traits_type::assign(std::__to_address(__p), __n, __c);
2113    traits_type::assign(__p[__n], value_type());
2114}
2115
2116template <class _CharT, class _Traits, class _Allocator>
2117inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2118basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c)
2119     : __r_(__default_init_tag(), __default_init_tag())
2120{
2121    __init(__n, __c);
2122    std::__debug_db_insert_c(this);
2123}
2124
2125template <class _CharT, class _Traits, class _Allocator>
2126template <class>
2127_LIBCPP_CONSTEXPR_AFTER_CXX17
2128basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a)
2129    : __r_(__default_init_tag(), __a)
2130{
2131    __init(__n, __c);
2132    std::__debug_db_insert_c(this);
2133}
2134
2135template <class _CharT, class _Traits, class _Allocator>
2136_LIBCPP_CONSTEXPR_AFTER_CXX17
2137basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str,
2138                                                        size_type __pos, size_type __n,
2139                                                        const _Allocator& __a)
2140    : __r_(__default_init_tag(), __a)
2141{
2142    size_type __str_sz = __str.size();
2143    if (__pos > __str_sz)
2144        __throw_out_of_range();
2145    __init(__str.data() + __pos, std::min(__n, __str_sz - __pos));
2146    std::__debug_db_insert_c(this);
2147}
2148
2149template <class _CharT, class _Traits, class _Allocator>
2150inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2151basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos,
2152                                                        const _Allocator& __a)
2153    : __r_(__default_init_tag(), __a)
2154{
2155    size_type __str_sz = __str.size();
2156    if (__pos > __str_sz)
2157        __throw_out_of_range();
2158    __init(__str.data() + __pos, __str_sz - __pos);
2159    std::__debug_db_insert_c(this);
2160}
2161
2162template <class _CharT, class _Traits, class _Allocator>
2163template <class _Tp, class>
2164_LIBCPP_CONSTEXPR_AFTER_CXX17
2165basic_string<_CharT, _Traits, _Allocator>::basic_string(
2166             const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a)
2167    : __r_(__default_init_tag(), __a)
2168{
2169    __self_view __sv0 = __t;
2170    __self_view __sv = __sv0.substr(__pos, __n);
2171    __init(__sv.data(), __sv.size());
2172    std::__debug_db_insert_c(this);
2173}
2174
2175template <class _CharT, class _Traits, class _Allocator>
2176template <class _Tp, class>
2177_LIBCPP_CONSTEXPR_AFTER_CXX17
2178basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t)
2179     : __r_(__default_init_tag(), __default_init_tag())
2180{
2181    __self_view __sv = __t;
2182    __init(__sv.data(), __sv.size());
2183    std::__debug_db_insert_c(this);
2184}
2185
2186template <class _CharT, class _Traits, class _Allocator>
2187template <class _Tp, class>
2188_LIBCPP_CONSTEXPR_AFTER_CXX17
2189basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t, const _Allocator& __a)
2190    : __r_(__default_init_tag(), __a)
2191{
2192    __self_view __sv = __t;
2193    __init(__sv.data(), __sv.size());
2194    std::__debug_db_insert_c(this);
2195}
2196
2197template <class _CharT, class _Traits, class _Allocator>
2198template <class _InputIterator>
2199_LIBCPP_CONSTEXPR_AFTER_CXX17
2200__enable_if_t
2201<
2202    __is_exactly_cpp17_input_iterator<_InputIterator>::value
2203>
2204basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last)
2205{
2206    __default_init();
2207#ifndef _LIBCPP_NO_EXCEPTIONS
2208    try
2209    {
2210#endif // _LIBCPP_NO_EXCEPTIONS
2211    for (; __first != __last; ++__first)
2212        push_back(*__first);
2213#ifndef _LIBCPP_NO_EXCEPTIONS
2214    }
2215    catch (...)
2216    {
2217        if (__is_long())
2218            __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2219        throw;
2220    }
2221#endif // _LIBCPP_NO_EXCEPTIONS
2222}
2223
2224template <class _CharT, class _Traits, class _Allocator>
2225template <class _ForwardIterator>
2226_LIBCPP_CONSTEXPR_AFTER_CXX17
2227__enable_if_t
2228<
2229    __is_cpp17_forward_iterator<_ForwardIterator>::value
2230>
2231basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last)
2232{
2233    if (__libcpp_is_constant_evaluated())
2234        __zero();
2235    size_type __sz = static_cast<size_type>(std::distance(__first, __last));
2236    if (__sz > max_size())
2237        __throw_length_error();
2238    pointer __p;
2239    if (__fits_in_sso(__sz))
2240    {
2241        __set_short_size(__sz);
2242        __p = __get_short_pointer();
2243    }
2244    else
2245    {
2246        auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
2247        __p = __allocation.ptr;
2248        __begin_lifetime(__p, __allocation.count);
2249        __set_long_pointer(__p);
2250        __set_long_cap(__allocation.count);
2251        __set_long_size(__sz);
2252    }
2253
2254#ifndef _LIBCPP_NO_EXCEPTIONS
2255    try
2256    {
2257#endif  // _LIBCPP_NO_EXCEPTIONS
2258    for (; __first != __last; ++__first, (void) ++__p)
2259        traits_type::assign(*__p, *__first);
2260    traits_type::assign(*__p, value_type());
2261#ifndef _LIBCPP_NO_EXCEPTIONS
2262    }
2263    catch (...)
2264    {
2265        if (__is_long())
2266            __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2267        throw;
2268    }
2269#endif  // _LIBCPP_NO_EXCEPTIONS
2270}
2271
2272template <class _CharT, class _Traits, class _Allocator>
2273template<class _InputIterator, class>
2274inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2275basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last)
2276     : __r_(__default_init_tag(), __default_init_tag())
2277{
2278    __init(__first, __last);
2279    std::__debug_db_insert_c(this);
2280}
2281
2282template <class _CharT, class _Traits, class _Allocator>
2283template<class _InputIterator, class>
2284inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2285basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last,
2286                                                        const allocator_type& __a)
2287    : __r_(__default_init_tag(), __a)
2288{
2289    __init(__first, __last);
2290    std::__debug_db_insert_c(this);
2291}
2292
2293#ifndef _LIBCPP_CXX03_LANG
2294
2295template <class _CharT, class _Traits, class _Allocator>
2296inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2297basic_string<_CharT, _Traits, _Allocator>::basic_string(
2298    initializer_list<_CharT> __il)
2299     : __r_(__default_init_tag(), __default_init_tag())
2300{
2301    __init(__il.begin(), __il.end());
2302    std::__debug_db_insert_c(this);
2303}
2304
2305template <class _CharT, class _Traits, class _Allocator>
2306inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2307basic_string<_CharT, _Traits, _Allocator>::basic_string(
2308    initializer_list<_CharT> __il, const _Allocator& __a)
2309    : __r_(__default_init_tag(), __a)
2310{
2311    __init(__il.begin(), __il.end());
2312    std::__debug_db_insert_c(this);
2313}
2314
2315#endif // _LIBCPP_CXX03_LANG
2316
2317template <class _CharT, class _Traits, class _Allocator>
2318_LIBCPP_CONSTEXPR_AFTER_CXX17
2319basic_string<_CharT, _Traits, _Allocator>::~basic_string()
2320{
2321    std::__debug_db_erase_c(this);
2322    if (__is_long())
2323        __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
2324}
2325
2326template <class _CharT, class _Traits, class _Allocator>
2327_LIBCPP_CONSTEXPR_AFTER_CXX17
2328void
2329basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
2330    (size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2331     size_type __n_copy,  size_type __n_del,     size_type __n_add, const value_type* __p_new_stuff)
2332{
2333    size_type __ms = max_size();
2334    if (__delta_cap > __ms - __old_cap - 1)
2335        __throw_length_error();
2336    pointer __old_p = __get_pointer();
2337    size_type __cap = __old_cap < __ms / 2 - __alignment ?
2338                          __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
2339                          __ms - 1;
2340    auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
2341    pointer __p = __allocation.ptr;
2342    __begin_lifetime(__p, __allocation.count);
2343    std::__debug_db_invalidate_all(this);
2344    if (__n_copy != 0)
2345        traits_type::copy(std::__to_address(__p),
2346                          std::__to_address(__old_p), __n_copy);
2347    if (__n_add != 0)
2348        traits_type::copy(std::__to_address(__p) + __n_copy, __p_new_stuff, __n_add);
2349    size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
2350    if (__sec_cp_sz != 0)
2351        traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
2352                          std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
2353    if (__old_cap+1 != __min_cap || __libcpp_is_constant_evaluated())
2354        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
2355    __set_long_pointer(__p);
2356    __set_long_cap(__allocation.count);
2357    __old_sz = __n_copy + __n_add + __sec_cp_sz;
2358    __set_long_size(__old_sz);
2359    traits_type::assign(__p[__old_sz], value_type());
2360}
2361
2362template <class _CharT, class _Traits, class _Allocator>
2363void
2364_LIBCPP_CONSTEXPR_AFTER_CXX17
2365basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
2366                                                     size_type __n_copy,  size_type __n_del,     size_type __n_add)
2367{
2368    size_type __ms = max_size();
2369    if (__delta_cap > __ms - __old_cap)
2370        __throw_length_error();
2371    pointer __old_p = __get_pointer();
2372    size_type __cap = __old_cap < __ms / 2 - __alignment ?
2373                          __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
2374                          __ms - 1;
2375    auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
2376    pointer __p = __allocation.ptr;
2377    __begin_lifetime(__p, __allocation.count);
2378    std::__debug_db_invalidate_all(this);
2379    if (__n_copy != 0)
2380        traits_type::copy(std::__to_address(__p),
2381                          std::__to_address(__old_p), __n_copy);
2382    size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
2383    if (__sec_cp_sz != 0)
2384        traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
2385                          std::__to_address(__old_p) + __n_copy + __n_del,
2386                          __sec_cp_sz);
2387    if (__libcpp_is_constant_evaluated() || __old_cap + 1 != __min_cap)
2388        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
2389    __set_long_pointer(__p);
2390    __set_long_cap(__allocation.count);
2391}
2392
2393// assign
2394
2395template <class _CharT, class _Traits, class _Allocator>
2396template <bool __is_short>
2397_LIBCPP_CONSTEXPR_AFTER_CXX17
2398basic_string<_CharT, _Traits, _Allocator>&
2399basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
2400    const value_type* __s, size_type __n) {
2401  size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
2402  if (__n < __cap) {
2403    pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
2404    __is_short ? __set_short_size(__n) : __set_long_size(__n);
2405    traits_type::copy(std::__to_address(__p), __s, __n);
2406    traits_type::assign(__p[__n], value_type());
2407    __invalidate_iterators_past(__n);
2408  } else {
2409    size_type __sz = __is_short ? __get_short_size() : __get_long_size();
2410    __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
2411  }
2412  return *this;
2413}
2414
2415template <class _CharT, class _Traits, class _Allocator>
2416_LIBCPP_CONSTEXPR_AFTER_CXX17
2417basic_string<_CharT, _Traits, _Allocator>&
2418basic_string<_CharT, _Traits, _Allocator>::__assign_external(
2419    const value_type* __s, size_type __n) {
2420  size_type __cap = capacity();
2421  if (__cap >= __n) {
2422    value_type* __p = std::__to_address(__get_pointer());
2423    traits_type::move(__p, __s, __n);
2424    return __null_terminate_at(__p, __n);
2425  } else {
2426    size_type __sz = size();
2427    __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s);
2428    return *this;
2429  }
2430}
2431
2432template <class _CharT, class _Traits, class _Allocator>
2433_LIBCPP_CONSTEXPR_AFTER_CXX17
2434basic_string<_CharT, _Traits, _Allocator>&
2435basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
2436{
2437    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr");
2438    return (__builtin_constant_p(__n) && __fits_in_sso(__n))
2439               ? __assign_short(__s, __n)
2440               : __assign_external(__s, __n);
2441}
2442
2443template <class _CharT, class _Traits, class _Allocator>
2444_LIBCPP_CONSTEXPR_AFTER_CXX17
2445basic_string<_CharT, _Traits, _Allocator>&
2446basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
2447{
2448    size_type __cap = capacity();
2449    if (__cap < __n)
2450    {
2451        size_type __sz = size();
2452        __grow_by(__cap, __n - __cap, __sz, 0, __sz);
2453    }
2454    value_type* __p = std::__to_address(__get_pointer());
2455    traits_type::assign(__p, __n, __c);
2456    return __null_terminate_at(__p, __n);
2457}
2458
2459template <class _CharT, class _Traits, class _Allocator>
2460_LIBCPP_CONSTEXPR_AFTER_CXX17
2461basic_string<_CharT, _Traits, _Allocator>&
2462basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c)
2463{
2464    pointer __p;
2465    if (__is_long())
2466    {
2467        __p = __get_long_pointer();
2468        __set_long_size(1);
2469    }
2470    else
2471    {
2472        __p = __get_short_pointer();
2473        __set_short_size(1);
2474    }
2475    traits_type::assign(*__p, __c);
2476    traits_type::assign(*++__p, value_type());
2477    __invalidate_iterators_past(1);
2478    return *this;
2479}
2480
2481template <class _CharT, class _Traits, class _Allocator>
2482_LIBCPP_CONSTEXPR_AFTER_CXX17
2483basic_string<_CharT, _Traits, _Allocator>&
2484basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
2485{
2486  if (this != &__str) {
2487    __copy_assign_alloc(__str);
2488    if (!__is_long()) {
2489      if (!__str.__is_long()) {
2490        __r_.first().__r = __str.__r_.first().__r;
2491      } else {
2492        return __assign_no_alias<true>(__str.data(), __str.size());
2493      }
2494    } else {
2495      return __assign_no_alias<false>(__str.data(), __str.size());
2496    }
2497  }
2498  return *this;
2499}
2500
2501#ifndef _LIBCPP_CXX03_LANG
2502
2503template <class _CharT, class _Traits, class _Allocator>
2504inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2505void
2506basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type)
2507    _NOEXCEPT_(__alloc_traits::is_always_equal::value)
2508{
2509    if (__alloc() != __str.__alloc())
2510        assign(__str);
2511    else
2512        __move_assign(__str, true_type());
2513}
2514
2515template <class _CharT, class _Traits, class _Allocator>
2516inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2517void
2518basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
2519#if _LIBCPP_STD_VER > 14
2520    _NOEXCEPT
2521#else
2522    _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
2523#endif
2524{
2525  if (__is_long()) {
2526    __alloc_traits::deallocate(__alloc(), __get_long_pointer(),
2527                               __get_long_cap());
2528#if _LIBCPP_STD_VER <= 14
2529    if (!is_nothrow_move_assignable<allocator_type>::value) {
2530      __set_short_size(0);
2531      traits_type::assign(__get_short_pointer()[0], value_type());
2532    }
2533#endif
2534  }
2535  __move_assign_alloc(__str);
2536  __r_.first() = __str.__r_.first();
2537  if (__libcpp_is_constant_evaluated()) {
2538    __str.__default_init();
2539  } else {
2540    __str.__set_short_size(0);
2541    traits_type::assign(__str.__get_short_pointer()[0], value_type());
2542  }
2543}
2544
2545template <class _CharT, class _Traits, class _Allocator>
2546inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2547basic_string<_CharT, _Traits, _Allocator>&
2548basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str)
2549    _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
2550{
2551    __move_assign(__str, integral_constant<bool,
2552          __alloc_traits::propagate_on_container_move_assignment::value>());
2553    return *this;
2554}
2555
2556#endif
2557
2558template <class _CharT, class _Traits, class _Allocator>
2559template<class _InputIterator>
2560_LIBCPP_CONSTEXPR_AFTER_CXX17
2561__enable_if_t
2562<
2563     __is_exactly_cpp17_input_iterator<_InputIterator>::value,
2564    basic_string<_CharT, _Traits, _Allocator>&
2565>
2566basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
2567{
2568    const basic_string __temp(__first, __last, __alloc());
2569    assign(__temp.data(), __temp.size());
2570    return *this;
2571}
2572
2573template <class _CharT, class _Traits, class _Allocator>
2574template<class _ForwardIterator>
2575_LIBCPP_CONSTEXPR_AFTER_CXX17
2576__enable_if_t
2577<
2578    __is_cpp17_forward_iterator<_ForwardIterator>::value,
2579    basic_string<_CharT, _Traits, _Allocator>&
2580>
2581basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
2582{
2583    size_type __cap = capacity();
2584    size_type __n = __string_is_trivial_iterator<_ForwardIterator>::value ?
2585        static_cast<size_type>(std::distance(__first, __last)) : 0;
2586
2587    if (__string_is_trivial_iterator<_ForwardIterator>::value &&
2588        (__cap >= __n || !__addr_in_range(*__first)))
2589    {
2590        if (__cap < __n)
2591        {
2592            size_type __sz = size();
2593            __grow_by(__cap, __n - __cap, __sz, 0, __sz);
2594        }
2595        pointer __p = __get_pointer();
2596        for (; __first != __last; ++__p, (void) ++__first)
2597            traits_type::assign(*__p, *__first);
2598        traits_type::assign(*__p, value_type());
2599        __set_size(__n);
2600        __invalidate_iterators_past(__n);
2601    }
2602    else
2603    {
2604        const basic_string __temp(__first, __last, __alloc());
2605        assign(__temp.data(), __temp.size());
2606    }
2607    return *this;
2608}
2609
2610template <class _CharT, class _Traits, class _Allocator>
2611_LIBCPP_CONSTEXPR_AFTER_CXX17
2612basic_string<_CharT, _Traits, _Allocator>&
2613basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n)
2614{
2615    size_type __sz = __str.size();
2616    if (__pos > __sz)
2617        __throw_out_of_range();
2618    return assign(__str.data() + __pos, std::min(__n, __sz - __pos));
2619}
2620
2621template <class _CharT, class _Traits, class _Allocator>
2622template <class _Tp>
2623_LIBCPP_CONSTEXPR_AFTER_CXX17
2624__enable_if_t
2625<
2626    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
2627    && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
2628    basic_string<_CharT, _Traits, _Allocator>&
2629>
2630basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __pos, size_type __n)
2631{
2632    __self_view __sv = __t;
2633    size_type __sz = __sv.size();
2634    if (__pos > __sz)
2635        __throw_out_of_range();
2636    return assign(__sv.data() + __pos, std::min(__n, __sz - __pos));
2637}
2638
2639
2640template <class _CharT, class _Traits, class _Allocator>
2641_LIBCPP_CONSTEXPR_AFTER_CXX17
2642basic_string<_CharT, _Traits, _Allocator>&
2643basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) {
2644  return __assign_external(__s, traits_type::length(__s));
2645}
2646
2647template <class _CharT, class _Traits, class _Allocator>
2648_LIBCPP_CONSTEXPR_AFTER_CXX17
2649basic_string<_CharT, _Traits, _Allocator>&
2650basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s)
2651{
2652    _LIBCPP_ASSERT(__s != nullptr, "string::assign received nullptr");
2653    return __builtin_constant_p(*__s)
2654               ? (__fits_in_sso(traits_type::length(__s))
2655                      ? __assign_short(__s, traits_type::length(__s))
2656                      : __assign_external(__s, traits_type::length(__s)))
2657               : __assign_external(__s);
2658}
2659// append
2660
2661template <class _CharT, class _Traits, class _Allocator>
2662_LIBCPP_CONSTEXPR_AFTER_CXX17
2663basic_string<_CharT, _Traits, _Allocator>&
2664basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n)
2665{
2666    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::append received nullptr");
2667    size_type __cap = capacity();
2668    size_type __sz = size();
2669    if (__cap - __sz >= __n)
2670    {
2671        if (__n)
2672        {
2673            value_type* __p = std::__to_address(__get_pointer());
2674            traits_type::copy(__p + __sz, __s, __n);
2675            __sz += __n;
2676            __set_size(__sz);
2677            traits_type::assign(__p[__sz], value_type());
2678        }
2679    }
2680    else
2681        __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s);
2682    return *this;
2683}
2684
2685template <class _CharT, class _Traits, class _Allocator>
2686_LIBCPP_CONSTEXPR_AFTER_CXX17
2687basic_string<_CharT, _Traits, _Allocator>&
2688basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c)
2689{
2690    if (__n)
2691    {
2692        size_type __cap = capacity();
2693        size_type __sz = size();
2694        if (__cap - __sz < __n)
2695            __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
2696        pointer __p = __get_pointer();
2697        traits_type::assign(std::__to_address(__p) + __sz, __n, __c);
2698        __sz += __n;
2699        __set_size(__sz);
2700        traits_type::assign(__p[__sz], value_type());
2701    }
2702    return *this;
2703}
2704
2705template <class _CharT, class _Traits, class _Allocator>
2706_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void
2707basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n)
2708{
2709    if (__n)
2710    {
2711        size_type __cap = capacity();
2712        size_type __sz = size();
2713        if (__cap - __sz < __n)
2714            __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
2715        pointer __p = __get_pointer();
2716        __sz += __n;
2717        __set_size(__sz);
2718        traits_type::assign(__p[__sz], value_type());
2719    }
2720}
2721
2722template <class _CharT, class _Traits, class _Allocator>
2723_LIBCPP_CONSTEXPR_AFTER_CXX17
2724void
2725basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
2726{
2727    bool __is_short = !__is_long();
2728    size_type __cap;
2729    size_type __sz;
2730    if (__is_short)
2731    {
2732        __cap = __min_cap - 1;
2733        __sz = __get_short_size();
2734    }
2735    else
2736    {
2737        __cap = __get_long_cap() - 1;
2738        __sz = __get_long_size();
2739    }
2740    if (__sz == __cap)
2741    {
2742        __grow_by(__cap, 1, __sz, __sz, 0);
2743        __is_short = false; // the string is always long after __grow_by
2744    }
2745    pointer __p = __get_pointer();
2746    if (__is_short)
2747    {
2748        __p = __get_short_pointer() + __sz;
2749        __set_short_size(__sz+1);
2750    }
2751    else
2752    {
2753        __p = __get_long_pointer() + __sz;
2754        __set_long_size(__sz+1);
2755    }
2756    traits_type::assign(*__p, __c);
2757    traits_type::assign(*++__p, value_type());
2758}
2759
2760template <class _CharT, class _Traits, class _Allocator>
2761template<class _ForwardIterator>
2762_LIBCPP_CONSTEXPR_AFTER_CXX17
2763__enable_if_t
2764<
2765    __is_cpp17_forward_iterator<_ForwardIterator>::value,
2766    basic_string<_CharT, _Traits, _Allocator>&
2767>
2768basic_string<_CharT, _Traits, _Allocator>::append(
2769    _ForwardIterator __first, _ForwardIterator __last)
2770{
2771    size_type __sz = size();
2772    size_type __cap = capacity();
2773    size_type __n = static_cast<size_type>(std::distance(__first, __last));
2774    if (__n)
2775    {
2776        if (__string_is_trivial_iterator<_ForwardIterator>::value &&
2777            !__addr_in_range(*__first))
2778        {
2779            if (__cap - __sz < __n)
2780                __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
2781            pointer __p = __get_pointer() + __sz;
2782            for (; __first != __last; ++__p, (void) ++__first)
2783                traits_type::assign(*__p, *__first);
2784            traits_type::assign(*__p, value_type());
2785            __set_size(__sz + __n);
2786        }
2787        else
2788        {
2789            const basic_string __temp(__first, __last, __alloc());
2790            append(__temp.data(), __temp.size());
2791        }
2792    }
2793    return *this;
2794}
2795
2796template <class _CharT, class _Traits, class _Allocator>
2797inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2798basic_string<_CharT, _Traits, _Allocator>&
2799basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str)
2800{
2801    return append(__str.data(), __str.size());
2802}
2803
2804template <class _CharT, class _Traits, class _Allocator>
2805_LIBCPP_CONSTEXPR_AFTER_CXX17
2806basic_string<_CharT, _Traits, _Allocator>&
2807basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n)
2808{
2809    size_type __sz = __str.size();
2810    if (__pos > __sz)
2811        __throw_out_of_range();
2812    return append(__str.data() + __pos, std::min(__n, __sz - __pos));
2813}
2814
2815template <class _CharT, class _Traits, class _Allocator>
2816template <class _Tp>
2817_LIBCPP_CONSTEXPR_AFTER_CXX17
2818    __enable_if_t
2819    <
2820        __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
2821        basic_string<_CharT, _Traits, _Allocator>&
2822    >
2823basic_string<_CharT, _Traits, _Allocator>::append(const _Tp & __t, size_type __pos, size_type __n)
2824{
2825    __self_view __sv = __t;
2826    size_type __sz = __sv.size();
2827    if (__pos > __sz)
2828        __throw_out_of_range();
2829    return append(__sv.data() + __pos, std::min(__n, __sz - __pos));
2830}
2831
2832template <class _CharT, class _Traits, class _Allocator>
2833_LIBCPP_CONSTEXPR_AFTER_CXX17
2834basic_string<_CharT, _Traits, _Allocator>&
2835basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s)
2836{
2837    _LIBCPP_ASSERT(__s != nullptr, "string::append received nullptr");
2838    return append(__s, traits_type::length(__s));
2839}
2840
2841// insert
2842
2843template <class _CharT, class _Traits, class _Allocator>
2844_LIBCPP_CONSTEXPR_AFTER_CXX17
2845basic_string<_CharT, _Traits, _Allocator>&
2846basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n)
2847{
2848    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::insert received nullptr");
2849    size_type __sz = size();
2850    if (__pos > __sz)
2851        __throw_out_of_range();
2852    size_type __cap = capacity();
2853    if (__libcpp_is_constant_evaluated()) {
2854        if (__cap - __sz >= __n)
2855            __grow_by_and_replace(__cap, 0, __sz, __pos, 0, __n, __s);
2856        else
2857            __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
2858        return *this;
2859    }
2860    if (__cap - __sz >= __n)
2861    {
2862        if (__n)
2863        {
2864            value_type* __p = std::__to_address(__get_pointer());
2865            size_type __n_move = __sz - __pos;
2866            if (__n_move != 0)
2867            {
2868                if (__p + __pos <= __s && __s < __p + __sz)
2869                    __s += __n;
2870                traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
2871            }
2872            traits_type::move(__p + __pos, __s, __n);
2873            __sz += __n;
2874            __set_size(__sz);
2875            traits_type::assign(__p[__sz], value_type());
2876        }
2877    }
2878    else
2879        __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
2880    return *this;
2881}
2882
2883template <class _CharT, class _Traits, class _Allocator>
2884_LIBCPP_CONSTEXPR_AFTER_CXX17
2885basic_string<_CharT, _Traits, _Allocator>&
2886basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c)
2887{
2888    size_type __sz = size();
2889    if (__pos > __sz)
2890        __throw_out_of_range();
2891    if (__n)
2892    {
2893        size_type __cap = capacity();
2894        value_type* __p;
2895        if (__cap - __sz >= __n)
2896        {
2897            __p = std::__to_address(__get_pointer());
2898            size_type __n_move = __sz - __pos;
2899            if (__n_move != 0)
2900                traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
2901        }
2902        else
2903        {
2904            __grow_by(__cap, __sz + __n - __cap, __sz, __pos, 0, __n);
2905            __p = std::__to_address(__get_long_pointer());
2906        }
2907        traits_type::assign(__p + __pos, __n, __c);
2908        __sz += __n;
2909        __set_size(__sz);
2910        traits_type::assign(__p[__sz], value_type());
2911    }
2912    return *this;
2913}
2914
2915template <class _CharT, class _Traits, class _Allocator>
2916template<class _InputIterator>
2917_LIBCPP_CONSTEXPR_AFTER_CXX17
2918__enable_if_t
2919<
2920   __is_exactly_cpp17_input_iterator<_InputIterator>::value,
2921   typename basic_string<_CharT, _Traits, _Allocator>::iterator
2922>
2923basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last)
2924{
2925  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
2926                       "string::insert(iterator, range) called with an iterator not"
2927                       " referring to this string");
2928  const basic_string __temp(__first, __last, __alloc());
2929  return insert(__pos, __temp.data(), __temp.data() + __temp.size());
2930}
2931
2932template <class _CharT, class _Traits, class _Allocator>
2933template<class _ForwardIterator>
2934_LIBCPP_CONSTEXPR_AFTER_CXX17
2935__enable_if_t
2936<
2937    __is_cpp17_forward_iterator<_ForwardIterator>::value,
2938    typename basic_string<_CharT, _Traits, _Allocator>::iterator
2939>
2940basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last)
2941{
2942    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
2943                         "string::insert(iterator, range) called with an iterator not referring to this string");
2944
2945    size_type __ip = static_cast<size_type>(__pos - begin());
2946    size_type __n = static_cast<size_type>(std::distance(__first, __last));
2947    if (__n == 0)
2948        return begin() + __ip;
2949
2950    if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first))
2951    {
2952        return __insert_from_safe_copy(__n, __ip, __first, __last);
2953    }
2954    else
2955    {
2956        const basic_string __temp(__first, __last, __alloc());
2957        return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end());
2958    }
2959}
2960
2961template <class _CharT, class _Traits, class _Allocator>
2962inline _LIBCPP_CONSTEXPR_AFTER_CXX17
2963basic_string<_CharT, _Traits, _Allocator>&
2964basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str)
2965{
2966    return insert(__pos1, __str.data(), __str.size());
2967}
2968
2969template <class _CharT, class _Traits, class _Allocator>
2970_LIBCPP_CONSTEXPR_AFTER_CXX17
2971basic_string<_CharT, _Traits, _Allocator>&
2972basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str,
2973                                                  size_type __pos2, size_type __n)
2974{
2975    size_type __str_sz = __str.size();
2976    if (__pos2 > __str_sz)
2977        __throw_out_of_range();
2978    return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2));
2979}
2980
2981template <class _CharT, class _Traits, class _Allocator>
2982template <class _Tp>
2983_LIBCPP_CONSTEXPR_AFTER_CXX17
2984__enable_if_t
2985<
2986    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
2987    basic_string<_CharT, _Traits, _Allocator>&
2988>
2989basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t,
2990                                                  size_type __pos2, size_type __n)
2991{
2992    __self_view __sv = __t;
2993    size_type __str_sz = __sv.size();
2994    if (__pos2 > __str_sz)
2995        __throw_out_of_range();
2996    return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2));
2997}
2998
2999template <class _CharT, class _Traits, class _Allocator>
3000_LIBCPP_CONSTEXPR_AFTER_CXX17
3001basic_string<_CharT, _Traits, _Allocator>&
3002basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s)
3003{
3004    _LIBCPP_ASSERT(__s != nullptr, "string::insert received nullptr");
3005    return insert(__pos, __s, traits_type::length(__s));
3006}
3007
3008template <class _CharT, class _Traits, class _Allocator>
3009_LIBCPP_CONSTEXPR_AFTER_CXX17
3010typename basic_string<_CharT, _Traits, _Allocator>::iterator
3011basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c)
3012{
3013    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
3014                         "string::insert(iterator, character) called with an iterator not"
3015                         " referring to this string");
3016
3017    size_type __ip = static_cast<size_type>(__pos - begin());
3018    size_type __sz = size();
3019    size_type __cap = capacity();
3020    value_type* __p;
3021    if (__cap == __sz)
3022    {
3023        __grow_by(__cap, 1, __sz, __ip, 0, 1);
3024        __p = std::__to_address(__get_long_pointer());
3025    }
3026    else
3027    {
3028        __p = std::__to_address(__get_pointer());
3029        size_type __n_move = __sz - __ip;
3030        if (__n_move != 0)
3031            traits_type::move(__p + __ip + 1, __p + __ip, __n_move);
3032    }
3033    traits_type::assign(__p[__ip], __c);
3034    traits_type::assign(__p[++__sz], value_type());
3035    __set_size(__sz);
3036    return begin() + static_cast<difference_type>(__ip);
3037}
3038
3039template <class _CharT, class _Traits, class _Allocator>
3040inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3041typename basic_string<_CharT, _Traits, _Allocator>::iterator
3042basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, size_type __n, value_type __c)
3043{
3044  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
3045                       "string::insert(iterator, n, value) called with an iterator not"
3046                       " referring to this string");
3047  difference_type __p = __pos - begin();
3048  insert(static_cast<size_type>(__p), __n, __c);
3049  return begin() + __p;
3050}
3051
3052// replace
3053
3054template <class _CharT, class _Traits, class _Allocator>
3055_LIBCPP_CONSTEXPR_AFTER_CXX17
3056basic_string<_CharT, _Traits, _Allocator>&
3057basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2)
3058    _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
3059{
3060    _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::replace received nullptr");
3061    size_type __sz = size();
3062    if (__pos > __sz)
3063        __throw_out_of_range();
3064    __n1 = std::min(__n1, __sz - __pos);
3065    size_type __cap = capacity();
3066    if (__cap - __sz + __n1 >= __n2)
3067    {
3068        if (__libcpp_is_constant_evaluated()) {
3069            __grow_by_and_replace(__cap, 0, __sz, __pos, __n1, __n2, __s);
3070            return *this;
3071        }
3072        value_type* __p = std::__to_address(__get_pointer());
3073        if (__n1 != __n2)
3074        {
3075            size_type __n_move = __sz - __pos - __n1;
3076            if (__n_move != 0)
3077            {
3078                if (__n1 > __n2)
3079                {
3080                    traits_type::move(__p + __pos, __s, __n2);
3081                    traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3082                    return __null_terminate_at(__p, __sz + (__n2 - __n1));
3083                }
3084                if (__p + __pos < __s && __s < __p + __sz)
3085                {
3086                    if (__p + __pos + __n1 <= __s)
3087                        __s += __n2 - __n1;
3088                    else // __p + __pos < __s < __p + __pos + __n1
3089                    {
3090                        traits_type::move(__p + __pos, __s, __n1);
3091                        __pos += __n1;
3092                        __s += __n2;
3093                        __n2 -= __n1;
3094                        __n1 = 0;
3095                    }
3096                }
3097                traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3098            }
3099        }
3100        traits_type::move(__p + __pos, __s, __n2);
3101        return __null_terminate_at(__p, __sz + (__n2 - __n1));
3102    }
3103    else
3104        __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s);
3105    return *this;
3106}
3107
3108template <class _CharT, class _Traits, class _Allocator>
3109_LIBCPP_CONSTEXPR_AFTER_CXX17
3110basic_string<_CharT, _Traits, _Allocator>&
3111basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c)
3112{
3113    size_type __sz = size();
3114    if (__pos > __sz)
3115        __throw_out_of_range();
3116    __n1 = std::min(__n1, __sz - __pos);
3117    size_type __cap = capacity();
3118    value_type* __p;
3119    if (__cap - __sz + __n1 >= __n2)
3120    {
3121        __p = std::__to_address(__get_pointer());
3122        if (__n1 != __n2)
3123        {
3124            size_type __n_move = __sz - __pos - __n1;
3125            if (__n_move != 0)
3126                traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
3127        }
3128    }
3129    else
3130    {
3131        __grow_by(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2);
3132        __p = std::__to_address(__get_long_pointer());
3133    }
3134    traits_type::assign(__p + __pos, __n2, __c);
3135    return __null_terminate_at(__p, __sz - (__n1 - __n2));
3136}
3137
3138template <class _CharT, class _Traits, class _Allocator>
3139template<class _InputIterator>
3140_LIBCPP_CONSTEXPR_AFTER_CXX17
3141__enable_if_t
3142<
3143    __is_cpp17_input_iterator<_InputIterator>::value,
3144    basic_string<_CharT, _Traits, _Allocator>&
3145>
3146basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,
3147                                                   _InputIterator __j1, _InputIterator __j2)
3148{
3149    const basic_string __temp(__j1, __j2, __alloc());
3150    return replace(__i1, __i2, __temp);
3151}
3152
3153template <class _CharT, class _Traits, class _Allocator>
3154inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3155basic_string<_CharT, _Traits, _Allocator>&
3156basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str)
3157{
3158    return replace(__pos1, __n1, __str.data(), __str.size());
3159}
3160
3161template <class _CharT, class _Traits, class _Allocator>
3162_LIBCPP_CONSTEXPR_AFTER_CXX17
3163basic_string<_CharT, _Traits, _Allocator>&
3164basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str,
3165                                                   size_type __pos2, size_type __n2)
3166{
3167    size_type __str_sz = __str.size();
3168    if (__pos2 > __str_sz)
3169        __throw_out_of_range();
3170    return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2));
3171}
3172
3173template <class _CharT, class _Traits, class _Allocator>
3174template <class _Tp>
3175_LIBCPP_CONSTEXPR_AFTER_CXX17
3176__enable_if_t
3177<
3178    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
3179    basic_string<_CharT, _Traits, _Allocator>&
3180>
3181basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const _Tp& __t,
3182                                                   size_type __pos2, size_type __n2)
3183{
3184    __self_view __sv = __t;
3185    size_type __str_sz = __sv.size();
3186    if (__pos2 > __str_sz)
3187        __throw_out_of_range();
3188    return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2));
3189}
3190
3191template <class _CharT, class _Traits, class _Allocator>
3192_LIBCPP_CONSTEXPR_AFTER_CXX17
3193basic_string<_CharT, _Traits, _Allocator>&
3194basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s)
3195{
3196    _LIBCPP_ASSERT(__s != nullptr, "string::replace received nullptr");
3197    return replace(__pos, __n1, __s, traits_type::length(__s));
3198}
3199
3200template <class _CharT, class _Traits, class _Allocator>
3201inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3202basic_string<_CharT, _Traits, _Allocator>&
3203basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const basic_string& __str)
3204{
3205    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1),
3206                   __str.data(), __str.size());
3207}
3208
3209template <class _CharT, class _Traits, class _Allocator>
3210inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3211basic_string<_CharT, _Traits, _Allocator>&
3212basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n)
3213{
3214    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s, __n);
3215}
3216
3217template <class _CharT, class _Traits, class _Allocator>
3218inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3219basic_string<_CharT, _Traits, _Allocator>&
3220basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s)
3221{
3222    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s);
3223}
3224
3225template <class _CharT, class _Traits, class _Allocator>
3226inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3227basic_string<_CharT, _Traits, _Allocator>&
3228basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c)
3229{
3230    return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c);
3231}
3232
3233// erase
3234
3235// 'externally instantiated' erase() implementation, called when __n != npos.
3236// Does not check __pos against size()
3237template <class _CharT, class _Traits, class _Allocator>
3238_LIBCPP_CONSTEXPR_AFTER_CXX17
3239void
3240basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(
3241    size_type __pos, size_type __n)
3242{
3243    if (__n)
3244    {
3245        size_type __sz = size();
3246        value_type* __p = std::__to_address(__get_pointer());
3247        __n = std::min(__n, __sz - __pos);
3248        size_type __n_move = __sz - __pos - __n;
3249        if (__n_move != 0)
3250            traits_type::move(__p + __pos, __p + __pos + __n, __n_move);
3251        __null_terminate_at(__p, __sz - __n);
3252    }
3253}
3254
3255template <class _CharT, class _Traits, class _Allocator>
3256_LIBCPP_CONSTEXPR_AFTER_CXX17
3257basic_string<_CharT, _Traits, _Allocator>&
3258basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos,
3259                                                 size_type __n) {
3260  if (__pos > size())
3261    __throw_out_of_range();
3262  if (__n == npos) {
3263    __erase_to_end(__pos);
3264  } else {
3265    __erase_external_with_move(__pos, __n);
3266  }
3267  return *this;
3268}
3269
3270template <class _CharT, class _Traits, class _Allocator>
3271inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3272typename basic_string<_CharT, _Traits, _Allocator>::iterator
3273basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos)
3274{
3275  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
3276                       "string::erase(iterator) called with an iterator not"
3277                       " referring to this string");
3278
3279  _LIBCPP_ASSERT(__pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator");
3280  iterator __b = begin();
3281  size_type __r = static_cast<size_type>(__pos - __b);
3282  erase(__r, 1);
3283  return __b + static_cast<difference_type>(__r);
3284}
3285
3286template <class _CharT, class _Traits, class _Allocator>
3287inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3288typename basic_string<_CharT, _Traits, _Allocator>::iterator
3289basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last)
3290{
3291  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
3292                       "string::erase(iterator,  iterator) called with an iterator not"
3293                       " referring to this string");
3294
3295  _LIBCPP_ASSERT(__first <= __last, "string::erase(first, last) called with invalid range");
3296  iterator __b = begin();
3297  size_type __r = static_cast<size_type>(__first - __b);
3298  erase(__r, static_cast<size_type>(__last - __first));
3299  return __b + static_cast<difference_type>(__r);
3300}
3301
3302template <class _CharT, class _Traits, class _Allocator>
3303inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3304void
3305basic_string<_CharT, _Traits, _Allocator>::pop_back()
3306{
3307    _LIBCPP_ASSERT(!empty(), "string::pop_back(): string is already empty");
3308    __erase_to_end(size() - 1);
3309}
3310
3311template <class _CharT, class _Traits, class _Allocator>
3312inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3313void
3314basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT
3315{
3316    std::__debug_db_invalidate_all(this);
3317    if (__is_long())
3318    {
3319        traits_type::assign(*__get_long_pointer(), value_type());
3320        __set_long_size(0);
3321    }
3322    else
3323    {
3324        traits_type::assign(*__get_short_pointer(), value_type());
3325        __set_short_size(0);
3326    }
3327}
3328
3329template <class _CharT, class _Traits, class _Allocator>
3330inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3331void
3332basic_string<_CharT, _Traits, _Allocator>::__erase_to_end(size_type __pos)
3333{
3334  __null_terminate_at(std::__to_address(__get_pointer()), __pos);
3335}
3336
3337template <class _CharT, class _Traits, class _Allocator>
3338_LIBCPP_CONSTEXPR_AFTER_CXX17
3339void
3340basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c)
3341{
3342    size_type __sz = size();
3343    if (__n > __sz)
3344        append(__n - __sz, __c);
3345    else
3346        __erase_to_end(__n);
3347}
3348
3349template <class _CharT, class _Traits, class _Allocator>
3350_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void
3351basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n)
3352{
3353    size_type __sz = size();
3354    if (__n > __sz) {
3355       __append_default_init(__n - __sz);
3356    } else
3357        __erase_to_end(__n);
3358}
3359
3360template <class _CharT, class _Traits, class _Allocator>
3361inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3362typename basic_string<_CharT, _Traits, _Allocator>::size_type
3363basic_string<_CharT, _Traits, _Allocator>::max_size() const _NOEXCEPT
3364{
3365    size_type __m = __alloc_traits::max_size(__alloc());
3366    if (__m <= std::numeric_limits<size_type>::max() / 2) {
3367        return __m - __alignment;
3368    } else {
3369        bool __uses_lsb = __endian_factor == 2;
3370        return __uses_lsb ? __m - __alignment : (__m / 2) - __alignment;
3371    }
3372}
3373
3374template <class _CharT, class _Traits, class _Allocator>
3375_LIBCPP_CONSTEXPR_AFTER_CXX17
3376void
3377basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity)
3378{
3379    if (__requested_capacity > max_size())
3380        __throw_length_error();
3381
3382    // Make sure reserve(n) never shrinks. This is technically only required in C++20
3383    // and later (since P0966R1), however we provide consistent behavior in all Standard
3384    // modes because this function is instantiated in the shared library.
3385    if (__requested_capacity <= capacity())
3386        return;
3387
3388    size_type __target_capacity = std::max(__requested_capacity, size());
3389    __target_capacity = __recommend(__target_capacity);
3390    if (__target_capacity == capacity()) return;
3391
3392    __shrink_or_extend(__target_capacity);
3393}
3394
3395template <class _CharT, class _Traits, class _Allocator>
3396inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3397void
3398basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT
3399{
3400    size_type __target_capacity = __recommend(size());
3401    if (__target_capacity == capacity()) return;
3402
3403    __shrink_or_extend(__target_capacity);
3404}
3405
3406template <class _CharT, class _Traits, class _Allocator>
3407inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3408void
3409basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity)
3410{
3411    size_type __cap = capacity();
3412    size_type __sz = size();
3413
3414    pointer __new_data, __p;
3415    bool __was_long, __now_long;
3416    if (__fits_in_sso(__target_capacity))
3417    {
3418        __was_long = true;
3419        __now_long = false;
3420        __new_data = __get_short_pointer();
3421        __p = __get_long_pointer();
3422    }
3423    else
3424    {
3425        if (__target_capacity > __cap) {
3426            auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
3427            __new_data = __allocation.ptr;
3428            __target_capacity = __allocation.count - 1;
3429        }
3430        else
3431        {
3432        #ifndef _LIBCPP_NO_EXCEPTIONS
3433            try
3434            {
3435        #endif // _LIBCPP_NO_EXCEPTIONS
3436                auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
3437                __new_data = __allocation.ptr;
3438                __target_capacity = __allocation.count - 1;
3439        #ifndef _LIBCPP_NO_EXCEPTIONS
3440            }
3441            catch (...)
3442            {
3443                return;
3444            }
3445        #else  // _LIBCPP_NO_EXCEPTIONS
3446            if (__new_data == nullptr)
3447                return;
3448        #endif // _LIBCPP_NO_EXCEPTIONS
3449        }
3450        __begin_lifetime(__new_data, __target_capacity + 1);
3451        __now_long = true;
3452        __was_long = __is_long();
3453        __p = __get_pointer();
3454    }
3455    traits_type::copy(std::__to_address(__new_data),
3456                      std::__to_address(__p), size()+1);
3457    if (__was_long)
3458        __alloc_traits::deallocate(__alloc(), __p, __cap+1);
3459    if (__now_long)
3460    {
3461        __set_long_cap(__target_capacity+1);
3462        __set_long_size(__sz);
3463        __set_long_pointer(__new_data);
3464    }
3465    else
3466        __set_short_size(__sz);
3467    std::__debug_db_invalidate_all(this);
3468}
3469
3470template <class _CharT, class _Traits, class _Allocator>
3471inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3472typename basic_string<_CharT, _Traits, _Allocator>::const_reference
3473basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const _NOEXCEPT
3474{
3475    _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
3476    return *(data() + __pos);
3477}
3478
3479template <class _CharT, class _Traits, class _Allocator>
3480inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3481typename basic_string<_CharT, _Traits, _Allocator>::reference
3482basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) _NOEXCEPT
3483{
3484    _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
3485    return *(__get_pointer() + __pos);
3486}
3487
3488template <class _CharT, class _Traits, class _Allocator>
3489_LIBCPP_CONSTEXPR_AFTER_CXX17
3490typename basic_string<_CharT, _Traits, _Allocator>::const_reference
3491basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
3492{
3493    if (__n >= size())
3494        __throw_out_of_range();
3495    return (*this)[__n];
3496}
3497
3498template <class _CharT, class _Traits, class _Allocator>
3499_LIBCPP_CONSTEXPR_AFTER_CXX17
3500typename basic_string<_CharT, _Traits, _Allocator>::reference
3501basic_string<_CharT, _Traits, _Allocator>::at(size_type __n)
3502{
3503    if (__n >= size())
3504        __throw_out_of_range();
3505    return (*this)[__n];
3506}
3507
3508template <class _CharT, class _Traits, class _Allocator>
3509inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3510typename basic_string<_CharT, _Traits, _Allocator>::reference
3511basic_string<_CharT, _Traits, _Allocator>::front() _NOEXCEPT
3512{
3513    _LIBCPP_ASSERT(!empty(), "string::front(): string is empty");
3514    return *__get_pointer();
3515}
3516
3517template <class _CharT, class _Traits, class _Allocator>
3518inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3519typename basic_string<_CharT, _Traits, _Allocator>::const_reference
3520basic_string<_CharT, _Traits, _Allocator>::front() const _NOEXCEPT
3521{
3522    _LIBCPP_ASSERT(!empty(), "string::front(): string is empty");
3523    return *data();
3524}
3525
3526template <class _CharT, class _Traits, class _Allocator>
3527inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3528typename basic_string<_CharT, _Traits, _Allocator>::reference
3529basic_string<_CharT, _Traits, _Allocator>::back() _NOEXCEPT
3530{
3531    _LIBCPP_ASSERT(!empty(), "string::back(): string is empty");
3532    return *(__get_pointer() + size() - 1);
3533}
3534
3535template <class _CharT, class _Traits, class _Allocator>
3536inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3537typename basic_string<_CharT, _Traits, _Allocator>::const_reference
3538basic_string<_CharT, _Traits, _Allocator>::back() const _NOEXCEPT
3539{
3540    _LIBCPP_ASSERT(!empty(), "string::back(): string is empty");
3541    return *(data() + size() - 1);
3542}
3543
3544template <class _CharT, class _Traits, class _Allocator>
3545_LIBCPP_CONSTEXPR_AFTER_CXX17
3546typename basic_string<_CharT, _Traits, _Allocator>::size_type
3547basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const
3548{
3549    size_type __sz = size();
3550    if (__pos > __sz)
3551        __throw_out_of_range();
3552    size_type __rlen = std::min(__n, __sz - __pos);
3553    traits_type::copy(__s, data() + __pos, __rlen);
3554    return __rlen;
3555}
3556
3557template <class _CharT, class _Traits, class _Allocator>
3558inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3559basic_string<_CharT, _Traits, _Allocator>
3560basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n) const
3561{
3562    return basic_string(*this, __pos, __n, __alloc());
3563}
3564
3565template <class _CharT, class _Traits, class _Allocator>
3566inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3567void
3568basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
3569#if _LIBCPP_STD_VER >= 14
3570        _NOEXCEPT
3571#else
3572        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
3573                    __is_nothrow_swappable<allocator_type>::value)
3574#endif
3575{
3576    if (!__is_long())
3577        std::__debug_db_invalidate_all(this);
3578    if (!__str.__is_long())
3579        std::__debug_db_invalidate_all(&__str);
3580    std::__debug_db_swap(this, &__str);
3581
3582    _LIBCPP_ASSERT(
3583        __alloc_traits::propagate_on_container_swap::value ||
3584        __alloc_traits::is_always_equal::value ||
3585        __alloc() == __str.__alloc(), "swapping non-equal allocators");
3586    std::swap(__r_.first(), __str.__r_.first());
3587    std::__swap_allocator(__alloc(), __str.__alloc());
3588}
3589
3590// find
3591
3592template <class _Traits>
3593struct _LIBCPP_HIDDEN __traits_eq
3594{
3595    typedef typename _Traits::char_type char_type;
3596    _LIBCPP_HIDE_FROM_ABI
3597    bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT
3598        {return _Traits::eq(__x, __y);}
3599};
3600
3601template<class _CharT, class _Traits, class _Allocator>
3602_LIBCPP_CONSTEXPR_AFTER_CXX17
3603typename basic_string<_CharT, _Traits, _Allocator>::size_type
3604basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
3605                                                size_type __pos,
3606                                                size_type __n) const _NOEXCEPT
3607{
3608    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find(): received nullptr");
3609    return __str_find<value_type, size_type, traits_type, npos>
3610        (data(), size(), __s, __pos, __n);
3611}
3612
3613template<class _CharT, class _Traits, class _Allocator>
3614inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3615typename basic_string<_CharT, _Traits, _Allocator>::size_type
3616basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str,
3617                                                size_type __pos) const _NOEXCEPT
3618{
3619    return __str_find<value_type, size_type, traits_type, npos>
3620        (data(), size(), __str.data(), __pos, __str.size());
3621}
3622
3623template<class _CharT, class _Traits, class _Allocator>
3624template <class _Tp>
3625_LIBCPP_CONSTEXPR_AFTER_CXX17
3626__enable_if_t
3627<
3628    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3629    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3630>
3631basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t,
3632                                                size_type __pos) const _NOEXCEPT
3633{
3634    __self_view __sv = __t;
3635    return __str_find<value_type, size_type, traits_type, npos>
3636        (data(), size(), __sv.data(), __pos, __sv.size());
3637}
3638
3639template<class _CharT, class _Traits, class _Allocator>
3640inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3641typename basic_string<_CharT, _Traits, _Allocator>::size_type
3642basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
3643                                                size_type __pos) const _NOEXCEPT
3644{
3645    _LIBCPP_ASSERT(__s != nullptr, "string::find(): received nullptr");
3646    return __str_find<value_type, size_type, traits_type, npos>
3647        (data(), size(), __s, __pos, traits_type::length(__s));
3648}
3649
3650template<class _CharT, class _Traits, class _Allocator>
3651_LIBCPP_CONSTEXPR_AFTER_CXX17
3652typename basic_string<_CharT, _Traits, _Allocator>::size_type
3653basic_string<_CharT, _Traits, _Allocator>::find(value_type __c,
3654                                                size_type __pos) const _NOEXCEPT
3655{
3656    return __str_find<value_type, size_type, traits_type, npos>
3657        (data(), size(), __c, __pos);
3658}
3659
3660// rfind
3661
3662template<class _CharT, class _Traits, class _Allocator>
3663_LIBCPP_CONSTEXPR_AFTER_CXX17
3664typename basic_string<_CharT, _Traits, _Allocator>::size_type
3665basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
3666                                                 size_type __pos,
3667                                                 size_type __n) const _NOEXCEPT
3668{
3669    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::rfind(): received nullptr");
3670    return __str_rfind<value_type, size_type, traits_type, npos>
3671        (data(), size(), __s, __pos, __n);
3672}
3673
3674template<class _CharT, class _Traits, class _Allocator>
3675inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3676typename basic_string<_CharT, _Traits, _Allocator>::size_type
3677basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str,
3678                                                 size_type __pos) const _NOEXCEPT
3679{
3680    return __str_rfind<value_type, size_type, traits_type, npos>
3681        (data(), size(), __str.data(), __pos, __str.size());
3682}
3683
3684template<class _CharT, class _Traits, class _Allocator>
3685template <class _Tp>
3686_LIBCPP_CONSTEXPR_AFTER_CXX17
3687__enable_if_t
3688<
3689    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3690    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3691>
3692basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t,
3693                                                size_type __pos) const _NOEXCEPT
3694{
3695    __self_view __sv = __t;
3696    return __str_rfind<value_type, size_type, traits_type, npos>
3697        (data(), size(), __sv.data(), __pos, __sv.size());
3698}
3699
3700template<class _CharT, class _Traits, class _Allocator>
3701inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3702typename basic_string<_CharT, _Traits, _Allocator>::size_type
3703basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
3704                                                 size_type __pos) const _NOEXCEPT
3705{
3706    _LIBCPP_ASSERT(__s != nullptr, "string::rfind(): received nullptr");
3707    return __str_rfind<value_type, size_type, traits_type, npos>
3708        (data(), size(), __s, __pos, traits_type::length(__s));
3709}
3710
3711template<class _CharT, class _Traits, class _Allocator>
3712_LIBCPP_CONSTEXPR_AFTER_CXX17
3713typename basic_string<_CharT, _Traits, _Allocator>::size_type
3714basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c,
3715                                                 size_type __pos) const _NOEXCEPT
3716{
3717    return __str_rfind<value_type, size_type, traits_type, npos>
3718        (data(), size(), __c, __pos);
3719}
3720
3721// find_first_of
3722
3723template<class _CharT, class _Traits, class _Allocator>
3724_LIBCPP_CONSTEXPR_AFTER_CXX17
3725typename basic_string<_CharT, _Traits, _Allocator>::size_type
3726basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
3727                                                         size_type __pos,
3728                                                         size_type __n) const _NOEXCEPT
3729{
3730    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr");
3731    return __str_find_first_of<value_type, size_type, traits_type, npos>
3732        (data(), size(), __s, __pos, __n);
3733}
3734
3735template<class _CharT, class _Traits, class _Allocator>
3736inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3737typename basic_string<_CharT, _Traits, _Allocator>::size_type
3738basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str,
3739                                                         size_type __pos) const _NOEXCEPT
3740{
3741    return __str_find_first_of<value_type, size_type, traits_type, npos>
3742        (data(), size(), __str.data(), __pos, __str.size());
3743}
3744
3745template<class _CharT, class _Traits, class _Allocator>
3746template <class _Tp>
3747_LIBCPP_CONSTEXPR_AFTER_CXX17
3748__enable_if_t
3749<
3750    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3751    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3752>
3753basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t,
3754                                                size_type __pos) const _NOEXCEPT
3755{
3756    __self_view __sv = __t;
3757    return __str_find_first_of<value_type, size_type, traits_type, npos>
3758        (data(), size(), __sv.data(), __pos, __sv.size());
3759}
3760
3761template<class _CharT, class _Traits, class _Allocator>
3762inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3763typename basic_string<_CharT, _Traits, _Allocator>::size_type
3764basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
3765                                                         size_type __pos) const _NOEXCEPT
3766{
3767    _LIBCPP_ASSERT(__s != nullptr, "string::find_first_of(): received nullptr");
3768    return __str_find_first_of<value_type, size_type, traits_type, npos>
3769        (data(), size(), __s, __pos, traits_type::length(__s));
3770}
3771
3772template<class _CharT, class _Traits, class _Allocator>
3773inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3774typename basic_string<_CharT, _Traits, _Allocator>::size_type
3775basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c,
3776                                                         size_type __pos) const _NOEXCEPT
3777{
3778    return find(__c, __pos);
3779}
3780
3781// find_last_of
3782
3783template<class _CharT, class _Traits, class _Allocator>
3784inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3785typename basic_string<_CharT, _Traits, _Allocator>::size_type
3786basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
3787                                                        size_type __pos,
3788                                                        size_type __n) const _NOEXCEPT
3789{
3790    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr");
3791    return __str_find_last_of<value_type, size_type, traits_type, npos>
3792        (data(), size(), __s, __pos, __n);
3793}
3794
3795template<class _CharT, class _Traits, class _Allocator>
3796inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3797typename basic_string<_CharT, _Traits, _Allocator>::size_type
3798basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str,
3799                                                        size_type __pos) const _NOEXCEPT
3800{
3801    return __str_find_last_of<value_type, size_type, traits_type, npos>
3802        (data(), size(), __str.data(), __pos, __str.size());
3803}
3804
3805template<class _CharT, class _Traits, class _Allocator>
3806template <class _Tp>
3807_LIBCPP_CONSTEXPR_AFTER_CXX17
3808__enable_if_t
3809<
3810    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3811    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3812>
3813basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t,
3814                                                size_type __pos) const _NOEXCEPT
3815{
3816    __self_view __sv = __t;
3817    return __str_find_last_of<value_type, size_type, traits_type, npos>
3818        (data(), size(), __sv.data(), __pos, __sv.size());
3819}
3820
3821template<class _CharT, class _Traits, class _Allocator>
3822inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3823typename basic_string<_CharT, _Traits, _Allocator>::size_type
3824basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
3825                                                        size_type __pos) const _NOEXCEPT
3826{
3827    _LIBCPP_ASSERT(__s != nullptr, "string::find_last_of(): received nullptr");
3828    return __str_find_last_of<value_type, size_type, traits_type, npos>
3829        (data(), size(), __s, __pos, traits_type::length(__s));
3830}
3831
3832template<class _CharT, class _Traits, class _Allocator>
3833inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3834typename basic_string<_CharT, _Traits, _Allocator>::size_type
3835basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c,
3836                                                        size_type __pos) const _NOEXCEPT
3837{
3838    return rfind(__c, __pos);
3839}
3840
3841// find_first_not_of
3842
3843template<class _CharT, class _Traits, class _Allocator>
3844_LIBCPP_CONSTEXPR_AFTER_CXX17
3845typename basic_string<_CharT, _Traits, _Allocator>::size_type
3846basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
3847                                                             size_type __pos,
3848                                                             size_type __n) const _NOEXCEPT
3849{
3850    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr");
3851    return __str_find_first_not_of<value_type, size_type, traits_type, npos>
3852        (data(), size(), __s, __pos, __n);
3853}
3854
3855template<class _CharT, class _Traits, class _Allocator>
3856inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3857typename basic_string<_CharT, _Traits, _Allocator>::size_type
3858basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str,
3859                                                             size_type __pos) const _NOEXCEPT
3860{
3861    return __str_find_first_not_of<value_type, size_type, traits_type, npos>
3862        (data(), size(), __str.data(), __pos, __str.size());
3863}
3864
3865template<class _CharT, class _Traits, class _Allocator>
3866template <class _Tp>
3867_LIBCPP_CONSTEXPR_AFTER_CXX17
3868__enable_if_t
3869<
3870    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3871    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3872>
3873basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t,
3874                                                size_type __pos) const _NOEXCEPT
3875{
3876    __self_view __sv = __t;
3877    return __str_find_first_not_of<value_type, size_type, traits_type, npos>
3878        (data(), size(), __sv.data(), __pos, __sv.size());
3879}
3880
3881template<class _CharT, class _Traits, class _Allocator>
3882inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3883typename basic_string<_CharT, _Traits, _Allocator>::size_type
3884basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
3885                                                             size_type __pos) const _NOEXCEPT
3886{
3887    _LIBCPP_ASSERT(__s != nullptr, "string::find_first_not_of(): received nullptr");
3888    return __str_find_first_not_of<value_type, size_type, traits_type, npos>
3889        (data(), size(), __s, __pos, traits_type::length(__s));
3890}
3891
3892template<class _CharT, class _Traits, class _Allocator>
3893inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3894typename basic_string<_CharT, _Traits, _Allocator>::size_type
3895basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c,
3896                                                             size_type __pos) const _NOEXCEPT
3897{
3898    return __str_find_first_not_of<value_type, size_type, traits_type, npos>
3899        (data(), size(), __c, __pos);
3900}
3901
3902// find_last_not_of
3903
3904template<class _CharT, class _Traits, class _Allocator>
3905_LIBCPP_CONSTEXPR_AFTER_CXX17
3906typename basic_string<_CharT, _Traits, _Allocator>::size_type
3907basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
3908                                                            size_type __pos,
3909                                                            size_type __n) const _NOEXCEPT
3910{
3911    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr");
3912    return __str_find_last_not_of<value_type, size_type, traits_type, npos>
3913        (data(), size(), __s, __pos, __n);
3914}
3915
3916template<class _CharT, class _Traits, class _Allocator>
3917inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3918typename basic_string<_CharT, _Traits, _Allocator>::size_type
3919basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str,
3920                                                            size_type __pos) const _NOEXCEPT
3921{
3922    return __str_find_last_not_of<value_type, size_type, traits_type, npos>
3923        (data(), size(), __str.data(), __pos, __str.size());
3924}
3925
3926template<class _CharT, class _Traits, class _Allocator>
3927template <class _Tp>
3928_LIBCPP_CONSTEXPR_AFTER_CXX17
3929__enable_if_t
3930<
3931    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3932    typename basic_string<_CharT, _Traits, _Allocator>::size_type
3933>
3934basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t,
3935                                                size_type __pos) const _NOEXCEPT
3936{
3937    __self_view __sv = __t;
3938    return __str_find_last_not_of<value_type, size_type, traits_type, npos>
3939        (data(), size(), __sv.data(), __pos, __sv.size());
3940}
3941
3942template<class _CharT, class _Traits, class _Allocator>
3943inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3944typename basic_string<_CharT, _Traits, _Allocator>::size_type
3945basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
3946                                                            size_type __pos) const _NOEXCEPT
3947{
3948    _LIBCPP_ASSERT(__s != nullptr, "string::find_last_not_of(): received nullptr");
3949    return __str_find_last_not_of<value_type, size_type, traits_type, npos>
3950        (data(), size(), __s, __pos, traits_type::length(__s));
3951}
3952
3953template<class _CharT, class _Traits, class _Allocator>
3954inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3955typename basic_string<_CharT, _Traits, _Allocator>::size_type
3956basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c,
3957                                                            size_type __pos) const _NOEXCEPT
3958{
3959    return __str_find_last_not_of<value_type, size_type, traits_type, npos>
3960        (data(), size(), __c, __pos);
3961}
3962
3963// compare
3964
3965template <class _CharT, class _Traits, class _Allocator>
3966template <class _Tp>
3967_LIBCPP_CONSTEXPR_AFTER_CXX17
3968__enable_if_t
3969<
3970    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
3971    int
3972>
3973basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT
3974{
3975    __self_view __sv = __t;
3976    size_t __lhs_sz = size();
3977    size_t __rhs_sz = __sv.size();
3978    int __result = traits_type::compare(data(), __sv.data(),
3979                                        std::min(__lhs_sz, __rhs_sz));
3980    if (__result != 0)
3981        return __result;
3982    if (__lhs_sz < __rhs_sz)
3983        return -1;
3984    if (__lhs_sz > __rhs_sz)
3985        return 1;
3986    return 0;
3987}
3988
3989template <class _CharT, class _Traits, class _Allocator>
3990inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3991int
3992basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT
3993{
3994    return compare(__self_view(__str));
3995}
3996
3997template <class _CharT, class _Traits, class _Allocator>
3998inline _LIBCPP_CONSTEXPR_AFTER_CXX17
3999int
4000basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4001                                                   size_type __n1,
4002                                                   const value_type* __s,
4003                                                   size_type __n2) const
4004{
4005    _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr");
4006    size_type __sz = size();
4007    if (__pos1 > __sz || __n2 == npos)
4008        __throw_out_of_range();
4009    size_type __rlen = std::min(__n1, __sz - __pos1);
4010    int __r = traits_type::compare(data() + __pos1, __s, std::min(__rlen, __n2));
4011    if (__r == 0)
4012    {
4013        if (__rlen < __n2)
4014            __r = -1;
4015        else if (__rlen > __n2)
4016            __r = 1;
4017    }
4018    return __r;
4019}
4020
4021template <class _CharT, class _Traits, class _Allocator>
4022template <class _Tp>
4023_LIBCPP_CONSTEXPR_AFTER_CXX17
4024__enable_if_t
4025<
4026    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
4027    int
4028>
4029basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4030                                                   size_type __n1,
4031                                                   const _Tp& __t) const
4032{
4033    __self_view __sv = __t;
4034    return compare(__pos1, __n1, __sv.data(), __sv.size());
4035}
4036
4037template <class _CharT, class _Traits, class _Allocator>
4038inline _LIBCPP_CONSTEXPR_AFTER_CXX17
4039int
4040basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4041                                                   size_type __n1,
4042                                                   const basic_string& __str) const
4043{
4044    return compare(__pos1, __n1, __str.data(), __str.size());
4045}
4046
4047template <class _CharT, class _Traits, class _Allocator>
4048template <class _Tp>
4049_LIBCPP_CONSTEXPR_AFTER_CXX17
4050__enable_if_t
4051<
4052    __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
4053    && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
4054    int
4055>
4056basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4057                                                   size_type __n1,
4058                                                   const _Tp& __t,
4059                                                   size_type __pos2,
4060                                                   size_type __n2) const
4061{
4062    __self_view __sv = __t;
4063    return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
4064}
4065
4066template <class _CharT, class _Traits, class _Allocator>
4067_LIBCPP_CONSTEXPR_AFTER_CXX17
4068int
4069basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4070                                                   size_type __n1,
4071                                                   const basic_string& __str,
4072                                                   size_type __pos2,
4073                                                   size_type __n2) const
4074{
4075    return compare(__pos1, __n1, __self_view(__str), __pos2, __n2);
4076}
4077
4078template <class _CharT, class _Traits, class _Allocator>
4079_LIBCPP_CONSTEXPR_AFTER_CXX17
4080int
4081basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT
4082{
4083    _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr");
4084    return compare(0, npos, __s, traits_type::length(__s));
4085}
4086
4087template <class _CharT, class _Traits, class _Allocator>
4088_LIBCPP_CONSTEXPR_AFTER_CXX17
4089int
4090basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
4091                                                   size_type __n1,
4092                                                   const value_type* __s) const
4093{
4094    _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr");
4095    return compare(__pos1, __n1, __s, traits_type::length(__s));
4096}
4097
4098// __invariants
4099
4100template<class _CharT, class _Traits, class _Allocator>
4101inline _LIBCPP_CONSTEXPR_AFTER_CXX17
4102bool
4103basic_string<_CharT, _Traits, _Allocator>::__invariants() const
4104{
4105    if (size() > capacity())
4106        return false;
4107    if (capacity() < __min_cap - 1)
4108        return false;
4109    if (data() == nullptr)
4110        return false;
4111    if (data()[size()] != value_type())
4112        return false;
4113    return true;
4114}
4115
4116// __clear_and_shrink
4117
4118template<class _CharT, class _Traits, class _Allocator>
4119inline _LIBCPP_CONSTEXPR_AFTER_CXX17
4120void
4121basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT
4122{
4123    clear();
4124    if(__is_long())
4125    {
4126        __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
4127        __set_long_cap(0);
4128        __set_short_size(0);
4129        traits_type::assign(*__get_short_pointer(), value_type());
4130    }
4131}
4132
4133// operator==
4134
4135template<class _CharT, class _Traits, class _Allocator>
4136inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4137bool
4138operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4139           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4140{
4141    size_t __lhs_sz = __lhs.size();
4142    return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(),
4143                                                        __rhs.data(),
4144                                                        __lhs_sz) == 0;
4145}
4146
4147template<class _Allocator>
4148inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4149bool
4150operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs,
4151           const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT
4152{
4153    size_t __lhs_sz = __lhs.size();
4154    if (__lhs_sz != __rhs.size())
4155        return false;
4156    const char* __lp = __lhs.data();
4157    const char* __rp = __rhs.data();
4158    if (__lhs.__is_long())
4159        return char_traits<char>::compare(__lp, __rp, __lhs_sz) == 0;
4160    for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp)
4161        if (*__lp != *__rp)
4162            return false;
4163    return true;
4164}
4165
4166template<class _CharT, class _Traits, class _Allocator>
4167inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4168bool
4169operator==(const _CharT* __lhs,
4170           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4171{
4172    typedef basic_string<_CharT, _Traits, _Allocator> _String;
4173    _LIBCPP_ASSERT(__lhs != nullptr, "operator==(char*, basic_string): received nullptr");
4174    size_t __lhs_len = _Traits::length(__lhs);
4175    if (__lhs_len != __rhs.size()) return false;
4176    return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0;
4177}
4178
4179template<class _CharT, class _Traits, class _Allocator>
4180inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4181bool
4182operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
4183           const _CharT* __rhs) _NOEXCEPT
4184{
4185    typedef basic_string<_CharT, _Traits, _Allocator> _String;
4186    _LIBCPP_ASSERT(__rhs != nullptr, "operator==(basic_string, char*): received nullptr");
4187    size_t __rhs_len = _Traits::length(__rhs);
4188    if (__rhs_len != __lhs.size()) return false;
4189    return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0;
4190}
4191
4192template<class _CharT, class _Traits, class _Allocator>
4193inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4194bool
4195operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
4196           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4197{
4198    return !(__lhs == __rhs);
4199}
4200
4201template<class _CharT, class _Traits, class _Allocator>
4202inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4203bool
4204operator!=(const _CharT* __lhs,
4205           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4206{
4207    return !(__lhs == __rhs);
4208}
4209
4210template<class _CharT, class _Traits, class _Allocator>
4211inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4212bool
4213operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4214           const _CharT* __rhs) _NOEXCEPT
4215{
4216    return !(__lhs == __rhs);
4217}
4218
4219// operator<
4220
4221template<class _CharT, class _Traits, class _Allocator>
4222inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4223bool
4224operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4225           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4226{
4227    return __lhs.compare(__rhs) < 0;
4228}
4229
4230template<class _CharT, class _Traits, class _Allocator>
4231inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4232bool
4233operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4234           const _CharT* __rhs) _NOEXCEPT
4235{
4236    return __lhs.compare(__rhs) < 0;
4237}
4238
4239template<class _CharT, class _Traits, class _Allocator>
4240inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4241bool
4242operator< (const _CharT* __lhs,
4243           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4244{
4245    return __rhs.compare(__lhs) > 0;
4246}
4247
4248// operator>
4249
4250template<class _CharT, class _Traits, class _Allocator>
4251inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4252bool
4253operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4254           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4255{
4256    return __rhs < __lhs;
4257}
4258
4259template<class _CharT, class _Traits, class _Allocator>
4260inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4261bool
4262operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4263           const _CharT* __rhs) _NOEXCEPT
4264{
4265    return __rhs < __lhs;
4266}
4267
4268template<class _CharT, class _Traits, class _Allocator>
4269inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4270bool
4271operator> (const _CharT* __lhs,
4272           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4273{
4274    return __rhs < __lhs;
4275}
4276
4277// operator<=
4278
4279template<class _CharT, class _Traits, class _Allocator>
4280inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4281bool
4282operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4283           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4284{
4285    return !(__rhs < __lhs);
4286}
4287
4288template<class _CharT, class _Traits, class _Allocator>
4289inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4290bool
4291operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4292           const _CharT* __rhs) _NOEXCEPT
4293{
4294    return !(__rhs < __lhs);
4295}
4296
4297template<class _CharT, class _Traits, class _Allocator>
4298inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4299bool
4300operator<=(const _CharT* __lhs,
4301           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4302{
4303    return !(__rhs < __lhs);
4304}
4305
4306// operator>=
4307
4308template<class _CharT, class _Traits, class _Allocator>
4309inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4310bool
4311operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4312           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4313{
4314    return !(__lhs < __rhs);
4315}
4316
4317template<class _CharT, class _Traits, class _Allocator>
4318inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4319bool
4320operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4321           const _CharT* __rhs) _NOEXCEPT
4322{
4323    return !(__lhs < __rhs);
4324}
4325
4326template<class _CharT, class _Traits, class _Allocator>
4327inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI
4328bool
4329operator>=(const _CharT* __lhs,
4330           const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
4331{
4332    return !(__lhs < __rhs);
4333}
4334
4335// operator +
4336
4337template<class _CharT, class _Traits, class _Allocator>
4338_LIBCPP_CONSTEXPR_AFTER_CXX17
4339basic_string<_CharT, _Traits, _Allocator>
4340operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4341          const basic_string<_CharT, _Traits, _Allocator>& __rhs)
4342{
4343    using _String = basic_string<_CharT, _Traits, _Allocator>;
4344    auto __lhs_sz = __lhs.size();
4345    auto __rhs_sz = __rhs.size();
4346    _String __r(__uninitialized_size_tag(),
4347                __lhs_sz + __rhs_sz,
4348                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4349    auto __ptr = std::__to_address(__r.__get_pointer());
4350    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4351    _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4352    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4353    return __r;
4354}
4355
4356template<class _CharT, class _Traits, class _Allocator>
4357_LIBCPP_CONSTEXPR_AFTER_CXX17
4358basic_string<_CharT, _Traits, _Allocator>
4359operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs)
4360{
4361    using _String = basic_string<_CharT, _Traits, _Allocator>;
4362    auto __lhs_sz = _Traits::length(__lhs);
4363    auto __rhs_sz = __rhs.size();
4364    _String __r(__uninitialized_size_tag(),
4365                __lhs_sz + __rhs_sz,
4366                _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
4367    auto __ptr = std::__to_address(__r.__get_pointer());
4368    _Traits::copy(__ptr, __lhs, __lhs_sz);
4369    _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4370    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4371    return __r;
4372}
4373
4374template<class _CharT, class _Traits, class _Allocator>
4375_LIBCPP_CONSTEXPR_AFTER_CXX17
4376basic_string<_CharT, _Traits, _Allocator>
4377operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs)
4378{
4379    using _String = basic_string<_CharT, _Traits, _Allocator>;
4380    typename _String::size_type __rhs_sz = __rhs.size();
4381    _String __r(__uninitialized_size_tag(),
4382                __rhs_sz + 1,
4383                _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
4384    auto __ptr = std::__to_address(__r.__get_pointer());
4385    _Traits::assign(__ptr, 1, __lhs);
4386    _Traits::copy(__ptr + 1, __rhs.data(), __rhs_sz);
4387    _Traits::assign(__ptr + 1 + __rhs_sz, 1, _CharT());
4388    return __r;
4389}
4390
4391template<class _CharT, class _Traits, class _Allocator>
4392inline _LIBCPP_CONSTEXPR_AFTER_CXX17
4393basic_string<_CharT, _Traits, _Allocator>
4394operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs)
4395{
4396    using _String = basic_string<_CharT, _Traits, _Allocator>;
4397    typename _String::size_type __lhs_sz = __lhs.size();
4398    typename _String::size_type __rhs_sz = _Traits::length(__rhs);
4399    _String __r(__uninitialized_size_tag(),
4400                __lhs_sz + __rhs_sz,
4401                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4402    auto __ptr = std::__to_address(__r.__get_pointer());
4403    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4404    _Traits::copy(__ptr + __lhs_sz, __rhs, __rhs_sz);
4405    _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4406    return __r;
4407}
4408
4409template<class _CharT, class _Traits, class _Allocator>
4410_LIBCPP_CONSTEXPR_AFTER_CXX17
4411basic_string<_CharT, _Traits, _Allocator>
4412operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs)
4413{
4414    using _String = basic_string<_CharT, _Traits, _Allocator>;
4415    typename _String::size_type __lhs_sz = __lhs.size();
4416    _String __r(__uninitialized_size_tag(),
4417                __lhs_sz + 1,
4418                _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4419    auto __ptr = std::__to_address(__r.__get_pointer());
4420    _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4421    _Traits::assign(__ptr + __lhs_sz, 1, __rhs);
4422    _Traits::assign(__ptr + 1 + __lhs_sz, 1, _CharT());
4423    return __r;
4424}
4425
4426#ifndef _LIBCPP_CXX03_LANG
4427
4428template<class _CharT, class _Traits, class _Allocator>
4429inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4430basic_string<_CharT, _Traits, _Allocator>
4431operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs)
4432{
4433    return std::move(__lhs.append(__rhs));
4434}
4435
4436template<class _CharT, class _Traits, class _Allocator>
4437inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4438basic_string<_CharT, _Traits, _Allocator>
4439operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
4440{
4441    return std::move(__rhs.insert(0, __lhs));
4442}
4443
4444template<class _CharT, class _Traits, class _Allocator>
4445inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4446basic_string<_CharT, _Traits, _Allocator>
4447operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
4448{
4449    return std::move(__lhs.append(__rhs));
4450}
4451
4452template<class _CharT, class _Traits, class _Allocator>
4453inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4454basic_string<_CharT, _Traits, _Allocator>
4455operator+(const _CharT* __lhs , basic_string<_CharT,_Traits,_Allocator>&& __rhs)
4456{
4457    return std::move(__rhs.insert(0, __lhs));
4458}
4459
4460template<class _CharT, class _Traits, class _Allocator>
4461inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4462basic_string<_CharT, _Traits, _Allocator>
4463operator+(_CharT __lhs, basic_string<_CharT,_Traits,_Allocator>&& __rhs)
4464{
4465    __rhs.insert(__rhs.begin(), __lhs);
4466    return std::move(__rhs);
4467}
4468
4469template<class _CharT, class _Traits, class _Allocator>
4470inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4471basic_string<_CharT, _Traits, _Allocator>
4472operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs)
4473{
4474    return std::move(__lhs.append(__rhs));
4475}
4476
4477template<class _CharT, class _Traits, class _Allocator>
4478inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4479basic_string<_CharT, _Traits, _Allocator>
4480operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs)
4481{
4482    __lhs.push_back(__rhs);
4483    return std::move(__lhs);
4484}
4485
4486#endif // _LIBCPP_CXX03_LANG
4487
4488// swap
4489
4490template<class _CharT, class _Traits, class _Allocator>
4491inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
4492void
4493swap(basic_string<_CharT, _Traits, _Allocator>& __lhs,
4494     basic_string<_CharT, _Traits, _Allocator>& __rhs)
4495     _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs)))
4496{
4497    __lhs.swap(__rhs);
4498}
4499
4500_LIBCPP_FUNC_VIS int                stoi  (const string& __str, size_t* __idx = nullptr, int __base = 10);
4501_LIBCPP_FUNC_VIS long               stol  (const string& __str, size_t* __idx = nullptr, int __base = 10);
4502_LIBCPP_FUNC_VIS unsigned long      stoul (const string& __str, size_t* __idx = nullptr, int __base = 10);
4503_LIBCPP_FUNC_VIS long long          stoll (const string& __str, size_t* __idx = nullptr, int __base = 10);
4504_LIBCPP_FUNC_VIS unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10);
4505
4506_LIBCPP_FUNC_VIS float       stof (const string& __str, size_t* __idx = nullptr);
4507_LIBCPP_FUNC_VIS double      stod (const string& __str, size_t* __idx = nullptr);
4508_LIBCPP_FUNC_VIS long double stold(const string& __str, size_t* __idx = nullptr);
4509
4510_LIBCPP_FUNC_VIS string to_string(int __val);
4511_LIBCPP_FUNC_VIS string to_string(unsigned __val);
4512_LIBCPP_FUNC_VIS string to_string(long __val);
4513_LIBCPP_FUNC_VIS string to_string(unsigned long __val);
4514_LIBCPP_FUNC_VIS string to_string(long long __val);
4515_LIBCPP_FUNC_VIS string to_string(unsigned long long __val);
4516_LIBCPP_FUNC_VIS string to_string(float __val);
4517_LIBCPP_FUNC_VIS string to_string(double __val);
4518_LIBCPP_FUNC_VIS string to_string(long double __val);
4519
4520#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4521_LIBCPP_FUNC_VIS int                stoi  (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4522_LIBCPP_FUNC_VIS long               stol  (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4523_LIBCPP_FUNC_VIS unsigned long      stoul (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4524_LIBCPP_FUNC_VIS long long          stoll (const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4525_LIBCPP_FUNC_VIS unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10);
4526
4527_LIBCPP_FUNC_VIS float       stof (const wstring& __str, size_t* __idx = nullptr);
4528_LIBCPP_FUNC_VIS double      stod (const wstring& __str, size_t* __idx = nullptr);
4529_LIBCPP_FUNC_VIS long double stold(const wstring& __str, size_t* __idx = nullptr);
4530
4531_LIBCPP_FUNC_VIS wstring to_wstring(int __val);
4532_LIBCPP_FUNC_VIS wstring to_wstring(unsigned __val);
4533_LIBCPP_FUNC_VIS wstring to_wstring(long __val);
4534_LIBCPP_FUNC_VIS wstring to_wstring(unsigned long __val);
4535_LIBCPP_FUNC_VIS wstring to_wstring(long long __val);
4536_LIBCPP_FUNC_VIS wstring to_wstring(unsigned long long __val);
4537_LIBCPP_FUNC_VIS wstring to_wstring(float __val);
4538_LIBCPP_FUNC_VIS wstring to_wstring(double __val);
4539_LIBCPP_FUNC_VIS wstring to_wstring(long double __val);
4540#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4541
4542template<class _CharT, class _Traits, class _Allocator>
4543_LIBCPP_TEMPLATE_DATA_VIS
4544const typename basic_string<_CharT, _Traits, _Allocator>::size_type
4545               basic_string<_CharT, _Traits, _Allocator>::npos;
4546
4547template <class _CharT, class _Allocator>
4548struct _LIBCPP_TEMPLATE_VIS
4549    hash<basic_string<_CharT, char_traits<_CharT>, _Allocator> >
4550    : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t>
4551{
4552    size_t
4553    operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT
4554    { return __do_string_hash(__val.data(), __val.data() + __val.size()); }
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#ifdef _LIBCPP_ENABLE_DEBUG_MODE
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_ENABLE_DEBUG_MODE
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