MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
basic_string.hpp
1#ifndef MSTL_CORE_STRING_BASIC_STRING_HPP__
2#define MSTL_CORE_STRING_BASIC_STRING_HPP__
3#include <initializer_list>
9#include "string_view.hpp"
11
12template <typename CharT, typename Traits, typename Alloc>
13class basic_string;
14
15template <bool IsConst, typename String>
16struct basic_string_iterator {
17private:
18 using container_type = String;
19 using iterator = basic_string_iterator<false, container_type>;
20 using const_iterator = basic_string_iterator<true, container_type>;
21
22public:
23 using iterator_category = contiguous_iterator_tag;
24 using value_type = typename container_type::value_type;
27 using difference_type = typename container_type::difference_type;
28 using size_type = typename container_type::size_type;
29
30private:
31 pointer ptr_ = nullptr;
32 const container_type* str_ = nullptr;
33
34 template <typename, typename, typename> friend class basic_string;
35 template <bool, typename> friend struct basic_string_iterator;
36
37public:
38 MSTL_CONSTEXPR20 basic_string_iterator() = default;
39 MSTL_CONSTEXPR20 basic_string_iterator(pointer ptr) : ptr_(ptr) {}
40 MSTL_CONSTEXPR20 basic_string_iterator(pointer ptr, const container_type* vec) : ptr_(ptr), str_(vec) {}
41
42 MSTL_CONSTEXPR20 basic_string_iterator(const iterator& x) noexcept
43 : ptr_(const_cast<pointer>(x.ptr_)), str_(x.str_) {}
44
45 MSTL_CONSTEXPR20 basic_string_iterator& operator =(const iterator& rhs) noexcept {
46 if (_MSTL addressof(rhs) == this) return *this;
47 ptr_ = const_cast<pointer>(rhs.ptr_);
48 str_ = rhs.str_;
49 return *this;
50 }
51
52 MSTL_CONSTEXPR20 basic_string_iterator(iterator&& x) noexcept
53 : ptr_(const_cast<pointer>(x.ptr_)), str_(x.str_) {
54 x.ptr_ = nullptr;
55 x.str_ = nullptr;
56 }
57
58 MSTL_CONSTEXPR20 basic_string_iterator& operator =(iterator&& rhs) noexcept {
59 if (_MSTL addressof(rhs) == this) return *this;
60 ptr_ = const_cast<pointer>(rhs.ptr_);
61 str_ = rhs.str_;
62 rhs.ptr_ = nullptr;
63 rhs.str_ = nullptr;
64 return *this;
65 }
66
67 MSTL_CONSTEXPR20 basic_string_iterator(const const_iterator& x) noexcept
68 : ptr_(const_cast<pointer>(x.ptr_)), str_(x.str_) {}
69
70 MSTL_CONSTEXPR20 basic_string_iterator& operator =(const const_iterator& rhs) noexcept {
71 if (_MSTL addressof(rhs) == this) return *this;
72 ptr_ = const_cast<pointer>(rhs.ptr_);
73 str_ = rhs.str_;
74 return *this;
75 }
76
77 MSTL_CONSTEXPR20 basic_string_iterator(const_iterator&& x) noexcept
78 : ptr_(const_cast<pointer>(x.ptr_)), str_(x.str_) {
79 x.ptr_ = nullptr;
80 x.str_ = nullptr;
81 }
82
83 MSTL_CONSTEXPR20 basic_string_iterator& operator =(const_iterator&& rhs) noexcept {
84 if (_MSTL addressof(rhs) == this) return *this;
85 ptr_ = const_cast<pointer>(rhs.ptr_);
86 str_ = rhs.str_;
87 rhs.ptr_ = nullptr;
88 rhs.str_ = nullptr;
89 return *this;
90 }
91
92 MSTL_CONSTEXPR20 ~basic_string_iterator() noexcept = default;
93
94 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator *() const noexcept {
95 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
96 MSTL_DEBUG_VERIFY(str_->data() <= ptr_ && ptr_ <= str_->data() + str_->size_,
97 __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
98 return *ptr_;
99 }
100 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer operator ->() const noexcept {
101 return &operator*();
102 }
103
104 MSTL_CONSTEXPR20 basic_string_iterator& operator ++() noexcept {
105 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
106 MSTL_DEBUG_VERIFY(ptr_ < str_->data() + str_->size_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
107 ++ptr_;
108 return *this;
109 }
110 MSTL_CONSTEXPR20 basic_string_iterator operator ++(int) noexcept {
111 basic_string_iterator tmp = *this;
112 ++*this;
113 return tmp;
114 }
115
116 MSTL_CONSTEXPR20 basic_string_iterator& operator --() noexcept {
117 MSTL_DEBUG_VERIFY(ptr_ && str_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
118 MSTL_DEBUG_VERIFY(str_->data() < ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
119 --ptr_;
120 return *this;
121 }
122 MSTL_CONSTEXPR20 basic_string_iterator operator --(int) noexcept {
123 basic_string_iterator tmp = *this;
124 --*this;
125 return tmp;
126 }
127
128 MSTL_CONSTEXPR20 basic_string_iterator& operator +=(difference_type n) noexcept {
129 if (n < 0) {
130 MSTL_DEBUG_VERIFY((ptr_ && str_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
131 MSTL_DEBUG_VERIFY(n >= str_->data() - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_DECREMENT));
132 }
133 else if (n > 0) {
134 MSTL_DEBUG_VERIFY((ptr_ && str_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
135 MSTL_DEBUG_VERIFY(n <= str_->data() + str_->size_ - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(basic_string_iterator, __MSTL_DEBUG_TAG_INCREMENT));
136 }
137 ptr_ += n;
138 return *this;
139 }
140 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string_iterator operator +(const difference_type n) const noexcept {
141 basic_string_iterator tmp = *this;
142 tmp += n;
143 return tmp;
144 }
145 MSTL_NODISCARD friend MSTL_CONSTEXPR20 basic_string_iterator operator +(const difference_type n, const basic_string_iterator& it) noexcept {
146 return it + n;
147 }
148
149 MSTL_CONSTEXPR20 basic_string_iterator& operator -=(difference_type n) noexcept {
150 ptr_ += -n;
151 return *this;
152 }
153 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string_iterator operator -(difference_type n) const noexcept {
154 auto tmp = *this;
155 tmp -= n;
156 return tmp;
157 }
158 MSTL_NODISCARD MSTL_CONSTEXPR20 difference_type operator -(const basic_string_iterator& rhs) const noexcept {
159 return static_cast<difference_type>(ptr_ - rhs.ptr_);
160 }
161
162 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](difference_type n) const noexcept {
163 return *(*this + n);
164 }
165
166 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(const basic_string_iterator& rhs) const noexcept {
167 MSTL_DEBUG_VERIFY(str_ == rhs.str_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
168 return ptr_ == rhs.ptr_;
169 }
170 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(const basic_string_iterator& rhs) const noexcept {
171 return !(*this == rhs);
172 }
173 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(const basic_string_iterator& rhs) const noexcept {
174 MSTL_DEBUG_VERIFY(str_ == rhs.str_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
175 return ptr_ < rhs.ptr_;
176 }
177 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(const basic_string_iterator& rhs) const noexcept {
178 return rhs < *this;
179 }
180 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(const basic_string_iterator& rhs) const noexcept {
181 return !(*this > rhs);
182 }
183 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(const basic_string_iterator& rhs) const noexcept {
184 return !(*this < rhs);
185 }
186};
187
188template <typename CharT, typename Traits = char_traits<CharT>, typename Alloc = allocator<CharT>>
189class basic_string : public icommon<basic_string<CharT, Traits, Alloc>> {
190#ifdef MSTL_STANDARD_20__
191 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
192#endif
193 static_assert(is_same_v<CharT, typename Alloc::value_type>, "allocator type mismatch.");
194 static_assert(is_same_v<CharT, typename Traits::char_type>, "trait type mismatch.");
195 static_assert(!is_array_v<CharT> && is_trivial_v<CharT> && is_standard_layout_v<CharT>,
196 "basic string only contains non-array trivial standard-layout types.");
197
198public:
200
201 using iterator = basic_string_iterator<false, basic_string>;
202 using const_iterator = basic_string_iterator<true, basic_string>;
203 using reverse_iterator = _MSTL reverse_iterator<iterator>;
204 using const_reverse_iterator = _MSTL reverse_iterator<const_iterator>;
205
206 using traits_type = Traits;
207 using view_type = basic_string_view<CharT, Traits>;
208 using allocator_type = Alloc;
209
210 static constexpr size_type npos = string_view::npos;
211
212private:
213 pointer data_ = nullptr;
214 size_type size_ = 0;
215 compressed_pair<allocator_type, size_type> capacity_pair_{ default_construct_tag{}, 0 };
216
217 template <bool, typename> friend struct basic_string_iterator;
218
219private:
220 MSTL_CONSTEXPR20 void null_terminate() {
221 if (data_ && size_ < capacity_pair_.value) {
222 traits_type::assign(data_ + size_, 1, value_type());
223 } else if (size_ == capacity_pair_.value) {
224 this->reserve(capacity_pair_.value * 1.5);
225 traits_type::assign(data_ + size_, 1, value_type());
226 }
227 }
228
229 template <typename Iterator, enable_if_t<!is_ranges_fwd_iter_v<Iterator>, int> = 0>
230 MSTL_CONSTEXPR20 void construct_from_iter(Iterator first, Iterator last) {
231 size_type n = _MSTL distance(first, last);
232 const size_type init_size = _MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
233 pointer temp_data = nullptr;
234 size_type temp_size = 0;
235 try {
236 temp_data = capacity_pair_.get_base().allocate(init_size);
237 _MSTL uninitialized_copy(temp_data, temp_data + temp_size, first);
238
239 data_ = temp_data;
240 size_ = n;
241 capacity_pair_.value = init_size;
242 null_terminate();
243 } catch (...) {
244 if (temp_data) {
245 _MSTL destroy(temp_data, temp_data + n);
246 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
247 }
248 destroy_buffer();
249 throw;
250 }
251 }
252
253 template <typename Iterator, enable_if_t<is_ranges_fwd_iter_v<Iterator>, int> = 0>
254 MSTL_CONSTEXPR20 void construct_from_iter(Iterator first, Iterator last) {
255 const size_type n = _MSTL distance(first, last);
256 const size_type init_size = _MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
257 pointer temp_data = nullptr;
258 try {
259 temp_data = capacity_pair_.get_base().allocate(init_size);
260 size_ = n;
261 capacity_pair_.value = init_size;
262 _MSTL uninitialized_copy(first, last, temp_data);
263
264 data_ = temp_data;
265 size_ = n;
266 capacity_pair_.value = init_size;
267 null_terminate();
268 } catch (...) {
269 if (temp_data) {
270 _MSTL destroy(temp_data, temp_data + n);
271 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
272 }
273 destroy_buffer();
274 throw;
275 }
276 }
277
278 MSTL_CONSTEXPR20 void construct_from_ptr(const_pointer str, size_type position, size_type n) {
279 pointer temp_data = nullptr;
280 size_type temp_capacity = 0;
281 try {
282 temp_capacity = _MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
283 temp_data = capacity_pair_.get_base().allocate(temp_capacity);
284 traits_type::copy(temp_data, str + position, n);
285
286 data_ = temp_data;
287 size_ = n;
288 capacity_pair_.value = temp_capacity;
289 null_terminate();
290 } catch (...) {
291 if (temp_data) {
292 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
293 }
294 data_ = nullptr;
295 size_ = 0;
296 capacity_pair_.value = 0;
297 throw;
298 }
299 }
300
301 MSTL_CONSTEXPR20 void destroy_buffer() noexcept {
302 if (data_) {
303 if (capacity_pair_.value > 0) {
304 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
305 }
306 data_ = nullptr;
307 }
308 capacity_pair_.value = 0;
309 size_ = 0;
310 }
311
312 MSTL_CONSTEXPR20 basic_string& replace_fill(iterator first, size_type n1, const size_type n2, const value_type chr) {
313 if (static_cast<size_type>(end() - first) < n1) {
314 n1 = cend() - first;
315 }
316 if (n1 < n2) {
317 const size_type diff = n2 - n1;
318 MSTL_DEBUG_VERIFY(size_ + diff < max_size(), "basic_string index out of range.");
319 if (size_ > capacity_pair_.value - diff)
320 reallocate(diff);
321 pointer raw_ptr = &*first;
322 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
323 traits_type::assign(raw_ptr, n2, chr);
324 size_ += diff;
325 }
326 else {
327 pointer raw_ptr = &*first;
328 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
329 traits_type::assign(raw_ptr, n2, chr);
330 size_ -= n1 - n2;
331 }
332 null_terminate();
333 return *this;
334 }
335
336 template <typename Iterator,
337 enable_if_t<is_iter_v<Iterator> && is_same_v<iter_value_t<Iterator>, value_type>, int> = 0>
338 MSTL_CONSTEXPR20 basic_string& replace_copy(iterator first1, iterator last1, Iterator first2, Iterator last2) {
339 size_type len1 = _MSTL distance(first1, last1);
340 size_type len2 = _MSTL distance(first2, last2);
341 if (len1 < len2) {
342 const size_type diff = len2 - len1;
343 MSTL_DEBUG_VERIFY(size_ + diff < max_size(), "basic_string replace_copy index out of range.");
344 if (size_ > capacity_pair_.value - diff)
345 reallocate(diff);
346 pointer raw_ptr = &*first1;
347 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
348 traits_type::copy(raw_ptr, &*first2, len2);
349 size_ += diff;
350 }
351 else {
352 pointer raw_ptr = &*first1;
353 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
354 traits_type::copy(raw_ptr, &*first2, len2);
355 size_ -= len1 - len2;
356 }
357 null_terminate();
358 return *this;
359 }
360
361 template <typename Iterator>
362 MSTL_CONSTEXPR20 basic_string& replace_copy(iterator first1, const size_type n1, Iterator first2, const size_type n2) {
363 return this->replace_copy(first1, first1 + n1, first2, _MSTL next(first2, n2));
364 }
365
366 MSTL_CONSTEXPR20 void reallocate(size_type n) {
367 pointer new_buffer = nullptr;
368 try {
369 const size_t new_cap = _MSTL max(
370 capacity_pair_.value + n,
371 capacity_pair_.value + (capacity_pair_.value >> 1)
372 ) + 1;
373 new_buffer = capacity_pair_.get_base().allocate(new_cap);
374 traits_type::move(new_buffer, data_, size_);
375
376 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
377 data_ = new_buffer;
378 capacity_pair_.value = new_cap;
379 null_terminate();
380 } catch (...) {
381 if (new_buffer) {
382 capacity_pair_.get_base().deallocate(new_buffer, capacity_pair_.value);
383 }
384 throw;
385 }
386 }
387
388 MSTL_CONSTEXPR20 iterator reallocate_and_fill(iterator position, size_type n, value_type chr) {
389 const difference_type diff = (&*position) - data_;
390 const size_t old_cap = capacity_pair_.value;
391 const size_t new_cap = _MSTL max(old_cap + n, old_cap + (old_cap >> 1));
392 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
393 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
394 pointer end2 = traits_type::assign(end1, n, chr) + n;
395 traits_type::move(end2, data_ + diff, size_ - diff);
396 capacity_pair_.get_base().deallocate(data_, old_cap);
397 data_ = new_buffer;
398 size_ += n;
399 capacity_pair_.value = new_cap;
400 null_terminate();
401 return iterator(data_ + diff, this);
402 }
403
404 MSTL_CONSTEXPR20 iterator reallocate_and_copy(iterator position, const_iterator first, const_iterator last) {
405 const difference_type diff = position - data_;
406 const size_type old_cap = capacity_pair_.value;
407 const size_type n = _MSTL distance(first, last);
408 const size_t new_cap = _MSTL max(old_cap + n, old_cap + (old_cap >> 1));
409 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
410 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
411 pointer end2 = _MSTL uninitialized_copy_n(first, n, end1).second + n;
412 traits_type::move(end2, data_ + diff, size_ - diff);
413 capacity_pair_.get_base().deallocate(data_, old_cap);
414 data_ = new_buffer;
415 size_ += n;
416 capacity_pair_.value = new_cap;
417 null_terminate();
418 return iterator(data_ + diff, this);
419 }
420
421public:
422 MSTL_CONSTEXPR20 basic_string() {
423 null_terminate();
424 }
425
426 MSTL_CONSTEXPR20 explicit basic_string(size_type n)
427 : basic_string(n, static_cast<value_type>(0)) {}
428
429 MSTL_CONSTEXPR20 explicit basic_string(size_type n, int32_t chr)
430 : basic_string(n, static_cast<value_type>(chr)) {}
431
432 MSTL_CONSTEXPR20 explicit basic_string(size_type n, value_type chr) {
433 const size_type init_size = _MSTL max(MEMORY_ALIGN_THRESHHOLD, n + 1);
434 data_ = capacity_pair_.get_base().allocate(init_size);
435 traits_type::assign(data_, n, chr);
436 size_ = n;
437 capacity_pair_.value = init_size;
438 null_terminate();
439 }
440
441 MSTL_CONSTEXPR20 basic_string& operator =(value_type chr) {
442 if (capacity_pair_.value < 1) {
443 pointer new_buffer = capacity_pair_.get_base().allocate(2);
444 capacity_pair_.get_base().deallocate(data_);
445 data_ = new_buffer;
446 capacity_pair_.value = 2;
447 }
448 *data_ = chr;
449 size_ = 1;
450 null_terminate();
451 return *this;
452 }
453
454 MSTL_CONSTEXPR20 basic_string(const basic_string& str) {
455 this->construct_from_ptr(str.data(), 0, str.size_);
456 }
457
458 MSTL_CONSTEXPR20 basic_string& operator =(const basic_string& str) {
459 if (_MSTL addressof(str) == this) return *this;
460 destroy_buffer();
461 this->construct_from_ptr(str.data(), 0, str.size_);
462 return *this;
463 }
464
465 MSTL_CONSTEXPR20 basic_string(basic_string&& str) noexcept
466 : data_(str.data_), size_(str.size_),
467 capacity_pair_(_MSTL move(str.capacity_pair_)) {
468 str.data_ = nullptr;
469 str.size_ = 0;
470 str.capacity_pair_.value = 0;
471 }
472
473 MSTL_CONSTEXPR20 basic_string& operator =(basic_string&& str) noexcept {
474 if (_MSTL addressof(str) == this) return *this;
475
476 pointer new_data = str.data_;
477 const size_type new_size = str.size_;
478 auto new_capacity_pair = _MSTL move(str.capacity_pair_);
479
480 str.data_ = nullptr;
481 str.size_ = 0;
482 str.capacity_pair_.value = 0;
483
484 destroy_buffer();
485 data_ = new_data;
486 size_ = new_size;
487 capacity_pair_ = _MSTL move(new_capacity_pair);
488
489 return *this;
490 }
491
492 MSTL_CONSTEXPR20 basic_string(view_type str) {
493 this->construct_from_ptr(str.data(), 0, str.size());
494 }
495
496 MSTL_CONSTEXPR20 basic_string(view_type str, const size_type n) {
497 this->construct_from_ptr(str.data(), 0, n);
498 }
499
500 MSTL_CONSTEXPR20 basic_string& operator =(view_type str) {
501 const size_type len = str.size();
502 if (capacity_pair_.value < len) {
503 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
504 capacity_pair_.get_base().deallocate(data_);
505 data_ = new_buffer;
506 capacity_pair_.value = len + 1;
507 }
508 traits_type::copy(data_, str.data(), len);
509 size_ = len;
510 null_terminate();
511 return *this;
512 }
513
514 MSTL_CONSTEXPR20 basic_string(const basic_string& str, size_type position) {
515 this->construct_from_ptr(str.data_, position, str.size_ - position);
516 }
517
518 MSTL_CONSTEXPR20 basic_string(const basic_string& str, const size_type position, const size_type n) {
519 this->construct_from_ptr(str.data_, position, n);
520 }
521
522 MSTL_CONSTEXPR20 basic_string(const_pointer str) {
523 this->construct_from_ptr(str, 0, traits_type::length(str));
524 }
525
526 MSTL_CONSTEXPR20 basic_string(const_pointer str, const size_type n) {
527 this->construct_from_ptr(str, 0, n);
528 }
529
530 MSTL_CONSTEXPR20 basic_string& operator =(const_pointer str) {
531 const size_type len = traits_type::length(str);
532 if (capacity_pair_.value < len) {
533 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
534 capacity_pair_.get_base().deallocate(data_);
535 data_ = new_buffer;
536 capacity_pair_.value = len + 1;
537 }
538 traits_type::copy(data_, str, len);
539 size_ = len;
540 null_terminate();
541 return *this;
542 }
543
544 template <typename Iterator, enable_if_t<!is_convertible_v<Iterator, value_type>, int> = 0>
545 MSTL_CONSTEXPR20 basic_string(Iterator first, Iterator last) {
546 this->construct_from_iter(first, last);
547 }
548
549 MSTL_CONSTEXPR20 basic_string(std::initializer_list<value_type> l) : basic_string(l.begin(), l.end()) {}
550 MSTL_CONSTEXPR20 basic_string& operator =(std::initializer_list<value_type> l) {
551 this->clear();
552 this->insert(begin(), l.begin(), l.end());
553 return *this;
554 }
555
556 MSTL_CONSTEXPR20 ~basic_string() { destroy_buffer(); }
557
558 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator begin() noexcept { return {data_, this}; }
559 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator end() noexcept { return {data_ + size_, this}; }
560 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator begin() const noexcept { return cbegin(); }
561 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator end() const noexcept { return cend(); }
562 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cbegin() const noexcept { return {data_, this}; }
563 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cend() const noexcept { return {data_ + size_, this}; }
564 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
565 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
566 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { return crbegin(); }
567 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rend() const noexcept { return crend(); }
568 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
569 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
570
571 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type size() const noexcept { return size_; }
572 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type max_size() const noexcept { return npos; }
573 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type capacity() const noexcept { return capacity_pair_.value; }
574 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type length() const noexcept { return size_; }
575 MSTL_NODISCARD MSTL_CONSTEXPR20 bool empty() const noexcept { return size_ == 0; }
576
577 MSTL_NODISCARD MSTL_CONSTEXPR20 allocator_type get_allocator() const noexcept { return allocator_type(); }
578
579 MSTL_CONSTEXPR20 void reserve_exact(const size_type n) {
580 MSTL_DEBUG_VERIFY(n < max_size(), "basic_string reserve index out of range.");
581 if (capacity_pair_.value >= n) return;
582
583 pointer new_buffer = capacity_pair_.get_base().allocate(n);
584 traits_type::move(new_buffer, data_, size_);
585 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
586
587 data_ = new_buffer;
588 capacity_pair_.value = n;
589 null_terminate();
590 }
591
592 MSTL_CONSTEXPR20 void reserve(const size_type n) {
593 reserve_exact(n + 1);
594 }
595
596 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](const size_type n) noexcept {
597 MSTL_DEBUG_VERIFY(n <= size_, "basic_string [] index out of range.");
598 return *(data() + n);
599 }
600 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference operator [](const size_type n) const noexcept {
601 MSTL_DEBUG_VERIFY(n <= size_, "basic_string [] index out of range.");
602 return *(data() + n);
603 }
604
605 MSTL_NODISCARD MSTL_CONSTEXPR20 reference at(const size_type n) noexcept {
606 MSTL_DEBUG_VERIFY(n < size_, "basic_string index out of ranges.");
607 return (*this)[n];
608 }
609 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference at(const size_type n) const noexcept {
610 MSTL_DEBUG_VERIFY(n < size_, "basic_string index out of ranges.");
611 return (*this)[n];
612 }
613
614 MSTL_NODISCARD MSTL_CONSTEXPR20 reference front() noexcept {
615 MSTL_DEBUG_VERIFY(!empty(), "front called on empty basic_string");
616 return *data();
617 }
618 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference front() const noexcept {
619 MSTL_DEBUG_VERIFY(!empty(), "front called on empty basic_string");
620 return *data();
621 }
622 MSTL_NODISCARD MSTL_CONSTEXPR20 reference back() noexcept {
623 MSTL_DEBUG_VERIFY(!empty(), "back called on empty basic_string");
624 return *(data() + size_ - 1);
625 }
626 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference back() const noexcept {
627 MSTL_DEBUG_VERIFY(!empty(), "back called on empty basic_string");
628 return *(data() + size_ - 1);
629 }
630
631 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer data() noexcept { return data_; }
632 MSTL_NODISCARD MSTL_CONSTEXPR20 const_pointer data() const noexcept { return data_; }
633 MSTL_NODISCARD MSTL_CONSTEXPR20 const_pointer c_str() const noexcept { return data_; }
634
635 MSTL_CONSTEXPR20 iterator insert(iterator position, value_type chr) {
636 if (size_ == capacity_pair_.value) {
637 return this->reallocate_and_fill(position, 1, chr);
638 }
639
640 size_type offset = position - begin();
641 pointer p = data_ + offset;
642 size_type chars_after = size_ - offset;
643 if (chars_after > 0) {
644 traits_type::move(p + 1, p, chars_after);
645 }
646
647 *p = chr;
648 ++size_;
649 null_terminate();
650 return iterator(p, this);
651 }
652
653 MSTL_CONSTEXPR20 basic_string& insert(size_type position, size_type n, value_type chr) {
654 this->insert(begin() + position, n, chr);
655 return *this;
656 }
657
658 MSTL_CONSTEXPR20 iterator insert(iterator position, size_type n, value_type chr) {
659 if (n == 0) return position;
660 if (capacity_pair_.value - size_ < n) {
661 return this->reallocate_and_fill(position, n, chr);
662 }
663
664 const size_type offset = position - begin();
665 pointer p = data_ + offset;
666 const size_type chars_after = size_ - offset;
667
668 if (chars_after > 0) {
669 traits_type::move(p + n, p, chars_after);
670 }
671 traits_type::assign(p, n, chr);
672
673 size_ += n;
674 null_terminate();
675 return iterator(p, this);
676 }
677
678 template <typename Iterator>
679 MSTL_CONSTEXPR20 iterator insert(iterator position, Iterator first, Iterator last) {
680 const size_type len = _MSTL distance(first, last);
681 if (len == 0) return position;
682 if (capacity_pair_.value - size_ < len) {
683 return reallocate_and_copy(position, first, last);
684 }
685
686 const size_type offset = position - begin();
687 pointer p = data_ + offset;
688 const size_type chars_after = size_ - offset;
689
690 if (chars_after > 0) {
691 traits_type::move(p + len, p, chars_after);
692 }
693 pointer curr = p;
694 for (Iterator it = first; it != last; ++it, ++curr) {
695 *curr = *it;
696 }
697
698 size_ += len;
699 null_terminate();
700 return position;
701 }
702
703 MSTL_CONSTEXPR20 void push_back(value_type chr) {
704 this->append(1, chr);
705 }
706
707 MSTL_CONSTEXPR20 void pop_back() noexcept {
708 MSTL_DEBUG_VERIFY(!empty(), "pop_back called on empty basic_string");
709 --size_;
710 null_terminate();
711 }
712
713 MSTL_CONSTEXPR20 basic_string& append(size_type n, value_type chr) {
714 MSTL_DEBUG_VERIFY(size_ + n < max_size(), "basic_string append iterator out of ranges.");
715 if (capacity_pair_.value - size_ <= n) reallocate(n);
716 traits_type::assign(data_ + size_, n, chr);
717 size_ += n;
718 null_terminate();
719 return *this;
720 }
721 MSTL_CONSTEXPR20 basic_string& append(value_type chr) { return this->append(1, chr); }
722
723 MSTL_CONSTEXPR20 basic_string& append(const basic_string& str, size_type position, size_type n) {
724 MSTL_DEBUG_VERIFY(size_ + n < max_size(), "basic_string append iterator out of ranges.");
725 if (n == 0) return *this;
726
727 if (capacity_pair_.value - size_ <= n) reallocate(n);
728 traits_type::copy(data_ + size_, str.data_ + position, n);
729 size_ += n;
730 null_terminate();
731 return *this;
732 }
733
734 MSTL_CONSTEXPR20 basic_string& append(const basic_string& str) {
735 return this->append(str, 0, str.size_);
736 }
737 MSTL_CONSTEXPR20 basic_string& append(const basic_string& str, size_type position) {
738 return this->append(str, position, str.size_ - position);
739 }
740
741 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str, size_type position, size_type n) {
742 MSTL_DEBUG_VERIFY(size_ + n < max_size(), "basic_string append iterator out of ranges.");
743 if (n == 0) return *this;
744
745 if (capacity_pair_.value - size_ <= n) reallocate(n);
746 traits_type::move(data_ + size_, str.data_ + position, n);
747 size_ += n;
748 null_terminate();
749 return *this;
750 }
751
752 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str) {
753 const size_type len = str.size_;
754 return this->append(_MSTL move(str), 0, len);
755 }
756 MSTL_CONSTEXPR20 basic_string& append(basic_string&& str, size_type position) {
757 const size_type len = str.size_;
758 return this->append(_MSTL move(str), position, len - position);
759 }
760
761 MSTL_CONSTEXPR20 basic_string& append(view_type str, size_type n) {
762 return this->append(str.data(), n);
763 }
764 MSTL_CONSTEXPR20 basic_string& append(view_type str) {
765 return this->append(str.data(), str.size());
766 }
767
768 MSTL_CONSTEXPR20 basic_string& append(const_pointer str, size_type n) {
769 MSTL_DEBUG_VERIFY(size_ + n < max_size(), "basic_string append iterator out of ranges.");
770 if (capacity_pair_.value - size_ <= n) reallocate(n);
771 traits_type::copy(data_ + size_, str, n);
772 size_ += n;
773 null_terminate();
774 return *this;
775 }
776 MSTL_CONSTEXPR20 basic_string& append(const_pointer str) {
777 return this->append(str, traits_type::length(str));
778 }
779
780 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
781 MSTL_CONSTEXPR20 basic_string& append(Iterator first, Iterator last) {
782 const size_type n = _MSTL distance(first, last);
783 MSTL_DEBUG_VERIFY(size_ + n < max_size(), "basic_string append iterator out of ranges.");
784
785 if (capacity_pair_.value - size_ <= n) reallocate(n);
786 _MSTL uninitialized_copy_n(first, n, data_ + size_);
787 size_ += n;
788 null_terminate();
789 return *this;
790 }
791
792 MSTL_CONSTEXPR20 basic_string& append(std::initializer_list<value_type> l) {
793 return this->append(l.begin(), l.end());
794 }
795
796 MSTL_CONSTEXPR20 basic_string& assign(const basic_string& str) { return *this = str; }
797 MSTL_CONSTEXPR20 basic_string& assign(basic_string&& str) { return *this = _MSTL move(str); }
798 MSTL_CONSTEXPR20 basic_string& assign(const_pointer str) { return *this = str; }
799
800 MSTL_CONSTEXPR20 basic_string& assign(const_pointer str, const size_type n) {
801 this->clear();
802 return this->append(str, n);
803 }
804 MSTL_CONSTEXPR20 basic_string& assign(const size_type n, value_type chr) {
805 this->clear();
806 return this->append(n, chr);
807 }
808 template <typename Iterator>
809 MSTL_CONSTEXPR20 basic_string& assign(Iterator first, Iterator last) {
810 this->clear();
811 return this->append(first, last);
812 }
813
814 MSTL_CONSTEXPR20 basic_string& assign(std::initializer_list<value_type> ilist) {
815 return *this = ilist;
816 }
817 MSTL_CONSTEXPR20 basic_string& assign(const view_type& view) {
818 return *this = view;
819 }
820
821 MSTL_CONSTEXPR20 basic_string& operator +=(const basic_string& str) { return this->append(str); }
822 MSTL_CONSTEXPR20 basic_string& operator +=(basic_string&& str) { return this->append(_MSTL move(str)); }
823 MSTL_CONSTEXPR20 basic_string& operator +=(value_type chr) { return this->append(chr); }
824 MSTL_CONSTEXPR20 basic_string& operator +=(const_pointer str) { return this->append(str); }
825 MSTL_CONSTEXPR20 basic_string& operator +=(std::initializer_list<value_type> lls) { return this->append(lls); }
826 MSTL_CONSTEXPR20 basic_string& operator +=(view_type view) { return this->append(view); }
827
828 MSTL_CONSTEXPR20 iterator erase(iterator position) noexcept {
829 MSTL_DEBUG_VERIFY(position != end(), "erase: cannot erase end() iterator");
830
831 pointer p = &*position;
832 const size_type chars_after = end() - position - 1;
833 if (chars_after > 0) {
834 traits_type::move(p, p + 1, chars_after);
835 }
836
837 --size_;
838 null_terminate();
839 return position;
840 }
841
842 MSTL_CONSTEXPR20 basic_string& erase(size_type pos = 0, size_type len = npos) noexcept {
843 if (pos >= size_) return *this;
844 if (len == npos || pos + len >= size_) {
845 len = size_ - pos;
846 }
847 this->erase(begin() + pos, len);
848 return *this;
849 }
850
851 MSTL_CONSTEXPR20 iterator erase(iterator first, const size_type n) noexcept {
852 if (n == 0) return first;
853 iterator last = first + _MSTL min(n, static_cast<size_type>(end() - first));
854 return this->erase(first, last);
855 }
856
857 MSTL_CONSTEXPR20 iterator erase(iterator first, iterator last) noexcept {
858 if (first == last) return first;
859
860 const size_type erase_count = last - first;
861 const size_type chars_after = end() - last;
862
863 if (chars_after > 0) {
864 pointer p_first = data_ + (first - begin());
865 pointer p_last = data_ + (last - begin());
866 traits_type::move(p_first, p_last, chars_after);
867 }
868
869 size_ -= erase_count;
870 null_terminate();
871 return first;
872 }
873
874
875 MSTL_CONSTEXPR20 void resize(size_type count, value_type chr) {
876 if (count < size_)
877 this->erase({data_ + count, this}, {data_ + size_, this});
878 else
879 this->append(count - size_, chr);
880 }
881
882 MSTL_CONSTEXPR20 void resize(const size_type count) {
883 this->resize(count, value_type());
884 }
885
886 template <typename Operation>
887 MSTL_CONSTEXPR20 void resize_and_overwrite(size_type count, Operation op) {
888 MSTL_DEBUG_VERIFY(count < max_size(), "resize_and_overwrite: count too large");
889 if (count >= capacity_pair_.value) {
890 this->reserve(count + 1);
891 }
892 const size_type old_size = size_;
893 size_ = count;
894
895 try {
896 const size_type actual_size = op(data_, count);
897 if (actual_size > count) {
898 size_ = old_size;
899 throw_exception(value_exception("resize_and_overwrite: operation returned invalid size"));
900 }
901 size_ = actual_size;
902 null_terminate();
903 } catch (...) {
904 size_ = old_size;
905 null_terminate();
906 throw;
907 }
908 }
909
910 MSTL_CONSTEXPR20 void clear() noexcept {
911 size_ = 0;
912 null_terminate();
913 }
914
915 MSTL_CONSTEXPR20 void shrink_to_fit() {
916 const size_type new_cap = size_ + 1;
917 if (new_cap >= capacity_pair_.value) return;
918
919 basic_string temp;
920 temp.reserve(new_cap);
921 temp.append(*this);
922 this->swap(temp);
923 }
924
925 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string repeat(size_type n) const noexcept {
926 basic_string result;
927 result.reserve(size() * n);
928 while (n--) result += *this;
929 return _MSTL move(result);
930 }
931
932 MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string substr(const size_type off = 0, size_type count = npos) const {
933 MSTL_DEBUG_VERIFY(off < size_, "basic_string index out of ranges.");
934 count = _MSTL min(count, size_ - off);
935 return basic_string(data() + off, count);
936 }
937
938 MSTL_NODISCARD MSTL_CONSTEXPR20 view_type view() const noexcept {
939 return view_type(data(), size());
940 }
941
942 MSTL_NODISCARD MSTL_CONSTEXPR20 view_type view(const size_type off, size_type count = npos) const noexcept {
943 MSTL_DEBUG_VERIFY(off < size_, "basic_string index out of ranges.");
944 count = _MSTL min(count, size_ - off);
945 return view_type(data() + off, count);
946 }
947
948
949 MSTL_CONSTEXPR20 size_type copy(pointer dest, const size_type count, size_type position = 0) const {
950 MSTL_DEBUG_VERIFY(position <= size_, "basic_string copy position out of range");
951 const size_type len = _MSTL min(count, size_ - position);
952 traits_type::copy(dest, data() + position, len);
953 return len;
954 }
955
956
957 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const basic_string& str) const noexcept {
958 return this->compare(str.view());
959 }
960 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const size_type off, const size_type n, const basic_string& str) const {
961 return view(off, n).compare(str);
962 }
963 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const size_type off, const size_type n, const basic_string& str,
964 const size_type roff, const size_type count) const {
965 return view(off, n).compare(str.view(roff, count));
966 }
967 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const CharT* const str) const noexcept {
968 return this->compare(view_type(str));
969 }
970 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const string_view& str) const noexcept {
971 return _MSTL char_traits_compare<Traits>(data(), size_, str.data(), str.size());
972 }
973 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const size_type off, const size_type n, const CharT* const str) const {
974 return view(off, n).compare(view_type(str));
975 }
976 MSTL_NODISCARD MSTL_CONSTEXPR20 int compare(const size_type off, const size_type n,
977 const CharT* const str, const size_type count) const {
978 return view(off, n).compare(view_type(str, count));
979 }
980
981 MSTL_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n, const basic_string& str) {
982 MSTL_DEBUG_VERIFY(position < size_, "basic_string index out of ranges.");
983 return this->replace_copy(begin() + position, n, str.data(), str.size_);
984 }
985 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const basic_string& str) {
986 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last, "basic_string replace iterator out of ranges.");
987 return this->replace_copy(first, last - first, str.data(), str.size_);
988 }
989 MSTL_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n, const_pointer str) {
990 MSTL_DEBUG_VERIFY(position < size_, "basic_string index out of ranges.");
991 return this->replace_copy({data() + position, this}, n, str, traits_type::length(str));
992 }
993 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str) {
994 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last, "basic_string replace iterator out of ranges.");
995 return this->replace_copy(first, last - first, str, traits_type::length(str));
996 }
997 MSTL_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n1, const_pointer str, const size_type n2) {
998 MSTL_DEBUG_VERIFY(position < size_, "basic_string index out of ranges.");
999 return this->replace_copy(data() + position, n1, str, n2);
1000 }
1001 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str, const size_type n) {
1002 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last, "basic_string replace iterator out of ranges.");
1003 return this->replace_copy(first, last - first, str, n);
1004 }
1005 MSTL_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n1, const size_type n2, const value_type chr) {
1006 MSTL_DEBUG_VERIFY(position < size_, "basic_string index out of ranges.");
1007 return this->replace_fill(data() + position, n1, n2, chr);
1008 }
1009 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const size_type n, const value_type chr) {
1010 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last, "basic_string replace iterator out of ranges.");
1011 return this->replace_fill(first, static_cast<size_type>(last - first), n, chr);
1012 }
1013 MSTL_CONSTEXPR20 basic_string& replace(const size_type position1, const size_type n1, const basic_string& str,
1014 const size_type position2, const size_type n2 = npos) {
1015 MSTL_DEBUG_VERIFY(position1 < size_, "basic_string index out of ranges.");
1016 MSTL_DEBUG_VERIFY(position2 < size_, "basic_string index out of ranges.");
1017 return this->replace_copy(data() + position1, n1, str.data_ + position2, n2);
1018 }
1019 template <typename Iterator>
1020 MSTL_CONSTEXPR20 basic_string& replace(iterator first, iterator last, Iterator first2, Iterator last2) {
1021 MSTL_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last, "basic_string replace iterator out of ranges.");
1022 return this->replace_copy(first, last, first2, last2);
1023 }
1024
1025 MSTL_CONSTEXPR20 void reverse() noexcept {
1026 if (size() < 2) return;
1027 for (iterator first = begin(), last = end(); first < last; ) {
1028 _MSTL iter_swap(first++, --last);
1029 }
1030 }
1031
1032 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(const basic_string& str, const size_type n = 0) const noexcept {
1033 return (char_traits_find<Traits>)(data(), size_, n, str.data(), str.size_);
1034 }
1035 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(const CharT chr, const size_type n = 0) const noexcept {
1036 return (char_traits_find_char<Traits>)(data(), size_, n, chr);
1037 }
1038 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(const CharT* const str,
1039 const size_type off, const size_type count) const noexcept {
1040 return (char_traits_find<Traits>)(data(), size_, off, str, count);
1041 }
1042 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(const CharT* const str, const size_type off = 0) const noexcept {
1043 return (char_traits_find<Traits>)(data(), size_, off, str, Traits::length(str));
1044 }
1045 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(
1046 const string_view& str, const size_type off, const size_type count) const noexcept {
1047 return (char_traits_find<Traits>)(data(), size_, off, str.data(), count);
1048 }
1049 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find(const string_view& str, const size_type off = 0) const noexcept {
1050 return _MSTL char_traits_find<Traits>(data(), size_, off, str.data(), str.size());
1051 }
1052
1053 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(const basic_string& str, const size_type off = npos) const noexcept {
1054 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), str.size_);
1055 }
1056 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(const CharT chr, const size_type n = npos) const noexcept {
1057 return (char_traits_rfind_char<Traits>)(data(), size_, n, chr);
1058 }
1059 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(const CharT* const str, const size_type off,
1060 const size_type n) const noexcept {
1061 return (char_traits_rfind<Traits>)(data(), size_, off, str, n);
1062 }
1063 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(const CharT* const str, const size_type off = npos) const noexcept {
1064 return (char_traits_rfind<Traits>)(data(), size_, off, str, Traits::length(str));
1065 }
1066 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(
1067 const string_view& str, const size_type off, const size_type count) const noexcept {
1068 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), count);
1069 }
1070 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type rfind(const string_view& str, const size_type off = 0) const noexcept {
1071 return (char_traits_rfind<Traits>)(data(), size_, off, str.data(), str.size());
1072 }
1073
1074 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(const basic_string& str, const size_type off = 0) const noexcept {
1075 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data_, str.size_);
1076 }
1077 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(const CharT chr, const size_type off = 0) const noexcept {
1078 return (char_traits_find_char<Traits>)(data(), size_, off, chr);
1079 }
1080 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(const CharT* const str, const size_type off,
1081 const size_type n) const noexcept {
1082 return (char_traits_find_first_of<Traits>)(data(), size_, off, str, n);
1083 }
1084 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(const CharT* const str, const size_type off = 0) const noexcept {
1085 return (char_traits_find_first_of<Traits>)(data(), size_, off, str, Traits::length(str));
1086 }
1087 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(
1088 const string_view& str, const size_type off, const size_type n) const noexcept {
1089 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data(), n);
1090 }
1091 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_of(const string_view& str, const size_type off = 0) const noexcept {
1092 return (char_traits_find_first_of<Traits>)(data(), size_, off, str.data(), str.size());
1093 }
1094
1095 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(const basic_string& str, const size_type off = npos) const noexcept {
1096 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), str.size_);
1097 }
1098 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(const CharT chr, const size_type off = npos) const noexcept {
1099 return (char_traits_rfind_char<Traits>)(data(), size_, off, chr);
1100 }
1101 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(const CharT* const str, const size_type off,
1102 const size_type n) const noexcept {
1103 return (char_traits_find_last_of<Traits>)(data(), size_, off, str, n);
1104 }
1105 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(const CharT* const str, const size_type off = npos) const noexcept {
1106 return (char_traits_find_last_of<Traits>)(data(), size_, off, str, Traits::length(str));
1107 }
1108 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(
1109 const string_view& str, const size_type off, const size_type n) const noexcept {
1110 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), n);
1111 }
1112 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_of(const string_view& str, const size_type off = npos) const noexcept {
1113 return (char_traits_find_last_of<Traits>)(data(), size_, off, str.data(), str.size());
1114 }
1115
1116 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(const basic_string& str, const size_type off = 0) const noexcept {
1117 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), str.size_);
1118 }
1119 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(const CharT chr, const size_type off = 0) const noexcept {
1120 return (char_traits_find_not_char<Traits>)(data(), size_, off, chr);
1121 }
1122 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(const CharT* const str, const size_type off,
1123 const size_type n) const noexcept {
1124 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str, n);
1125 }
1126 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(const CharT* const str, const size_type off = 0) const noexcept {
1127 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str, Traits::length(str));
1128 }
1129 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(
1130 const string_view& str, const size_type off, const size_type n) const noexcept {
1131 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), n);
1132 }
1133 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_first_not_of(const string_view& str, const size_type off = 0) const noexcept {
1134 return (char_traits_find_first_not_of<Traits>)(data(), size_, off, str.data(), str.size());
1135 }
1136
1137 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(const basic_string& str, const size_type off = npos) const noexcept {
1138 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data_, str.size_);
1139 }
1140 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(const CharT chr, const size_type off = npos) const noexcept {
1141 return (char_traits_rfind_not_char<Traits>)(data(), size_, off, chr);
1142 }
1143 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1144 const CharT* const str, const size_type off, const size_type n) const noexcept {
1145 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str, n);
1146 }
1147 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(const CharT* const str,
1148 const size_type off = npos) const noexcept {
1149 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str, Traits::length(str));
1150 }
1151 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1152 const string_view& str, const size_type off, const size_type n) const noexcept {
1153 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data(), n);
1154 }
1155 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type find_last_not_of(
1156 const string_view& str, const size_type off = npos) const noexcept {
1157 return (char_traits_find_last_not_of<Traits>)(data(), size_, off, str.data(), str.size());
1158 }
1159
1160
1161 MSTL_CONSTEXPR20 size_type count(value_type chr, const size_type position = 0) const noexcept {
1162 size_type n = 0;
1163 for (size_type idx = position; idx < size_; ++idx) {
1164 if (*(data() + idx) == chr) ++n;
1165 }
1166 return n;
1167 }
1168
1169 MSTL_NODISCARD MSTL_CONSTEXPR20 bool starts_with(view_type view) const noexcept {
1170 return view.size() <= size_ && traits_type::compare(data(), view.data(), view.size()) == 0;
1171 }
1172 MSTL_NODISCARD MSTL_CONSTEXPR20 bool starts_with(value_type chr) const noexcept {
1173 return !empty() && traits_type::eq(front(), chr);
1174 }
1175 MSTL_NODISCARD MSTL_CONSTEXPR20 bool starts_with(const_pointer str) const noexcept {
1176 return this->starts_with(view_type(str));
1177 }
1178
1179 MSTL_NODISCARD MSTL_CONSTEXPR20 bool ends_with(view_type view) const noexcept {
1180 const size_type view_size = view.size();
1181 return view_size <= size_ && traits_type::compare(data_ + size_ - view_size, view.data(), view_size) == 0;
1182 }
1183 MSTL_NODISCARD MSTL_CONSTEXPR20 bool ends_with(value_type chr) const noexcept {
1184 return !empty() && traits_type::eq(back(), chr);
1185 }
1186 MSTL_NODISCARD MSTL_CONSTEXPR20 bool ends_with(const_pointer str) const noexcept {
1187 return this->ends_with(view_type(str));
1188 }
1189
1190 MSTL_NODISCARD MSTL_CONSTEXPR20 bool contains(view_type view) const noexcept {
1191 return this->find(view) != npos;
1192 }
1193 MSTL_NODISCARD MSTL_CONSTEXPR20 bool contains(value_type chr) const noexcept {
1194 return this->find(chr) != npos;
1195 }
1196 MSTL_NODISCARD MSTL_CONSTEXPR20 bool contains(const_pointer str) const noexcept {
1197 return this->find(str) != npos;
1198 }
1199
1200
1201 MSTL_CONSTEXPR20 basic_string& trim_left() noexcept {
1202 return this->trim_left_if([](value_type ch) { return _MSTL is_space(ch); });
1203 }
1204 MSTL_CONSTEXPR20 basic_string& trim_right() noexcept {
1205 return this->trim_right_if([](value_type ch) { return _MSTL is_space(ch); });
1206 }
1207 MSTL_CONSTEXPR20 basic_string& trim() noexcept { return this->trim_left().trim_right(); }
1208
1209 template <typename Predicate>
1210 MSTL_CONSTEXPR20 basic_string& trim_left_if(Predicate pred)
1211 noexcept(noexcept(pred(*cbegin()))) {
1212 if (empty()) return *this;
1213
1214 const_iterator it = cbegin();
1215 while (it != cend() && pred(*it))
1216 ++it;
1217
1218 if (it != cbegin())
1219 this->erase(begin(), it - begin());
1220
1221 return *this;
1222 }
1223
1224 template <typename Predicate>
1225 MSTL_CONSTEXPR20 basic_string& trim_right_if(Predicate pred)
1226 noexcept(noexcept(pred(*crbegin()))) {
1227 if (empty()) return *this;
1228
1229 const_reverse_iterator rit = crbegin();
1230 while (rit != crend() && pred(*rit))
1231 ++rit;
1232
1233 if (rit != crbegin())
1234 this->erase(end() - (rit - crbegin()), end());
1235
1236 return *this;
1237 }
1238
1239 template <typename Predicate>
1240 MSTL_CONSTEXPR20 basic_string& trim_if(Predicate pred)
1241 noexcept(noexcept(this->trim_right_if(pred)) && noexcept(this->trim_left_if(pred))) {
1242 return this->trim_left_if(pred).trim_right_if(pred);
1243 }
1244
1245 MSTL_CONSTEXPR20 bool equal_to(const basic_string& str) const noexcept {
1246 return this->equal_to(str.view());
1247 }
1248 MSTL_CONSTEXPR20 bool equal_to(const view_type str) const noexcept {
1249 return _MSTL char_traits_equal<Traits>(data(), size_, str.data(), str.size());
1250 }
1251 MSTL_CONSTEXPR20 bool equal_to(const CharT* str) const noexcept {
1252 return this->equal_to(view_type(str));
1253 }
1254
1255 MSTL_CONSTEXPR20 bool iequal_to(const basic_string& str) const noexcept {
1256 return this->iequal_to(str.view());
1257 }
1258 MSTL_CONSTEXPR20 bool iequal_to(const view_type str) const noexcept {
1259 return _MSTL char_traits_equal<Traits>(data(), size_, str.data(), str.size());
1260 }
1261 MSTL_CONSTEXPR20 bool iequal_to(const CharT* str) const noexcept {
1262 return this->iequal_to(view_type(str));
1263 }
1264
1265 MSTL_CONSTEXPR20 void lowercase()
1266 noexcept(noexcept(_MSTL transform(begin(), end(), begin(), _MSTL to_lowercase<CharT>))) {
1267 _MSTL transform(begin(), end(), begin(), _MSTL to_lowercase<CharT>);
1268 }
1269 MSTL_CONSTEXPR20 void uppercase()
1270 noexcept(noexcept(_MSTL transform(begin(), end(), begin(), _MSTL to_uppercase<CharT>))) {
1271 _MSTL transform(begin(), end(), begin(), _MSTL to_uppercase<CharT>);
1272 }
1273
1274 MSTL_CONSTEXPR20 void swap(basic_string& x) noexcept {
1275 if (_MSTL addressof(x) == this) return;
1276 _MSTL swap(data_, x.data_);
1277 _MSTL swap(size_, x.size_);
1278 _MSTL swap(capacity_pair_, x.capacity_pair_);
1279 }
1280
1281 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(const basic_string& rhs) const noexcept { return this->equal_to(rhs); }
1282 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(const basic_string& rhs) const noexcept { return this->compare(rhs) < 0; }
1283
1284 MSTL_NODISCARD MSTL_CONSTEXPR20 size_t to_hash() const noexcept {
1285 return _INNER FNV_hash_string(this->data(), this->length());
1286 }
1287};
1288#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
1289template <typename Iterator, typename Alloc = allocator<iter_value_t<Iterator>>>
1290basic_string(Iterator, Iterator, Alloc = Alloc())
1291-> basic_string<iter_value_t<Iterator>, char_traits<iter_value_t<Iterator>>, Alloc>;
1292
1293template <typename CharT, typename Traits, typename Alloc = allocator<CharT>>
1294explicit basic_string(basic_string_view<CharT, Traits>, const Alloc & = Alloc())
1295-> basic_string<CharT, Traits, Alloc>;
1296
1297template <typename CharT, typename Traits, typename Alloc = allocator<CharT>>
1298basic_string(basic_string_view<CharT, Traits>,
1301 const Alloc & = Alloc())
1302-> basic_string<CharT, Traits, Alloc>;
1303#endif
1304
1305template <typename CharT, typename Traits, typename Alloc>
1306MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1307 const basic_string<CharT, Traits, Alloc>& lhs, const basic_string<CharT, Traits, Alloc>& rhs) {
1308 basic_string<CharT, Traits, Alloc> tmp(lhs);
1309 tmp.append(rhs);
1310 return _MSTL move(tmp);
1311}
1312
1313template <typename CharT, typename Traits, typename Alloc>
1314MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1315 const CharT* lhs, const basic_string<CharT, Traits, Alloc>& rhs) {
1316 basic_string<CharT, Traits, Alloc> tmp(lhs);
1317 tmp.append(rhs);
1318 return _MSTL move(tmp);
1319}
1320template <typename CharT, typename Traits, typename Alloc>
1321MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1322 const basic_string<CharT, Traits, Alloc>& lhs, const CharT* rhs) {
1323 basic_string<CharT, Traits, Alloc> tmp(lhs);
1324 tmp.append(rhs);
1325 return _MSTL move(tmp);
1326}
1327
1328template <typename CharT, typename Traits, typename Alloc>
1329MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1330 const string_view& lhs, const basic_string<CharT, Traits, Alloc>& rhs) {
1331 basic_string<CharT, Traits, Alloc> tmp(lhs);
1332 tmp.append(rhs);
1333 return _MSTL move(tmp);
1334}
1335template <typename CharT, typename Traits, typename Alloc>
1336MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1337 const basic_string<CharT, Traits, Alloc>& lhs, const string_view& rhs) {
1338 basic_string<CharT, Traits, Alloc> tmp(lhs);
1339 tmp.append(rhs);
1340 return _MSTL move(tmp);
1341}
1342
1343template <typename CharT, typename Traits, typename Alloc>
1344MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1345 CharT lhs, const basic_string<CharT, Traits, Alloc>& rhs) {
1346 basic_string<CharT, Traits, Alloc> tmp(1, lhs);
1347 tmp.append(rhs);
1348 return _MSTL move(tmp);
1349}
1350template <typename CharT, typename Traits, typename Alloc>
1351MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1352 const basic_string<CharT, Traits, Alloc>& lhs, CharT rhs) {
1353 basic_string<CharT, Traits, Alloc> tmp(lhs);
1354 tmp.append(1, rhs);
1355 return _MSTL move(tmp);
1356}
1357
1358template <typename CharT, typename Traits, typename Alloc>
1359MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1360 basic_string<CharT, Traits, Alloc>&& lhs, const basic_string<CharT, Traits, Alloc>& rhs) {
1361 return _MSTL move(lhs.append(rhs));
1362}
1363template <typename CharT, typename Traits, typename Alloc>
1364MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1365 const basic_string<CharT, Traits, Alloc>& lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1366 basic_string<CharT, Traits, Alloc> tmp(lhs);
1367 tmp.append(_MSTL move(rhs));
1368 return _MSTL move(tmp);
1369}
1370
1371template <typename CharT, typename Traits, typename Alloc>
1372MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1373 basic_string<CharT, Traits, Alloc>&& lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1374 basic_string<CharT, Traits, Alloc> tmp(_MSTL move(lhs));
1375 if (_MSTL addressof(lhs) != _MSTL addressof(rhs)) {
1376 tmp.append(_MSTL move(rhs));
1377 } else {
1378 tmp.append(lhs);
1379 }
1380 return _MSTL move(tmp);
1381}
1382
1383template <typename CharT, typename Traits, typename Alloc>
1384MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1385 const CharT* lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1386 basic_string<CharT, Traits, Alloc> tmp(lhs);
1387 tmp.append(_MSTL move(rhs));
1388 return _MSTL move(tmp);
1389}
1390template <typename CharT, typename Traits, typename Alloc>
1391MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1392 basic_string<CharT, Traits, Alloc>&& lhs, const CharT* rhs) {
1393 return _MSTL move(lhs.append(rhs));
1394}
1395
1396template <typename CharT, typename Traits, typename Alloc>
1397MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1398 CharT lhs, basic_string<CharT, Traits, Alloc>&& rhs) {
1399 basic_string<CharT, Traits, Alloc> tmp(1, lhs);
1400 tmp.append(_MSTL move(rhs));
1401 return _MSTL move(tmp);
1402}
1403template <typename CharT, typename Traits, typename Alloc>
1404MSTL_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator +(
1405 basic_string<CharT, Traits, Alloc>&& lhs, CharT rhs) {
1406 return _MSTL move(lhs.append(rhs));
1407}
1408
1409template <typename CharT, typename Traits, typename Alloc>
1410MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(
1411 const CharT* const lhs,
1412 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1413 return rhs.equal_to(lhs);
1414}
1415template <typename CharT, typename Traits, typename Alloc>
1416MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(
1417 const basic_string<CharT, Traits, Alloc>& lhs,
1418 const CharT* const rhs) noexcept {
1419 return lhs.equal_to(rhs);
1420}
1421template <typename CharT, typename Traits, typename Alloc>
1422MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(
1423 const basic_string_view<CharT, Traits>& lhs,
1424 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1425 return rhs.equal_to(lhs);
1426}
1427template <typename CharT, typename Traits, typename Alloc>
1428MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(
1429 const basic_string<CharT, Traits, Alloc>& lhs,
1430 const basic_string_view<CharT, Traits>& rhs) noexcept {
1431 return lhs.equal_to(rhs);
1432}
1433
1434template <typename CharT, typename Traits, typename Alloc>
1435MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(
1436 const CharT* const lhs,
1437 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1438 return !(lhs == rhs);
1439}
1440template <typename CharT, typename Traits, typename Alloc>
1441MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(
1442 const basic_string<CharT, Traits, Alloc>& lhs,
1443 const CharT* const rhs) noexcept {
1444 return !(lhs == rhs);
1445}
1446template <typename CharT, typename Traits, typename Alloc>
1447MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(
1448 const basic_string_view<CharT, Traits>& lhs,
1449 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1450 return !(lhs == rhs);
1451}
1452template <typename CharT, typename Traits, typename Alloc>
1453MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(
1454 const basic_string<CharT, Traits, Alloc>& lhs,
1455 const basic_string_view<CharT, Traits>& rhs) noexcept {
1456 return !(lhs == rhs);
1457}
1458
1459template <typename CharT, typename Traits, typename Alloc>
1460MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(
1461 const CharT* const lhs,
1462 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1463 return 0 < rhs.compare(lhs);
1464}
1465template <typename CharT, typename Traits, typename Alloc>
1466MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(
1467 const basic_string<CharT, Traits, Alloc>& lhs,
1468 const CharT* const rhs) noexcept {
1469 return lhs.compare(rhs) < 0;
1470}
1471template <typename CharT, typename Traits, typename Alloc>
1472MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(
1473 const basic_string_view<CharT, Traits>& lhs,
1474 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1475 return 0 < rhs.compare(lhs);
1476}
1477template <typename CharT, typename Traits, typename Alloc>
1478MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(
1479 const basic_string<CharT, Traits, Alloc>& lhs,
1480 const basic_string_view<CharT, Traits>& rhs) noexcept {
1481 return lhs.compare(rhs) < 0;
1482}
1483
1484template <typename CharT, typename Traits, typename Alloc>
1485MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(
1486 const CharT* const lhs,
1487 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1488 return rhs < lhs;
1489}
1490template <typename CharT, typename Traits, typename Alloc>
1491MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(
1492 const basic_string<CharT, Traits, Alloc>& lhs,
1493 const CharT* const rhs) noexcept {
1494 return rhs < lhs;
1495}
1496template <typename CharT, typename Traits, typename Alloc>
1497MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(
1498 const basic_string_view<CharT, Traits>& lhs,
1499 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1500 return rhs < lhs;
1501}
1502template <typename CharT, typename Traits, typename Alloc>
1503MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(
1504 const basic_string<CharT, Traits, Alloc>& lhs,
1505 const basic_string_view<CharT, Traits>& rhs) noexcept {
1506 return rhs < lhs;
1507}
1508
1509template <typename CharT, typename Traits, typename Alloc>
1510MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(
1511 const CharT* const lhs,
1512 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1513 return !(lhs > rhs);
1514}
1515template <typename CharT, typename Traits, typename Alloc>
1516MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(
1517 const basic_string<CharT, Traits, Alloc>& lhs,
1518 const CharT* const rhs) noexcept {
1519 return !(lhs > rhs);
1520}
1521template <typename CharT, typename Traits, typename Alloc>
1522MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(
1523 const basic_string_view<CharT, Traits>& lhs,
1524 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1525 return !(lhs > rhs);
1526}
1527template <typename CharT, typename Traits, typename Alloc>
1528MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(
1529 const basic_string<CharT, Traits, Alloc>& lhs,
1530 const basic_string_view<CharT, Traits>& rhs) noexcept {
1531 return !(lhs > rhs);
1532}
1533
1534template <typename CharT, typename Traits, typename Alloc>
1535MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(
1536 const CharT* const lhs,
1537 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1538 return !(rhs < lhs);
1539}
1540template <typename CharT, typename Traits, typename Alloc>
1541MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(
1542 const basic_string<CharT, Traits, Alloc>& lhs,
1543 const CharT* const rhs) noexcept {
1544 return !(rhs < lhs);
1545}
1546template <typename CharT, typename Traits, typename Alloc>
1547MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(
1548 const basic_string_view<CharT, Traits>& lhs,
1549 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
1550 return !(rhs < lhs);
1551}
1552template <typename CharT, typename Traits, typename Alloc>
1553MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(
1554 const basic_string<CharT, Traits, Alloc>& lhs,
1555 const basic_string_view<CharT, Traits>& rhs) noexcept {
1556 return !(rhs < lhs);
1557}
1558
1560#endif // MSTL_CORE_STRING_BASIC_STRING_HPP__
MSTL分配器特性
MSTL压缩对实现
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 CharT to_uppercase(const CharT c) noexcept
将字符转换为大写
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 CharT to_lowercase(const CharT c) noexcept
将字符转换为小写
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 bool is_space(const CharT c) noexcept
检查字符是否为空白字符
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
constexpr const T & min(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(b, a)))
返回两个值中的较小者
int int32_t
32位有符号整数类型
MSTL_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
#define _MSTL
全局命名空间MSTL前缀
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BUILD_TYPE_ALIAS(TYPE)
快速构建标准类型别名
constexpr void iter_swap(Iterator1 a, Iterator2 b) noexcept(noexcept(_MSTL swap(*a, *b)))
交换迭代器指向的元素
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
constexpr Iterator2 transform(Iterator1 first, Iterator1 last, Iterator2 result, UnaryOperation op) noexcept(noexcept(++first) &&noexcept(++result) &&noexcept(*result=op(*first)))
对范围元素应用一元变换
void swap()=delete
删除无参数的swap重载
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL_CONSTEXPR20 pair< Iterator1, Iterator2 > uninitialized_copy_n(Iterator1 first, size_t count, Iterator2 result)
复制指定数量的元素到未初始化内存
MSTL_CONSTEXPR20 Iterator2 uninitialized_copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制元素到未初始化内存
MSTL移位和修改算法
MSTL标准分配器
typename real_size< Alloc, difference_type >::type size_type
大小类型
通用接口,同时具备可比较和可哈希功能
MSTL_NODISCARD constexpr size_t to_hash() const noexcept(noexcept(derived().to_hash()))
获取对象的哈希值
MSTL未初始化内存操作