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