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