NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
basic_string.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_STRING_BASIC_STRING_HPP__
2#define NEFORCE_CORE_STRING_BASIC_STRING_HPP__
3
10
16NEFORCE_BEGIN_NAMESPACE__
17
23
32template <bool IsConst, typename String>
33struct basic_string_iterator : iiterator<basic_string_iterator<IsConst, String>> {
34public:
35 using container_type = String;
36 using value_type = typename container_type::value_type;
37 using size_type = typename container_type::size_type;
38 using difference_type = typename container_type::difference_type;
40 using reference = conditional_t<IsConst, typename container_type::const_reference,
41 typename container_type::reference>;
42 using pointer = conditional_t<IsConst, typename container_type::const_pointer,
43 typename container_type::pointer>;
44
45private:
46 pointer current_ = nullptr;
47 const container_type* str_ = nullptr;
48
49public:
50 NEFORCE_CONSTEXPR20 basic_string_iterator() noexcept = default;
51 NEFORCE_CONSTEXPR20 ~basic_string_iterator() = default;
52
53 NEFORCE_CONSTEXPR20 basic_string_iterator(const basic_string_iterator&) noexcept = default;
54 NEFORCE_CONSTEXPR20 basic_string_iterator& operator=(const basic_string_iterator&) noexcept = default;
55 NEFORCE_CONSTEXPR20 basic_string_iterator(basic_string_iterator&&) noexcept = default;
56 NEFORCE_CONSTEXPR20 basic_string_iterator& operator=(basic_string_iterator&&) noexcept = default;
57
63 NEFORCE_CONSTEXPR20 basic_string_iterator(pointer ptr, const container_type* str) noexcept :
64 current_(ptr),
65 str_(str) {}
66
71 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference dereference() const noexcept {
72 NEFORCE_DEBUG_VERIFY(current_ && str_, "Attempting to dereference on a null pointer");
73 NEFORCE_DEBUG_VERIFY(str_->data() <= current_ && current_ <= str_->data() + str_->size(),
74 "Attempting to dereference out of boundary");
75 return *current_;
76 }
77
81 NEFORCE_CONSTEXPR20 void increment() noexcept {
82 NEFORCE_DEBUG_VERIFY(current_ && str_, "Attempting to increment a null pointer");
83 NEFORCE_DEBUG_VERIFY(current_ < str_->data() + str_->size(), "Attempting to increment out of boundary");
84 ++current_;
85 }
86
90 NEFORCE_CONSTEXPR20 void decrement() noexcept {
91 NEFORCE_DEBUG_VERIFY(current_ && str_, "Attempting to decrement a null pointer");
92 NEFORCE_DEBUG_VERIFY(str_->data() < current_, "Attempting to decrement out of boundary");
93 --current_;
94 }
95
100 NEFORCE_CONSTEXPR20 void advance(difference_type off) noexcept {
101 NEFORCE_DEBUG_VERIFY((current_ && str_) || off == 0, "Attempting to advance a null pointer");
102 NEFORCE_DEBUG_VERIFY((off < 0 ? off >= str_->data() - current_ : off <= str_->data() + str_->size() - current_),
103 "Attempting to advance out of boundary");
104 current_ += off;
105 }
106
112 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 difference_type
113 distance_to(const basic_string_iterator& other) const noexcept {
114 NEFORCE_DEBUG_VERIFY(str_ == other.str_, "Attempting to distance to a different container");
115 return static_cast<difference_type>(current_ - other.current_);
116 }
117
123 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference operator[](difference_type n) const noexcept {
124 return *(*this + n);
125 }
126
132 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool equal(const basic_string_iterator& rhs) const noexcept {
133 NEFORCE_DEBUG_VERIFY(str_ == rhs.str_, "Attempting to equal to a different container");
134 return current_ == rhs.current_;
135 }
136
142 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool less_than(const basic_string_iterator& rhs) const noexcept {
143 NEFORCE_DEBUG_VERIFY(str_ == rhs.str_, "Attempting to less than a different container");
144 return current_ < rhs.current_;
145 }
146
151 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 pointer base() const noexcept { return current_; }
152
157 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const container_type* container() const noexcept { return str_; }
158};
159
160
171template <typename CharT, typename Traits = char_traits<CharT>, typename Alloc = allocator<CharT>>
172class basic_string : public icommon<basic_string<CharT, Traits, Alloc>> {
173 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
174 static_assert(is_same_v<CharT, typename Alloc::value_type>, "allocator type mismatch.");
175 static_assert(is_same_v<CharT, typename Traits::char_type>, "trait type mismatch.");
177 "basic string only contains non-array trivial standard-layout types.");
178
179public:
180 using value_type = CharT;
181 using pointer = CharT*;
182 using reference = CharT&;
183 using const_pointer = const CharT*;
184 using const_reference = const CharT&;
191
192 using traits_type = Traits;
194 using allocator_type = Alloc;
195
197 static constexpr size_type npos = string_view::npos;
198
199private:
200#ifdef NEFORCE_USING_SSO
202 static constexpr size_type sso_buffer_bytes = MEMORY_ALIGN_THRESHHOLD;
204 static constexpr size_type sso_buffer_size = (sso_buffer_bytes + sizeof(CharT) - 1) / sizeof(CharT);
206 static constexpr size_type sso_capacity = sso_buffer_size - 1;
208 static constexpr size_type long_flag = static_cast<size_type>(1) << (sizeof(size_type) * 8 - 1);
209
213 union storage {
214 struct long_pointer {
215 pointer ptr;
216 size_type cap;
217 } long_;
218 CharT short_[sso_buffer_size];
219 } storage_;
220#else
221 pointer data_ = nullptr;
222 size_type size_ = 0;
224 compressed_pair<allocator_type, size_type> capacity_pair_{default_construct_tag{}, 0};
225#endif
226
227private:
228#ifdef NEFORCE_USING_SSO
233 NEFORCE_CONSTEXPR20 bool is_long() const noexcept { return (size_pair_.value & long_flag) != 0; }
234
239 NEFORCE_CONSTEXPR20 void set_size(size_type new_size) noexcept {
240 size_pair_.value = (is_long() ? (new_size | long_flag) : new_size);
241 }
242
247 NEFORCE_CONSTEXPR20 void switch_to_long(size_type new_cap) {
248 NEFORCE_DEBUG_VERIFY(new_cap >= sso_buffer_size, "switch_to_long: new_cap too small");
249 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
250 const size_type old_size = size();
251 traits_type::copy(new_ptr, storage_.short_, old_size);
252 traits_type::assign(new_ptr + old_size, 1, value_type());
253
254 storage_.long_.ptr = new_ptr;
255 storage_.long_.cap = new_cap;
256 size_pair_.value = old_size | long_flag;
257 }
258
262 NEFORCE_CONSTEXPR20 void destroy_long() noexcept {
263 if (storage_.long_.ptr) {
264 size_pair_.get_base().deallocate(storage_.long_.ptr, storage_.long_.cap);
265 storage_.long_.ptr = nullptr;
266 storage_.long_.cap = 0;
267 }
268 }
269#endif
270
277 template <typename Iterator>
278 NEFORCE_CONSTEXPR20 void construct_from_iter(Iterator first, Iterator last) {
279 const size_type n = _NEFORCE distance(first, last);
280
281#ifdef NEFORCE_USING_SSO
282 if (n < sso_capacity) {
283 pointer dest = storage_.short_;
284 for (size_type i = 0; i < n; ++i) {
285 dest[i] = *first++;
286 }
287 traits_type::assign(dest + n, 1, value_type());
288 size_pair_.value = n;
289 } else {
290 const size_type init_cap = _NEFORCE max(sso_buffer_size, n + 1);
291 pointer new_ptr = size_pair_.get_base().allocate(init_cap);
292 pointer dest = new_ptr;
293 for (size_type i = 0; i < n; ++i) {
294 *dest++ = *first++;
295 }
296 traits_type::assign(new_ptr + n, 1, value_type());
297
298 storage_.long_.ptr = new_ptr;
299 storage_.long_.cap = init_cap;
300 size_pair_.value = n | long_flag;
301 }
302#else
303 const size_type init_size = _NEFORCE max(MEMORY_ALIGN_THRESHHOLD, n + 1);
304 pointer temp_data = nullptr;
305 try {
306 temp_data = capacity_pair_.get_base().allocate(init_size);
307 size_ = n;
308 capacity_pair_.value = init_size;
309 _NEFORCE uninitialized_copy(first, last, temp_data);
310
311 data_ = temp_data;
312 size_ = n;
313 capacity_pair_.value = init_size;
314 traits_type::assign(data_ + size_, 1, value_type());
315 } catch (...) {
316 if (temp_data) {
317 _NEFORCE destroy(temp_data, temp_data + n);
318 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
319 }
320 destroy_buffer();
321 throw;
322 }
323#endif
324 }
325
332 NEFORCE_CONSTEXPR20 void construct_from_ptr(const_pointer str, size_type position, size_type n) {
333#ifdef NEFORCE_USING_SSO
334 if (n < sso_capacity) {
335 traits_type::copy(storage_.short_, str + position, n);
336 traits_type::assign(storage_.short_ + n, 1, value_type());
337 size_pair_.value = n;
338 } else {
339 const size_type init_cap = _NEFORCE max(sso_buffer_size, n + 1);
340 pointer new_ptr = size_pair_.get_base().allocate(init_cap);
341 traits_type::copy(new_ptr, str + position, n);
342 traits_type::assign(new_ptr + n, 1, value_type());
343
344 storage_.long_.ptr = new_ptr;
345 storage_.long_.cap = init_cap;
346 size_pair_.value = n | long_flag;
347 }
348#else
349 pointer temp_data = nullptr;
350 size_type temp_capacity = 0;
351 try {
352 temp_capacity = _NEFORCE max(MEMORY_ALIGN_THRESHHOLD, n + 1);
353 temp_data = capacity_pair_.get_base().allocate(temp_capacity);
354 traits_type::copy(temp_data, str + position, n);
355
356 data_ = temp_data;
357 size_ = n;
358 capacity_pair_.value = temp_capacity;
359 traits_type::assign(data_ + size_, 1, value_type());
360 } catch (...) {
361 if (temp_data) {
362 capacity_pair_.get_base().deallocate(temp_data, capacity_pair_.value);
363 }
364 data_ = nullptr;
365 size_ = 0;
366 capacity_pair_.value = 0;
367 throw;
368 }
369#endif
370 }
371
375 NEFORCE_CONSTEXPR20 void destroy_buffer() noexcept {
376#ifdef NEFORCE_USING_SSO
377 if (is_long()) {
378 destroy_long();
379 }
380 size_pair_.value = 0;
381 traits_type::assign(storage_.short_, 1, value_type());
382#else
383 if (data_) {
384 if (capacity_pair_.value > 0) {
385 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
386 }
387 data_ = nullptr;
388 }
389 capacity_pair_.value = 0;
390 size_ = 0;
391#endif
392 }
393
402 NEFORCE_CONSTEXPR20 basic_string& replace_fill(iterator first, size_type n1, const size_type n2,
403 const value_type value) {
404#ifdef NEFORCE_USING_SSO
405 const difference_type offset = first - begin();
406 const size_type old_size = size();
407 const size_type actual_n1 = _NEFORCE min(n1, old_size - offset);
408 if (actual_n1 == 0 && n2 == 0) {
409 return *this;
410 }
411
412 const size_type new_size = old_size - actual_n1 + n2;
413
414 if (!is_long() && new_size < sso_capacity) {
415 pointer p = storage_.short_ + offset;
416 if (static_cast<difference_type>(old_size - offset - actual_n1) > 0) {
417 traits_type::move(p + n2, p + actual_n1, old_size - offset - actual_n1);
418 }
419 traits_type::assign(p, n2, value);
420 size_pair_.value = new_size;
421 traits_type::assign(storage_.short_ + new_size, 1, value_type());
422 return *this;
423 }
424
425 size_type new_cap = is_long() ? storage_.long_.cap : sso_buffer_size;
426 if (new_cap < new_size + 1) {
427 new_cap = _NEFORCE max(new_size + 1, new_cap + (new_cap >> 1));
428 }
429
430 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
431 pointer dest = new_ptr;
432
433 dest = traits_type::copy(dest, data(), offset) + offset;
434 dest = traits_type::assign(dest, n2, value) + n2;
435 traits_type::copy(dest, data() + offset + actual_n1, old_size - offset - actual_n1);
436
437 if (is_long()) {
438 destroy_long();
439 }
440 storage_.long_.ptr = new_ptr;
441 storage_.long_.cap = new_cap;
442 size_pair_.value = new_size | long_flag;
443 traits_type::assign(storage_.long_.ptr + new_size, 1, value_type());
444
445 return *this;
446#else
447 if (static_cast<size_type>(end() - first) < n1) {
448 n1 = cend() - first;
449 }
450
451 if (n1 < n2) {
452 const size_type diff = n2 - n1;
453 NEFORCE_DEBUG_VERIFY(size_ + diff < max_size(), "basic_string index out of range.");
454 if (size_ > capacity_pair_.value - diff) {
455 reallocate(diff);
456 }
457
458 pointer raw_ptr = &*first;
459 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
460 traits_type::assign(raw_ptr, n2, value);
461 size_ += diff;
462 } else {
463 pointer raw_ptr = &*first;
464 traits_type::move(raw_ptr + n2, raw_ptr + n1, end() - (first + n1));
465 traits_type::assign(raw_ptr, n2, value);
466 size_ -= n1 - n2;
467 }
468
469 traits_type::assign(data_ + size_, 1, value_type());
470 return *this;
471#endif
472 }
473
483 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
484 NEFORCE_CONSTEXPR20 basic_string& replace_copy(iterator first1, iterator last1, Iterator first2, Iterator last2) {
485 static_assert(is_iter_v<Iterator> && is_same_v<iter_value_t<Iterator>, value_type>, "Iterator type mismatch.");
486
487 size_type len1 = _NEFORCE distance(first1, last1);
488 size_type len2 = _NEFORCE distance(first2, last2);
489
490#ifdef NEFORCE_USING_SSO
491 const difference_type offset = first1 - begin();
492 const size_type old_size = size();
493 const size_type new_size = old_size - len1 + len2;
494
495 if (!is_long() && new_size < sso_capacity) {
496 pointer p = storage_.short_ + offset;
497 if (static_cast<difference_type>(old_size - offset - len1) > 0) {
498 traits_type::move(p + len2, p + len1, old_size - offset - len1);
499 }
500 for (size_type i = 0; i < len2; ++i) {
501 p[i] = *first2++;
502 }
503 size_pair_.value = new_size;
504 traits_type::assign(storage_.short_ + new_size, 1, value_type());
505 return *this;
506 }
507
508 size_type new_cap = is_long() ? storage_.long_.cap : sso_buffer_size;
509 if (new_cap < new_size + 1) {
510 new_cap = _NEFORCE max(new_size + 1, new_cap + (new_cap >> 1));
511 }
512
513 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
514 pointer dest = new_ptr;
515
516 dest = traits_type::copy(dest, data(), offset) + offset;
517 dest = _NEFORCE uninitialized_copy(first2, last2, dest);
518 traits_type::copy(dest, data() + offset + len1, old_size - offset - len1);
519
520 if (is_long()) {
521 destroy_long();
522 }
523 storage_.long_.ptr = new_ptr;
524 storage_.long_.cap = new_cap;
525 size_pair_.value = new_size | long_flag;
526 traits_type::assign(storage_.long_.ptr + new_size, 1, value_type());
527
528 return *this;
529#else
530 if (len1 < len2) {
531 const size_type diff = len2 - len1;
532 NEFORCE_DEBUG_VERIFY(size_ + diff < max_size(), "basic_string replace_copy index out of range.");
533 if (size_ > capacity_pair_.value - diff) {
534 reallocate(diff);
535 }
536
537 pointer raw_ptr = &*first1;
538 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
539 traits_type::copy(raw_ptr, &*first2, len2);
540 size_ += diff;
541 } else {
542 pointer raw_ptr = &*first1;
543 traits_type::move(raw_ptr + len2, raw_ptr + len1, end() - (first1 + len1));
544 traits_type::copy(raw_ptr, &*first2, len2);
545 size_ -= len1 - len2;
546 }
547
548 traits_type::assign(data_ + size_, 1, value_type());
549 return *this;
550#endif
551 }
552
562 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
563 NEFORCE_CONSTEXPR20 basic_string& replace_copy(iterator first1, const size_type n1, Iterator first2,
564 const size_type n2) {
565 return replace_copy(first1, first1 + n1, first2, _NEFORCE next(first2, n2));
566 }
567
572 NEFORCE_CONSTEXPR20 void reallocate(size_type n) {
573#ifdef NEFORCE_USING_SSO
574 if (!is_long()) {
575 const size_type new_cap = _NEFORCE max(sso_buffer_size, size() + n + 1);
576 switch_to_long(new_cap);
577 return;
578 }
579
580 const size_type old_cap = storage_.long_.cap;
581 const size_type min_new_cap = size() + n + 1;
582 const size_type new_cap = _NEFORCE max(min_new_cap, old_cap + (old_cap >> 1));
583
584 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
585 traits_type::move(new_ptr, storage_.long_.ptr, size());
586 traits_type::assign(new_ptr + size(), 1, value_type());
587
588 destroy_long();
589 storage_.long_.ptr = new_ptr;
590 storage_.long_.cap = new_cap;
591#else
592 pointer new_buffer = nullptr;
593 try {
594 const size_t new_cap =
595 _NEFORCE max(capacity_pair_.value + n, capacity_pair_.value + (capacity_pair_.value >> 1)) + 1;
596 new_buffer = capacity_pair_.get_base().allocate(new_cap);
597 traits_type::move(new_buffer, data_, size_);
598
599 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
600 data_ = new_buffer;
601 capacity_pair_.value = new_cap;
602 traits_type::assign(data_ + size_, 1, value_type());
603 } catch (...) {
604 if (new_buffer) {
605 capacity_pair_.get_base().deallocate(new_buffer, capacity_pair_.value);
606 }
607 throw;
608 }
609#endif
610 }
611
619 NEFORCE_CONSTEXPR20 iterator reallocate_fill(iterator position, size_type n, value_type value) {
620#ifdef NEFORCE_USING_SSO
621 const size_type offset = position - begin();
622 if (!is_long() && size() + n < sso_buffer_size) {
623 pointer p = storage_.short_ + offset;
624 traits_type::move(p + n, p, size() - offset);
625 traits_type::assign(p, n, value);
626 size_pair_.value = (size() + n);
627 traits_type::assign(storage_.short_ + size(), 1, value_type());
628 return iterator(storage_.short_ + offset, this);
629 }
630
631 const size_type old_size = size();
632 const size_type new_cap = _NEFORCE max((is_long() ? storage_.long_.cap : sso_buffer_size) + n,
633 (is_long() ? storage_.long_.cap : sso_buffer_size) +
634 ((is_long() ? storage_.long_.cap : sso_buffer_size) >> 1)) +
635 1;
636
637 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
638 pointer dest = new_ptr;
639
640 dest = traits_type::copy(dest, data(), offset) + offset;
641 dest = traits_type::assign(dest, n, value) + n;
642 traits_type::copy(dest, data() + offset, old_size - offset);
643
644 if (is_long()) {
645 destroy_long();
646 }
647 storage_.long_.ptr = new_ptr;
648 storage_.long_.cap = new_cap;
649 size_pair_.value = (old_size + n) | long_flag;
650 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
651
652 return iterator(storage_.long_.ptr + offset, this);
653#else
654 const difference_type diff = (&*position) - data_;
655 const size_t old_cap = capacity_pair_.value;
656 const size_t new_cap = _NEFORCE max(old_cap + n, old_cap + (old_cap >> 1));
657 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
658 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
659 pointer end2 = traits_type::assign(end1, n, value) + n;
660 traits_type::move(end2, data_ + diff, size_ - diff);
661 capacity_pair_.get_base().deallocate(data_, old_cap);
662 data_ = new_buffer;
663 size_ += n;
664 capacity_pair_.value = new_cap;
665 traits_type::assign(data_ + size_, 1, value_type());
666 return iterator(data_ + diff, this);
667#endif
668 }
669
678 template <typename Iterator>
679 NEFORCE_CONSTEXPR20 iterator reallocate_copy(iterator position, Iterator first, Iterator last) {
680#ifdef NEFORCE_USING_SSO
681 const size_type offset = position - begin();
682 const size_type n = _NEFORCE distance(first, last);
683 const size_type old_size = size();
684
685 if (!is_long() && old_size + n < sso_buffer_size) {
686 pointer p = storage_.short_ + offset;
687 traits_type::move(p + n, p, old_size - offset);
688 for (size_type i = 0; i < n; ++i) {
689 p[i] = *first++;
690 }
691 size_pair_.value = old_size + n;
692 traits_type::assign(storage_.short_ + size(), 1, value_type());
693 return iterator(storage_.short_ + offset, this);
694 }
695
696 const size_type new_cap = _NEFORCE max((is_long() ? storage_.long_.cap : sso_buffer_size) + n,
697 (is_long() ? storage_.long_.cap : sso_buffer_size) +
698 ((is_long() ? storage_.long_.cap : sso_buffer_size) >> 1)) +
699 1;
700
701 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
702 pointer dest = new_ptr;
703
704 dest = traits_type::copy(dest, data(), offset) + offset;
705 dest = _NEFORCE uninitialized_copy(first, last, dest);
706 traits_type::copy(dest, data() + offset, old_size - offset);
707
708 if (is_long()) {
709 destroy_long();
710 }
711 storage_.long_.ptr = new_ptr;
712 storage_.long_.cap = new_cap;
713 size_pair_.value = (old_size + n) | long_flag;
714 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
715
716 return iterator(storage_.long_.ptr + offset, this);
717#else
718 const difference_type diff = position - begin();
719 const size_type old_cap = capacity_pair_.value;
720 const size_type n = _NEFORCE distance(first, last);
721 const size_t new_cap = _NEFORCE max(old_cap + n, old_cap + (old_cap >> 1));
722 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
723 pointer end1 = traits_type::move(new_buffer, data_, diff) + diff;
724 pointer end2 = _NEFORCE uninitialized_copy_n(first, n, end1).second + n;
725 traits_type::move(end2, data_ + diff, size_ - diff);
726 capacity_pair_.get_base().deallocate(data_, old_cap);
727 data_ = new_buffer;
728 size_ += n;
729 capacity_pair_.value = new_cap;
730 traits_type::assign(data_ + size_, 1, value_type());
731 return iterator(data_ + diff, this);
732#endif
733 }
734
735public:
741 NEFORCE_CONSTEXPR20 basic_string() {
742#ifdef NEFORCE_USING_SSO
743 traits_type::assign(storage_.short_, 1, value_type());
744 size_pair_.value = 0;
745#else
746 basic_string::reserve(MEMORY_ALIGN_THRESHHOLD);
747#endif
748 }
749
754 NEFORCE_CONSTEXPR20 explicit basic_string(size_type n) :
755 basic_string(n, static_cast<value_type>(0)) {}
756
762 NEFORCE_CONSTEXPR20 explicit basic_string(size_type n, int32_t value) :
763 basic_string(n, static_cast<value_type>(value)) {}
764
770 NEFORCE_CONSTEXPR20 explicit basic_string(size_type n, int64_t value) :
771 basic_string(n, static_cast<value_type>(value)) {}
772
778 NEFORCE_CONSTEXPR20 explicit basic_string(size_type n, value_type value) {
779#ifdef NEFORCE_USING_SSO
780 if (n < sso_capacity) {
781 traits_type::assign(storage_.short_, n, value);
782 traits_type::assign(storage_.short_ + n, 1, value_type());
783 size_pair_.value = n;
784 } else {
785 const size_type init_cap = _NEFORCE max(sso_buffer_size, n + 1);
786 pointer new_ptr = size_pair_.get_base().allocate(init_cap);
787 traits_type::assign(new_ptr, n, value);
788 traits_type::assign(new_ptr + n, 1, value_type());
789
790 storage_.long_.ptr = new_ptr;
791 storage_.long_.cap = init_cap;
792 size_pair_.value = n | long_flag;
793 }
794#else
795 const size_type init_size = _NEFORCE max(MEMORY_ALIGN_THRESHHOLD, n + 1);
796 data_ = capacity_pair_.get_base().allocate(init_size);
797 traits_type::assign(data_, n, value);
798 size_ = n;
799 capacity_pair_.value = init_size;
800 traits_type::assign(data_ + size_, 1, value_type());
801#endif
802 }
803
808 NEFORCE_CONSTEXPR20 basic_string(const basic_string& other) {
809#ifdef NEFORCE_USING_SSO
810 const size_type len = other.size();
811 if (len < sso_capacity) {
812 traits_type::copy(storage_.short_, other.data(), len);
813 traits_type::assign(storage_.short_ + len, 1, value_type());
814 size_pair_.value = len;
815 } else {
816 const size_type cap = other.is_long() ? other.storage_.long_.cap : (len + 1);
817 pointer new_ptr = size_pair_.get_base().allocate(cap);
818 traits_type::copy(new_ptr, other.data(), len);
819 traits_type::assign(new_ptr + len, 1, value_type());
820
821 storage_.long_.ptr = new_ptr;
822 storage_.long_.cap = cap;
823 size_pair_.value = len | long_flag;
824 }
825#else
826 construct_from_ptr(other.data(), 0, other.size());
827#endif
828 }
829
835 NEFORCE_CONSTEXPR20 basic_string& operator=(const basic_string& other) {
836 if (_NEFORCE addressof(other) == this) {
837 return *this;
838 }
839
840#ifdef NEFORCE_USING_SSO
841 const size_type len = other.size();
842
843 if (len < sso_capacity) {
844 if (is_long()) {
845 destroy_long();
846 }
847 traits_type::copy(storage_.short_, other.data(), len);
848 traits_type::assign(storage_.short_ + len, 1, value_type());
849 size_pair_.value = len;
850 } else {
851 if (is_long()) {
852 if (storage_.long_.cap >= len + 1) {
853 traits_type::copy(storage_.long_.ptr, other.data(), len);
854 traits_type::assign(storage_.long_.ptr + len, 1, value_type());
855 size_pair_.value = len | long_flag;
856 return *this;
857 }
858 destroy_long();
859 }
860
861 const size_type cap = other.is_long() ? other.storage_.long_.cap : (len + 1);
862 pointer new_ptr = size_pair_.get_base().allocate(cap);
863 traits_type::copy(new_ptr, other.data(), len);
864 traits_type::assign(new_ptr + len, 1, value_type());
865
866 storage_.long_.ptr = new_ptr;
867 storage_.long_.cap = cap;
868 size_pair_.value = len | long_flag;
869 }
870#else
871 destroy_buffer();
872 construct_from_ptr(other.data(), 0, other.size());
873#endif
874 return *this;
875 }
876
881 NEFORCE_CONSTEXPR20 basic_string(basic_string&& other) noexcept
882#ifdef NEFORCE_USING_SSO
883 :
884 size_pair_(_NEFORCE move(other.size_pair_)) {
885 if (other.is_long()) {
886 storage_.long_.ptr = other.storage_.long_.ptr;
887 storage_.long_.cap = other.storage_.long_.cap;
888 size_pair_.value = other.size_pair_.value;
889
890 other.storage_.long_.ptr = nullptr;
891 other.storage_.long_.cap = 0;
892 other.size_pair_.value = 0;
893 } else {
894 traits_type::copy(storage_.short_, other.storage_.short_, other.size() + 1);
895 size_pair_.value = other.size();
896 traits_type::assign(other.storage_.short_, 1, value_type());
897 other.size_pair_.value = 0;
898 }
899#else
900 :
901 data_(other.data_),
902 size_(other.size_),
903 capacity_pair_(_NEFORCE move(other.capacity_pair_)) {
904 other.data_ = nullptr;
905 other.size_ = 0;
906 other.capacity_pair_.value = 0;
907#endif
908 }
909
915 NEFORCE_CONSTEXPR20 basic_string& operator=(basic_string&& other) noexcept {
916 if (_NEFORCE addressof(other) == this) {
917 return *this;
918 }
919
920#ifdef NEFORCE_USING_SSO
921 destroy_buffer();
922
923 size_pair_ = _NEFORCE move(other.size_pair_);
924
925 if (other.is_long()) {
926 storage_.long_.ptr = other.storage_.long_.ptr;
927 storage_.long_.cap = other.storage_.long_.cap;
928 size_pair_.value = other.size_pair_.value;
929
930 other.storage_.long_.ptr = nullptr;
931 other.storage_.long_.cap = 0;
932 other.size_pair_.value = 0;
933 } else {
934 traits_type::copy(storage_.short_, other.storage_.short_, other.size() + 1);
935 size_pair_.value = other.size();
936 traits_type::assign(other.storage_.short_, 1, value_type());
937 other.size_pair_.value = 0;
938 }
939#else
940 pointer new_data = other.data_;
941 const size_type new_size = other.size_;
942 auto new_capacity_pair = _NEFORCE move(other.capacity_pair_);
943
944 other.data_ = nullptr;
945 other.size_ = 0;
946 other.capacity_pair_.value = 0;
947
948 destroy_buffer();
949 data_ = new_data;
950 size_ = new_size;
951 capacity_pair_ = _NEFORCE move(new_capacity_pair);
952#endif
953
954 return *this;
955 }
956
961 NEFORCE_CONSTEXPR20 basic_string(view_type view) { construct_from_ptr(view.data(), 0, view.size()); }
962
968 NEFORCE_CONSTEXPR20 basic_string(view_type view, const size_type n) { construct_from_ptr(view.data(), 0, n); }
969
975 NEFORCE_CONSTEXPR20 basic_string& operator=(view_type view) {
976 const size_type len = view.size();
977
978#ifdef NEFORCE_USING_SSO
979 if (len < sso_capacity) {
980 if (is_long()) {
981 destroy_long();
982 }
983 traits_type::copy(storage_.short_, view.data(), len);
984 traits_type::assign(storage_.short_ + len, 1, value_type());
985 size_pair_.value = len;
986 } else {
987 if (is_long() && storage_.long_.cap >= len + 1) {
988 traits_type::copy(storage_.long_.ptr, view.data(), len);
989 traits_type::assign(storage_.long_.ptr + len, 1, value_type());
990 size_pair_.value = len | long_flag;
991 return *this;
992 }
993
994 if (is_long()) {
995 destroy_long();
996 }
997 const size_type new_cap = len + 1;
998 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
999 traits_type::copy(new_ptr, view.data(), len);
1000 traits_type::assign(new_ptr + len, 1, value_type());
1001
1002 storage_.long_.ptr = new_ptr;
1003 storage_.long_.cap = new_cap;
1004 size_pair_.value = len | long_flag;
1005 }
1006#else
1007 if (capacity_pair_.value < len) {
1008 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
1009 capacity_pair_.get_base().deallocate(data_);
1010 data_ = new_buffer;
1011 capacity_pair_.value = len + 1;
1012 }
1013
1014 traits_type::copy(data_, view.data(), len);
1015 size_ = len;
1016 traits_type::assign(data_ + size_, 1, value_type());
1017#endif
1018 return *this;
1019 }
1020
1026 NEFORCE_CONSTEXPR20 basic_string(const basic_string& other, size_type position) {
1027 NEFORCE_DEBUG_VERIFY(position <= other.size(), "basic_string index out of range");
1028 construct_from_ptr(other.data(), position, other.size() - position);
1029 }
1030
1037 NEFORCE_CONSTEXPR20 basic_string(const basic_string& other, size_type position, size_type n) {
1038 NEFORCE_DEBUG_VERIFY(position <= other.size(), "basic_string index out of range");
1039 n = _NEFORCE min(n, other.size() - position);
1040 construct_from_ptr(other.data(), position, n);
1041 }
1042
1047 NEFORCE_CONSTEXPR20 basic_string(const_pointer str) { construct_from_ptr(str, 0, traits_type::length(str)); }
1048
1054 NEFORCE_CONSTEXPR20 basic_string(const_pointer str, const size_type n) { construct_from_ptr(str, 0, n); }
1055
1061 NEFORCE_CONSTEXPR20 basic_string& operator=(const_pointer str) {
1062 const size_type len = traits_type::length(str);
1063#ifdef NEFORCE_USING_SSO
1064 if (len < sso_capacity) {
1065 if (is_long()) {
1066 destroy_long();
1067 }
1068 traits_type::copy(storage_.short_, str, len);
1069 traits_type::assign(storage_.short_ + len, 1, value_type());
1070 size_pair_.value = len;
1071 } else {
1072 if (is_long() && storage_.long_.cap >= len + 1) {
1073 traits_type::copy(storage_.long_.ptr, str, len);
1074 traits_type::assign(storage_.long_.ptr + len, 1, value_type());
1075 size_pair_.value = len | long_flag;
1076 return *this;
1077 }
1078
1079 if (is_long()) {
1080 destroy_long();
1081 }
1082 const size_type new_cap = len + 1;
1083 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
1084 traits_type::copy(new_ptr, str, len);
1085 traits_type::assign(new_ptr + len, 1, value_type());
1086
1087 storage_.long_.ptr = new_ptr;
1088 storage_.long_.cap = new_cap;
1089 size_pair_.value = len | long_flag;
1090 }
1091#else
1092 if (capacity_pair_.value < len) {
1093 pointer new_buffer = capacity_pair_.get_base().allocate(len + 1);
1094 capacity_pair_.get_base().deallocate(data_);
1095 data_ = new_buffer;
1096 capacity_pair_.value = len + 1;
1097 }
1098 traits_type::copy(data_, str, len);
1099 size_ = len;
1100 traits_type::assign(data_ + size_, 1, value_type());
1101#endif
1102 return *this;
1103 }
1104
1111 template <typename Iterator, enable_if_t<!is_convertible_v<Iterator, value_type>, int> = 0>
1112 NEFORCE_CONSTEXPR20 basic_string(Iterator first, Iterator last) {
1113 construct_from_iter(first, last);
1114 }
1115
1120 NEFORCE_CONSTEXPR20 basic_string(std::initializer_list<value_type> ilist) :
1121 basic_string(ilist.begin(), ilist.end()) {}
1122
1128 NEFORCE_CONSTEXPR20 basic_string& operator=(std::initializer_list<value_type> ilist) {
1129 clear();
1130 insert(begin(), ilist.begin(), ilist.end());
1131 return *this;
1132 }
1133
1137 NEFORCE_CONSTEXPR20 ~basic_string() { destroy_buffer(); }
1138
1143 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 iterator begin() noexcept { return {data(), this}; }
1144
1149 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 iterator end() noexcept { return {data() + size(), this}; }
1150
1155 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator begin() const noexcept { return cbegin(); }
1156
1161 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator end() const noexcept { return cend(); }
1162
1167 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator cbegin() const noexcept { return {data(), this}; }
1168
1173 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator cend() const noexcept { return {data() + size(), this}; }
1174
1179 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
1180
1185 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
1186
1191 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { return crbegin(); }
1192
1197 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator rend() const noexcept { return crend(); }
1198
1203 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator crbegin() const noexcept {
1204 return const_reverse_iterator(cend());
1205 }
1206
1211 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator crend() const noexcept {
1213 }
1214
1219 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type size() const noexcept {
1220#ifdef NEFORCE_USING_SSO
1221 return size_pair_.value & ~long_flag;
1222#else
1223 return size_;
1224#endif
1225 }
1226
1231 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type max_size() const noexcept { return npos; }
1232
1237 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type capacity() const noexcept {
1238#ifdef NEFORCE_USING_SSO
1239 return is_long() ? storage_.long_.cap : sso_buffer_size;
1240#else
1241 return capacity_pair_.value;
1242#endif
1243 }
1244
1249 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type length() const noexcept { return size(); }
1250
1255 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool empty() const noexcept { return size() == 0; }
1256
1261 NEFORCE_CONSTEXPR20 void reserve(const size_type n) {
1262 NEFORCE_DEBUG_VERIFY(n < max_size(), "basic_string reserve index out of range.");
1263 const size_type new_cap = n + 1;
1264 if (new_cap <= capacity()) {
1265 return;
1266 }
1267
1268#ifdef NEFORCE_USING_SSO
1269 if (!is_long()) {
1270 switch_to_long(new_cap);
1271 } else {
1272 pointer new_ptr = size_pair_.get_base().allocate(new_cap);
1273 traits_type::move(new_ptr, storage_.long_.ptr, size());
1274 traits_type::assign(new_ptr + size(), 1, value_type());
1275 destroy_long();
1276 storage_.long_.ptr = new_ptr;
1277 storage_.long_.cap = new_cap;
1278 }
1279#else
1280 pointer new_buffer = capacity_pair_.get_base().allocate(new_cap);
1281 traits_type::move(new_buffer, data_, size_);
1282 capacity_pair_.get_base().deallocate(data_, capacity_pair_.value);
1283
1284 data_ = new_buffer;
1285 capacity_pair_.value = new_cap;
1286 traits_type::assign(data_ + size_, 1, value_type());
1287#endif
1288 }
1289
1295 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference operator[](const size_type n) noexcept {
1296 NEFORCE_DEBUG_VERIFY(n <= size(), "basic_string [] index out of range.");
1297 return *(data() + n);
1298 }
1299
1305 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference operator[](const size_type n) const noexcept {
1306 NEFORCE_DEBUG_VERIFY(n <= size(), "basic_string [] index out of range.");
1307 return *(data() + n);
1308 }
1309
1315 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference at(const size_type n) noexcept { return (*this)[n]; }
1316
1322 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference at(const size_type n) const noexcept { return (*this)[n]; }
1323
1328 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference front() noexcept {
1329 NEFORCE_DEBUG_VERIFY(!empty(), "front called on empty basic_string");
1330 return *data();
1331 }
1332
1337 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference front() const noexcept {
1338 NEFORCE_DEBUG_VERIFY(!empty(), "front called on empty basic_string");
1339 return *data();
1340 }
1341
1346 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference back() noexcept {
1347 NEFORCE_DEBUG_VERIFY(!empty(), "back called on empty basic_string");
1348 return *(data() + size() - 1);
1349 }
1350
1355 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference back() const noexcept {
1356 NEFORCE_DEBUG_VERIFY(!empty(), "back called on empty basic_string");
1357 return *(data() + size() - 1);
1358 }
1359
1364 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 pointer data() noexcept {
1365#ifdef NEFORCE_USING_SSO
1366 if (!is_long()) {
1367 return storage_.short_;
1368 }
1369 return storage_.long_.ptr;
1370#else
1371 return data_;
1372#endif
1373 }
1374
1379 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_pointer data() const noexcept {
1380#ifdef NEFORCE_USING_SSO
1381 if (!is_long()) {
1382 return storage_.short_;
1383 }
1384 return storage_.long_.ptr;
1385#else
1386 return data_;
1387#endif
1388 }
1389
1396 NEFORCE_CONSTEXPR20 iterator insert(iterator position, value_type value) {
1397#ifdef NEFORCE_USING_SSO
1398 const size_type offset = position - begin();
1399 if (!is_long() && size() + 1 < sso_buffer_size) {
1400 pointer p = storage_.short_ + offset;
1401 traits_type::move(p + 1, p, size() - offset);
1402 *p = value;
1403 ++size_pair_.value;
1404 traits_type::assign(storage_.short_ + size(), 1, value_type());
1405 return iterator(p, this);
1406 }
1407 return basic_string::reallocate_fill(position, 1, value);
1408#else
1409 if (size_ == capacity_pair_.value) {
1410 return basic_string::reallocate_fill(position, 1, value);
1411 }
1412
1413 size_type offset = position - begin();
1414 pointer p = data_ + offset;
1415 size_type chars_after = size_ - offset;
1416 if (chars_after > 0) {
1417 traits_type::move(p + 1, p, chars_after);
1418 }
1419
1420 *p = value;
1421 ++size_;
1422 traits_type::assign(data_ + size_, 1, value_type());
1423 return iterator(p, this);
1424#endif
1425 }
1426
1434 NEFORCE_CONSTEXPR20 basic_string& insert(size_type position, size_type n, value_type value) {
1435 insert(begin() + position, n, value);
1436 return *this;
1437 }
1438
1439 NEFORCE_CONSTEXPR20 iterator insert(iterator position, size_type n, value_type value) {
1440 if (n == 0) {
1441 return position;
1442 }
1443
1444#ifdef NEFORCE_USING_SSO
1445 if (!is_long() && size() + n < sso_buffer_size) {
1446 const size_type offset = position - begin();
1447 pointer p = storage_.short_ + offset;
1448 traits_type::move(p + n, p, size() - offset);
1449 traits_type::assign(p, n, value);
1450 size_pair_.value = size() + n;
1451 traits_type::assign(storage_.short_ + size(), 1, value_type());
1452 return iterator(p, this);
1453 }
1454
1455 return basic_string::reallocate_fill(position, n, value);
1456#else
1457 if (capacity_pair_.value - size_ < n) {
1458 return basic_string::reallocate_fill(position, n, value);
1459 }
1460
1461 const size_type offset = position - begin();
1462 pointer p = data_ + offset;
1463 const size_type chars_after = size_ - offset;
1464
1465 if (chars_after > 0) {
1466 traits_type::move(p + n, p, chars_after);
1467 }
1468 traits_type::assign(p, n, value);
1469
1470 size_ += n;
1471 traits_type::assign(data_ + size_, 1, value_type());
1472 return iterator(p, this);
1473#endif
1474 }
1475
1484 template <typename Iterator>
1485 NEFORCE_CONSTEXPR20 iterator insert(iterator position, Iterator first, Iterator last) {
1486 const size_type len = _NEFORCE distance(first, last);
1487 if (len == 0) {
1488 return position;
1489 }
1490
1491#ifdef NEFORCE_USING_SSO
1492 if (!is_long() && size() + len < sso_buffer_size) {
1493 const size_type offset = position - begin();
1494 pointer p = storage_.short_ + offset;
1495 traits_type::move(p + len, p, size() - offset);
1496 for (size_type i = 0; i < len; ++i) {
1497 p[i] = *first++;
1498 }
1499 size_pair_.value = size() + len;
1500 traits_type::assign(storage_.short_ + size(), 1, value_type());
1501 return iterator(p, this);
1502 }
1503 return basic_string::reallocate_copy(position, first, last);
1504#else
1505 if (capacity_pair_.value - size_ < len) {
1506 return basic_string::reallocate_copy(position, first, last);
1507 }
1508
1509 const size_type offset = position - begin();
1510 pointer p = data_ + offset;
1511 const size_type chars_after = size_ - offset;
1512
1513 if (chars_after > 0) {
1514 traits_type::move(p + len, p, chars_after);
1515 }
1516 pointer curr = p;
1517 for (Iterator it = first; it != last; ++it, ++curr) {
1518 *curr = *it;
1519 }
1520
1521 size_ += len;
1522 traits_type::assign(data_ + size_, 1, value_type());
1523 return position;
1524#endif
1525 }
1526
1531 NEFORCE_CONSTEXPR20 void push_back(value_type value) { append(1, value); }
1532
1536 NEFORCE_CONSTEXPR20 void pop_back() noexcept {
1537 NEFORCE_DEBUG_VERIFY(!empty(), "pop_back called on empty basic_string");
1538#ifdef NEFORCE_USING_SSO
1539 const size_type new_size = size() - 1;
1540 if (is_long()) {
1541 size_pair_.value = new_size | long_flag;
1542 traits_type::assign(storage_.long_.ptr + new_size, 1, value_type());
1543 } else {
1544 size_pair_.value = new_size;
1545 traits_type::assign(storage_.short_ + new_size, 1, value_type());
1546 }
1547#else
1548 --size_;
1549 traits_type::assign(data_ + size_, 1, value_type());
1550#endif
1551 }
1552
1559 NEFORCE_CONSTEXPR20 basic_string& append(size_type n, value_type value) {
1560 NEFORCE_DEBUG_VERIFY(size() + n < max_size(), "basic_string append iterator out of ranges.");
1561 if (n == 0) {
1562 return *this;
1563 }
1564
1565#ifdef NEFORCE_USING_SSO
1566 if (!is_long() && size() + n < sso_buffer_size) {
1567 pointer p = storage_.short_ + size();
1568 traits_type::assign(p, n, value);
1569 size_pair_.value = size() + n;
1570 traits_type::assign(storage_.short_ + size(), 1, value_type());
1571 return *this;
1572 }
1573
1574 const size_type old_size = size();
1575 if (is_long() && storage_.long_.cap >= old_size + n + 1) {
1576 pointer p = storage_.long_.ptr + old_size;
1577 traits_type::assign(p, n, value);
1578 size_pair_.value = (old_size + n) | long_flag;
1579 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
1580 return *this;
1581 }
1582
1583 reallocate(n);
1584 pointer p = data() + old_size;
1585 traits_type::assign(p, n, value);
1586 size_pair_.value = (old_size + n) | (is_long() ? long_flag : 0);
1588#else
1589 if (capacity_pair_.value - size_ <= n) {
1590 reallocate(n);
1591 }
1592 traits_type::assign(data_ + size_, n, value);
1593 size_ += n;
1594 traits_type::assign(data_ + size_, 1, value_type());
1595#endif
1596 return *this;
1597 }
1598
1604 NEFORCE_CONSTEXPR20 basic_string& append(value_type value) { return append(1, value); }
1605
1613 NEFORCE_CONSTEXPR20 basic_string& append(const basic_string& other, size_type position, size_type n) {
1614 NEFORCE_DEBUG_VERIFY(size() + n < max_size(), "basic_string append iterator out of ranges.");
1615 if (n == 0) {
1616 return *this;
1617 }
1618 n = _NEFORCE min(n, other.size() - position);
1619 return basic_string::append(other.data() + position, n);
1620 }
1621
1627 NEFORCE_CONSTEXPR20 basic_string& append(const basic_string& other) { return append(other, 0, other.size()); }
1628
1635 NEFORCE_CONSTEXPR20 basic_string& append(const basic_string& other, size_type position) {
1636 return append(other, position, other.size() - position);
1637 }
1638
1646 NEFORCE_CONSTEXPR20 basic_string& append(basic_string&& other, size_type position, size_type n) {
1647 NEFORCE_DEBUG_VERIFY(size() + n < max_size(), "basic_string append iterator out of ranges.");
1648 if (n == 0) {
1649 return *this;
1650 }
1651 n = _NEFORCE min(n, other.size() - position);
1652 basic_string::append(other.data() + position, n);
1653 other.clear();
1654 return *this;
1655 }
1656
1662 NEFORCE_CONSTEXPR20 basic_string& append(basic_string&& other) {
1663 const size_type len = other.size();
1664 return basic_string::append(_NEFORCE move(other), 0, len);
1665 }
1666
1673 NEFORCE_CONSTEXPR20 basic_string& append(basic_string&& other, size_type position) {
1674 const size_type len = other.size();
1675 return basic_string::append(_NEFORCE move(other), position, len - position);
1676 }
1677
1684 NEFORCE_CONSTEXPR20 basic_string& append(view_type view, size_type n) { return append(view.data(), n); }
1685
1691 NEFORCE_CONSTEXPR20 basic_string& append(view_type view) { return append(view.data(), view.size()); }
1692
1699 NEFORCE_CONSTEXPR20 basic_string& append(const_pointer str, size_type n) {
1700 NEFORCE_DEBUG_VERIFY(size() + n < max_size(), "basic_string append iterator out of ranges.");
1701 if (n == 0) {
1702 return *this;
1703 }
1704
1705#ifdef NEFORCE_USING_SSO
1706 const size_type old_size = size();
1707 if (!is_long() && old_size + n < sso_buffer_size) {
1708 traits_type::copy(storage_.short_ + old_size, str, n);
1709 size_pair_.value = old_size + n;
1710 traits_type::assign(storage_.short_ + size(), 1, value_type());
1711 return *this;
1712 }
1713
1714 if (is_long() && storage_.long_.cap >= old_size + n + 1) {
1715 traits_type::copy(storage_.long_.ptr + old_size, str, n);
1716 size_pair_.value = (old_size + n) | long_flag;
1717 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
1718 return *this;
1719 }
1720
1721 reallocate(n);
1722 traits_type::copy(data() + old_size, str, n);
1723 size_pair_.value = (old_size + n) | long_flag;
1725#else
1726 if (capacity_pair_.value - size_ <= n) {
1727 reallocate(n);
1728 }
1729 traits_type::copy(data_ + size_, str, n);
1730 size_ += n;
1731 traits_type::assign(data_ + size_, 1, value_type());
1732#endif
1733 return *this;
1734 }
1735
1741 NEFORCE_CONSTEXPR20 basic_string& append(const_pointer str) { return append(str, traits_type::length(str)); }
1742
1750 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
1751 NEFORCE_CONSTEXPR20 basic_string& append(Iterator first, Iterator last) {
1752 const size_type n = _NEFORCE distance(first, last);
1753 NEFORCE_DEBUG_VERIFY(size() + n < max_size(), "basic_string append iterator out of ranges.");
1754 if (n == 0) {
1755 return *this;
1756 }
1757
1758#ifdef NEFORCE_USING_SSO
1759 const size_type old_size = size();
1760 if (!is_long() && old_size + n < sso_buffer_size) {
1761 pointer p = storage_.short_ + old_size;
1762 for (size_type i = 0; i < n; ++i) {
1763 p[i] = *first++;
1764 }
1765 size_pair_.value = old_size + n;
1766 traits_type::assign(storage_.short_ + size(), 1, value_type());
1767 return *this;
1768 }
1769
1770 if (is_long() && storage_.long_.cap >= old_size + n + 1) {
1771 pointer p = storage_.long_.ptr + old_size;
1772 for (size_type i = 0; i < n; ++i) {
1773 p[i] = *first++;
1774 }
1775 size_pair_.value = (old_size + n) | long_flag;
1776 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
1777 return *this;
1778 }
1779
1780 reallocate(n);
1781 pointer p = data() + old_size;
1782 for (size_type i = 0; i < n; ++i) {
1783 p[i] = *first++;
1784 }
1785 size_pair_.value = (old_size + n) | long_flag;
1787#else
1788 if (capacity_pair_.value - size_ <= n) {
1789 reallocate(n);
1790 }
1791 _NEFORCE uninitialized_copy_n(first, n, data_ + size_);
1792 size_ += n;
1793 traits_type::assign(data_ + size_, 1, value_type());
1794#endif
1795 return *this;
1796 }
1797
1803 NEFORCE_CONSTEXPR20 basic_string& append(std::initializer_list<value_type> ilist) {
1804 return append(ilist.begin(), ilist.end());
1805 }
1806
1808 NEFORCE_CONSTEXPR20 basic_string& operator+=(const basic_string& other) { return basic_string::append(other); }
1809
1811 NEFORCE_CONSTEXPR20 basic_string& operator+=(basic_string&& other) {
1812 return basic_string::append(_NEFORCE move(other));
1813 }
1814
1816 NEFORCE_CONSTEXPR20 basic_string& operator+=(const value_type value) { return basic_string::append(value); }
1817
1819 NEFORCE_CONSTEXPR20 basic_string& operator+=(const_pointer str) { return basic_string::append(str); }
1820
1822 NEFORCE_CONSTEXPR20 basic_string& operator+=(std::initializer_list<value_type> ilist) {
1823 return basic_string::append(ilist);
1824 }
1825
1828
1834 NEFORCE_CONSTEXPR20 basic_string& assign(const basic_string& other) { return *this = other; }
1835
1841 NEFORCE_CONSTEXPR20 basic_string& assign(basic_string&& other) { return *this = _NEFORCE move(other); }
1842
1848 NEFORCE_CONSTEXPR20 basic_string& assign(const_pointer str) { return *this = str; }
1849
1856 NEFORCE_CONSTEXPR20 basic_string& assign(const_pointer str, const size_type n) {
1857 clear();
1858 return append(str, n);
1859 }
1860
1867 NEFORCE_CONSTEXPR20 basic_string& assign(const size_type n, value_type value) {
1868 clear();
1869 return append(n, value);
1870 }
1871
1879 template <typename Iterator>
1880 NEFORCE_CONSTEXPR20 basic_string& assign(Iterator first, Iterator last) {
1881 clear();
1882 return append(first, last);
1883 }
1884
1890 NEFORCE_CONSTEXPR20 basic_string& assign(std::initializer_list<value_type> ilist) { return *this = ilist; }
1891
1897 NEFORCE_CONSTEXPR20 basic_string& assign(const view_type& view) { return *this = view; }
1898
1904 NEFORCE_CONSTEXPR20 iterator erase(iterator position) noexcept {
1905 NEFORCE_DEBUG_VERIFY(position != end(), "erase: cannot erase end() iterator");
1906
1907#ifdef NEFORCE_USING_SSO
1908 const size_type offset = position - begin();
1909 pointer p = data() + offset;
1910 const size_type chars_after = size() - offset - 1;
1911 if (chars_after > 0) {
1912 traits_type::move(p, p + 1, chars_after);
1913 }
1914 if (is_long()) {
1915 size_pair_.value = (size() - 1) | long_flag;
1916 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
1917 } else {
1918 size_pair_.value = size() - 1;
1919 traits_type::assign(storage_.short_ + size(), 1, value_type());
1920 }
1921#else
1922 pointer ptr = &*position;
1923 const size_type chars_after = end() - position - 1;
1924 if (chars_after > 0) {
1925 traits_type::move(ptr, ptr + 1, chars_after);
1926 }
1927
1928 --size_;
1929 traits_type::assign(data_ + size_, 1, value_type());
1930#endif
1931 return position;
1932 }
1933
1940 NEFORCE_CONSTEXPR20 basic_string& erase(size_type position = 0, size_type n = npos) noexcept {
1941 if (position >= size()) {
1942 return *this;
1943 }
1944 n = _NEFORCE min(n, size() - position);
1945 basic_string::erase(begin() + position, n);
1946 return *this;
1947 }
1948
1955 NEFORCE_CONSTEXPR20 iterator erase(iterator first, const size_type n) noexcept {
1956 if (n == 0) {
1957 return first;
1958 }
1959 iterator last = first + _NEFORCE min(n, static_cast<size_type>(end() - first));
1960 return erase(first, last);
1961 }
1962
1969 NEFORCE_CONSTEXPR20 iterator erase(iterator first, iterator last) noexcept {
1970 if (first == last) {
1971 return first;
1972 }
1973
1974 const size_type erase_count = last - first;
1975
1976#ifdef NEFORCE_USING_SSO
1977 const size_type offset = first - begin();
1978 pointer p = data() + offset;
1979 const size_type chars_after = end() - last;
1980 if (chars_after > 0) {
1981 traits_type::move(p, p + erase_count, chars_after);
1982 }
1983 if (is_long()) {
1984 size_pair_.value = (size() - erase_count) | long_flag;
1985 traits_type::assign(storage_.long_.ptr + size(), 1, value_type());
1986 } else {
1987 size_pair_.value = size() - erase_count;
1988 traits_type::assign(storage_.short_ + size(), 1, value_type());
1989 }
1990#else
1991 const size_type chars_after = end() - last;
1992
1993 if (chars_after > 0) {
1994 pointer p_first = data_ + (first - begin());
1995 pointer p_last = data_ + (last - begin());
1996 traits_type::move(p_first, p_last, chars_after);
1997 }
1998
1999 size_ -= erase_count;
2000 traits_type::assign(data_ + size_, 1, value_type());
2001#endif
2002 return first;
2003 }
2004
2005
2011 NEFORCE_CONSTEXPR20 void resize(size_type n, value_type value) {
2012 if (n < size()) {
2013 basic_string::erase(begin() + n, end());
2014 } else {
2015 basic_string::append(n - size(), value);
2016 }
2017 }
2018
2023 NEFORCE_CONSTEXPR20 void resize(const size_type n) { basic_string::resize(n, value_type()); }
2024
2028 NEFORCE_CONSTEXPR20 void clear() noexcept {
2029#ifdef NEFORCE_USING_SSO
2030 if (is_long()) {
2031 destroy_long();
2032 traits_type::assign(storage_.short_, 1, value_type());
2033 size_pair_.value = 0;
2034 } else {
2035 traits_type::assign(storage_.short_, 1, value_type());
2036 size_pair_.value = 0;
2037 }
2038#else
2039 size_ = 0;
2040 traits_type::assign(data_ + size_, 1, value_type());
2041#endif
2042 }
2043
2047 NEFORCE_CONSTEXPR20 void shrink_to_fit() {
2048#ifdef NEFORCE_USING_SSO
2049 if (!is_long()) {
2050 return;
2051 }
2052 const size_type len = size();
2053 if (len < sso_capacity) {
2054 CharT tmp[sso_buffer_size];
2055 traits_type::copy(tmp, storage_.long_.ptr, len);
2056 traits_type::assign(tmp + len, 1, value_type());
2057 destroy_long();
2058 traits_type::copy(storage_.short_, tmp, len + 1);
2059 size_pair_.value = len;
2060 } else {
2061 if (storage_.long_.cap > len + 1) {
2062 pointer new_ptr = size_pair_.get_base().allocate(len + 1);
2063 traits_type::move(new_ptr, storage_.long_.ptr, len);
2064 traits_type::assign(new_ptr + len, 1, value_type());
2065 destroy_long();
2066 storage_.long_.ptr = new_ptr;
2067 storage_.long_.cap = len + 1;
2068 size_pair_.value = len | long_flag;
2069 }
2070 }
2071#else
2072 const size_type new_cap = size_ + 1;
2073 if (new_cap >= capacity_pair_.value) {
2074 return;
2075 }
2076
2077 basic_string temp;
2078 temp.reserve(new_cap);
2079 temp.append(*this);
2080 basic_string::swap(temp);
2081#endif
2082 }
2083
2089 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 basic_string repeat(size_type n) const noexcept {
2090 basic_string result;
2091 result.reserve(size() * n);
2092 while (n--) {
2093 result += *this;
2094 }
2095 return _NEFORCE move(result);
2096 }
2097
2104 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 basic_string substr(const size_type off = 0, size_type count = npos) const {
2105 NEFORCE_DEBUG_VERIFY(off <= size(), "basic_string index out of ranges.");
2106 count = _NEFORCE min(count, size() - off);
2107 return basic_string(data() + off, count);
2108 }
2109
2114 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 view_type view() const noexcept { return view_type(data(), size()); }
2115
2122 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 view_type view(const size_type off, size_type count = npos) const noexcept {
2123 NEFORCE_DEBUG_VERIFY(off <= size(), "basic_string index out of ranges.");
2124 count = _NEFORCE min(count, size() - off);
2125 return view_type(data() + off, count);
2126 }
2127
2135 NEFORCE_CONSTEXPR20 size_type copy(pointer dest, const size_type count, size_type position = 0) const {
2136 NEFORCE_DEBUG_VERIFY(position <= size(), "basic_string copy position out of range");
2137 const size_type len = _NEFORCE min(count, size() - position);
2138 traits_type::copy(dest, data() + position, len);
2139 return len;
2140 }
2141
2147 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const basic_string& other) const noexcept {
2148 return compare(other.view());
2149 }
2150
2158 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n,
2159 const basic_string& other) const {
2160 return view(off, n).compare(other.view());
2161 }
2162
2172 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const basic_string& other,
2173 const size_type roff, const size_type count) const {
2174 return view(off, n).compare(other.view(roff, count));
2175 }
2176
2182 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const CharT* str) const noexcept {
2183 return compare(view_type(str));
2184 }
2185
2191 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const view_type& view) const noexcept {
2192 return char_traits_compare<traits_type>(data(), size(), view.data(), view.size());
2193 }
2194
2202 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const CharT* str) const {
2203 return view(off, n).compare(view_type(str));
2204 }
2205
2214 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const CharT* str,
2215 size_type count) const {
2216 return view(off, n).compare(view_type(str, count));
2217 }
2218
2220 NEFORCE_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n, const basic_string& other) {
2221 NEFORCE_DEBUG_VERIFY(position < size(), "basic_string index out of ranges.");
2222 return replace_copy(begin() + position, n, other.data(), other.size());
2223 }
2224
2226 NEFORCE_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const basic_string& other) {
2227 NEFORCE_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
2228 "basic_string replace iterator out of ranges.");
2229 return replace_copy(first, last - first, other.data(), other.size());
2230 }
2231
2233 NEFORCE_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n, const_pointer str) {
2234 NEFORCE_DEBUG_VERIFY(position < size(), "basic_string index out of ranges.");
2235 return replace_copy({data() + position, this}, n, str, traits_type::length(str));
2236 }
2237
2239 NEFORCE_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str) {
2240 NEFORCE_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
2241 "basic_string replace iterator out of ranges.");
2242 return replace_copy(first, last - first, str, traits_type::length(str));
2243 }
2244
2246 NEFORCE_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n1, const_pointer str,
2247 const size_type n2) {
2248 NEFORCE_DEBUG_VERIFY(position < size(), "basic_string index out of ranges.");
2249 return replace_copy({data() + position, this}, n1, str, n2);
2250 }
2251
2253 NEFORCE_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const_pointer str, const size_type n) {
2254 NEFORCE_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
2255 "basic_string replace iterator out of ranges.");
2256 return replace_copy(first, last - first, str, n);
2257 }
2258
2260 NEFORCE_CONSTEXPR20 basic_string& replace(const size_type position, const size_type n1, const size_type n2,
2261 const value_type value) {
2262 NEFORCE_DEBUG_VERIFY(position < size(), "basic_string index out of ranges.");
2263 return replace_fill({data() + position, this}, n1, n2, value);
2264 }
2265
2267 NEFORCE_CONSTEXPR20 basic_string& replace(iterator first, iterator last, const size_type n,
2268 const value_type value) {
2269 NEFORCE_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
2270 "basic_string replace iterator out of ranges.");
2271 return replace_fill(first, static_cast<size_type>(last - first), n, value);
2272 }
2273
2275 NEFORCE_CONSTEXPR20 basic_string& replace(const size_type position1, const size_type n1, const basic_string& str,
2276 const size_type position2, const size_type n2 = npos) {
2277 NEFORCE_DEBUG_VERIFY(position1 < size(), "basic_string index out of ranges.");
2278 NEFORCE_DEBUG_VERIFY(position2 < size(), "basic_string index out of ranges.");
2279 return replace_copy({data() + position1, this}, n1, str.data() + position2, n2);
2280 }
2281
2283 template <typename Iterator>
2284 NEFORCE_CONSTEXPR20 basic_string& replace(iterator first, iterator last, Iterator first2, Iterator last2) {
2285 NEFORCE_DEBUG_VERIFY(begin() <= first && last <= end() && first <= last,
2286 "basic_string replace iterator out of ranges.");
2287 return replace_copy(first, last, first2, last2);
2288 }
2289
2293 NEFORCE_CONSTEXPR20 void reverse() noexcept {
2294 if (size() < 2) {
2295 return;
2296 }
2297
2298 for (iterator first = begin(), last = end(); first < last;) {
2299 _NEFORCE iter_swap(first++, --last);
2300 }
2301 }
2302
2304 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const basic_string& other,
2305 const size_type n = 0) const noexcept {
2306 return (char_traits_find<Traits>) (data(), size(), n, other.data(), other.size());
2307 }
2308
2310 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT value, const size_type n = 0) const noexcept {
2311 return (char_traits_find_char<Traits>) (data(), size(), n, value);
2312 }
2313
2315 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT* str, const size_type off,
2316 const size_type count) const noexcept {
2317 return (char_traits_find<Traits>) (data(), size(), off, str, count);
2318 }
2319
2321 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT* str, const size_type off = 0) const noexcept {
2322 return (char_traits_find<Traits>) (data(), size(), off, str, Traits::length(str));
2323 }
2324
2326 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const view_type& view, const size_type off,
2327 const size_type count) const noexcept {
2328 return (char_traits_find<Traits>) (data(), size(), off, view.data(), count);
2329 }
2330
2332 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const view_type& view,
2333 const size_type off = 0) const noexcept {
2334 return _NEFORCE char_traits_find<Traits>(data(), size(), off, view.data(), view.size());
2335 }
2336
2338 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const basic_string& other,
2339 const size_type off = npos) const noexcept {
2340 return (char_traits_rfind<Traits>) (data(), size(), off, other.data(), other.size());
2341 }
2342
2344 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT value, const size_type n = npos) const noexcept {
2345 return (char_traits_rfind_char<Traits>) (data(), size(), n, value);
2346 }
2347
2349 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT* str, const size_type off,
2350 const size_type n) const noexcept {
2351 return (char_traits_rfind<Traits>) (data(), size(), off, str, n);
2352 }
2353
2355 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT* str, const size_type off = npos) const noexcept {
2356 return (char_traits_rfind<Traits>) (data(), size(), off, str, Traits::length(str));
2357 }
2358
2360 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const view_type& view, const size_type off,
2361 const size_type count) const noexcept {
2362 return (char_traits_rfind<Traits>) (data(), size(), off, view.data(), count);
2363 }
2364
2366 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const view_type& view,
2367 const size_type off = 0) const noexcept {
2368 return (char_traits_rfind<Traits>) (data(), size(), off, view.data(), view.size());
2369 }
2370
2372 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const basic_string& other,
2373 const size_type off = 0) const noexcept {
2374 return (char_traits_find_first_of<Traits>) (data(), size(), off, other.data(), other.size());
2375 }
2376
2378 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT value,
2379 const size_type off = 0) const noexcept {
2380 return (char_traits_find_char<Traits>) (data(), size(), off, value);
2381 }
2382
2384 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT* str, const size_type off,
2385 const size_type n) const noexcept {
2386 return (char_traits_find_first_of<Traits>) (data(), size(), off, str, n);
2387 }
2388
2390 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT* str,
2391 const size_type off = 0) const noexcept {
2392 return (char_traits_find_first_of<Traits>) (data(), size(), off, str, Traits::length(str));
2393 }
2394
2396 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const view_type& view, const size_type off,
2397 const size_type n) const noexcept {
2398 return (char_traits_find_first_of<Traits>) (data(), size(), off, view.data(), n);
2399 }
2400
2402 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const view_type& view,
2403 const size_type off = 0) const noexcept {
2404 return (char_traits_find_first_of<Traits>) (data(), size(), off, view.data(), view.size());
2405 }
2406
2408 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const basic_string& other,
2409 const size_type off = npos) const noexcept {
2410 return (char_traits_find_last_of<Traits>) (data(), size(), off, other.data(), other.size());
2411 }
2412
2414 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT value,
2415 const size_type off = npos) const noexcept {
2416 return (char_traits_rfind_char<Traits>) (data(), size(), off, value);
2417 }
2418
2420 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT* str, const size_type off,
2421 const size_type n) const noexcept {
2422 return (char_traits_find_last_of<Traits>) (data(), size(), off, str, n);
2423 }
2424
2426 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT* str,
2427 const size_type off = npos) const noexcept {
2428 return (char_traits_find_last_of<Traits>) (data(), size(), off, str, Traits::length(str));
2429 }
2430
2432 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const view_type& view, const size_type off,
2433 const size_type n) const noexcept {
2434 return (char_traits_find_last_of<Traits>) (data(), size(), off, view.data(), n);
2435 }
2436
2438 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const view_type& view,
2439 const size_type off = npos) const noexcept {
2440 return (char_traits_find_last_of<Traits>) (data(), size(), off, view.data(), view.size());
2441 }
2442
2444 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const basic_string& other,
2445 const size_type off = 0) const noexcept {
2446 return (char_traits_find_first_not_of<Traits>) (data(), size(), off, other.data(), other.size());
2447 }
2448
2450 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT value,
2451 const size_type off = 0) const noexcept {
2452 return (char_traits_find_not_char<Traits>) (data(), size(), off, value);
2453 }
2454
2456 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT* str, const size_type off,
2457 const size_type n) const noexcept {
2458 return (char_traits_find_first_not_of<Traits>) (data(), size(), off, str, n);
2459 }
2460
2462 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT* str,
2463 const size_type off = 0) const noexcept {
2464 return (char_traits_find_first_not_of<Traits>) (data(), size(), off, str, Traits::length(str));
2465 }
2466
2468 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const view_type& view, const size_type off,
2469 const size_type n) const noexcept {
2470 return (char_traits_find_first_not_of<Traits>) (data(), size(), off, view.data(), n);
2471 }
2472
2474 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const view_type& view,
2475 const size_type off = 0) const noexcept {
2476 return (char_traits_find_first_not_of<Traits>) (data(), size(), off, view.data(), view.size());
2477 }
2478
2480 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const basic_string& other,
2481 const size_type off = npos) const noexcept {
2482 return (char_traits_find_last_not_of<Traits>) (data(), size(), off, other.data(), other.size());
2483 }
2484
2486 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT value,
2487 const size_type off = npos) const noexcept {
2488 return (char_traits_rfind_not_char<Traits>) (data(), size(), off, value);
2489 }
2490
2492 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT* str, const size_type off,
2493 const size_type n) const noexcept {
2494 return (char_traits_find_last_not_of<Traits>) (data(), size(), off, str, n);
2495 }
2496
2498 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT* str,
2499 const size_type off = npos) const noexcept {
2500 return (char_traits_find_last_not_of<Traits>) (data(), size(), off, str, Traits::length(str));
2501 }
2502
2504 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const view_type& view, const size_type off,
2505 const size_type n) const noexcept {
2506 return (char_traits_find_last_not_of<Traits>) (data(), size(), off, view.data(), n);
2507 }
2508
2510 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const view_type& view,
2511 const size_type off = npos) const noexcept {
2512 return (char_traits_find_last_not_of<Traits>) (data(), size(), off, view.data(), view.size());
2513 }
2514
2521 NEFORCE_CONSTEXPR20 size_type count(value_type value, const size_type position = 0) const noexcept {
2522 size_type n = 0;
2523 for (size_type idx = position; idx < size(); ++idx) {
2524 if (*(data() + idx) == value) {
2525 ++n;
2526 }
2527 }
2528 return n;
2529 }
2530
2532 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const basic_string& other) const noexcept {
2533 return other.size() <= size() && traits_type::compare(data(), other.data(), other.size()) == 0;
2534 }
2535
2537 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(view_type view) const noexcept {
2538 return view.size() <= size() && traits_type::compare(data(), view.data(), view.size()) == 0;
2539 }
2540
2542 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const value_type value) const noexcept {
2543 return !empty() && traits_type::eq(front(), value);
2544 }
2545
2547 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const_pointer str) const noexcept {
2548 return starts_with(view_type(str));
2549 }
2550
2552 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(const basic_string& other) const noexcept {
2553 const size_type other_size = other.size();
2554 return other_size <= size() &&
2555 traits_type::compare(data() + size() - other_size, other.data(), other_size) == 0;
2556 }
2557
2559 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(view_type view) const noexcept {
2560 const size_type view_size = view.size();
2561 return view_size <= size() && traits_type::compare(data() + size() - view_size, view.data(), view_size) == 0;
2562 }
2563
2565 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(value_type value) const noexcept {
2566 return !empty() && traits_type::eq(back(), value);
2567 }
2568
2570 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(const_pointer str) const noexcept {
2571 return ends_with(view_type(str));
2572 }
2573
2575 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(const basic_string& other) const noexcept {
2576 return find(other) != npos;
2577 }
2578
2580 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(view_type view) const noexcept { return find(view) != npos; }
2581
2583 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(value_type value) const noexcept { return find(value) != npos; }
2584
2586 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(const_pointer str) const noexcept { return find(str) != npos; }
2587
2592 NEFORCE_CONSTEXPR20 basic_string& trim_left() noexcept {
2593 return trim_left_if([](value_type value) { return _NEFORCE is_space(value); });
2594 }
2595
2600 NEFORCE_CONSTEXPR20 basic_string& trim_right() noexcept {
2601 return trim_right_if([](value_type value) { return _NEFORCE is_space(value); });
2602 }
2603
2608 NEFORCE_CONSTEXPR20 basic_string& trim() noexcept { return trim_left().trim_right(); }
2609
2616 template <typename Pred>
2617 NEFORCE_CONSTEXPR20 basic_string& trim_left_if(Pred pred) {
2618 if (empty()) {
2619 return *this;
2620 }
2621
2622 iterator it = begin();
2623 while (it != end() && pred(*it)) {
2624 ++it;
2625 }
2626 if (it != begin()) {
2627 basic_string::erase(begin(), it - begin());
2628 }
2629
2630 return *this;
2631 }
2632
2639 template <typename Pred>
2640 NEFORCE_CONSTEXPR20 basic_string& trim_right_if(Pred pred) {
2641 if (empty()) {
2642 return *this;
2643 }
2644
2645 reverse_iterator rit = rbegin();
2646 while (rit != rend() && pred(*rit)) {
2647 ++rit;
2648 }
2649 if (rit != rbegin()) {
2650 basic_string::erase(end() - (rit - rbegin()), end());
2651 }
2652
2653 return *this;
2654 }
2655
2662 template <typename Predicate>
2663 NEFORCE_CONSTEXPR20 basic_string& trim_if(Predicate pred) {
2664 return trim_left_if(pred).trim_right_if(pred);
2665 }
2666
2672 NEFORCE_CONSTEXPR20 bool equal_to(const basic_string& other) const noexcept { return equal_to(other.view()); }
2673
2679 NEFORCE_CONSTEXPR20 bool equal_to(const view_type view) const noexcept {
2680 return _NEFORCE char_traits_equal<Traits>(data(), size(), view.data(), view.size());
2681 }
2682
2688 NEFORCE_CONSTEXPR20 bool equal_to(const CharT* str) const noexcept { return equal_to(view_type(str)); }
2689
2693 NEFORCE_CONSTEXPR20 basic_string&
2694 lowercase() noexcept(noexcept(_NEFORCE transform(begin(), end(), begin(), _NEFORCE to_lowercase<CharT>))) {
2695 _NEFORCE transform(begin(), end(), begin(), _NEFORCE to_lowercase<CharT>);
2696 return *this;
2697 }
2698
2702 NEFORCE_CONSTEXPR20 basic_string&
2703 uppercase() noexcept(noexcept(_NEFORCE transform(begin(), end(), begin(), _NEFORCE to_uppercase<CharT>))) {
2704 _NEFORCE transform(begin(), end(), begin(), _NEFORCE to_uppercase<CharT>);
2705 return *this;
2706 }
2707
2712 NEFORCE_CONSTEXPR20 void swap(basic_string& other) noexcept {
2713 if (_NEFORCE addressof(other) == this) {
2714 return;
2715 }
2716#ifdef NEFORCE_USING_SSO
2717 _NEFORCE swap(storage_, other.storage_);
2718 _NEFORCE swap(size_pair_, other.size_pair_);
2719#else
2720 _NEFORCE swap(data_, other.data_);
2721 _NEFORCE swap(size_, other.size_);
2722 _NEFORCE swap(capacity_pair_, other.capacity_pair_);
2723#endif
2724 }
2725
2727 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const basic_string& rhs) const noexcept {
2728 return equal_to(rhs);
2729 }
2730
2732 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const basic_string& rhs) const noexcept {
2733 return compare(rhs) < 0;
2734 }
2735
2737 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_t to_hash() const noexcept {
2738 return _NEFORCE FNV_hash_string(data(), size());
2739 }
2740};
2741
2742#ifdef NEFORCE_STANDARD_17
2743template <typename Iterator, typename Alloc = allocator<iter_value_t<Iterator>>>
2744basic_string(Iterator, Iterator, Alloc = Alloc())
2745 -> basic_string<iter_value_t<Iterator>, char_traits<iter_value_t<Iterator>>, Alloc>;
2746
2747template <typename CharT, typename Traits, typename Alloc = allocator<CharT>>
2748explicit basic_string(basic_string_view<CharT, Traits>, const Alloc& = Alloc()) -> basic_string<CharT, Traits, Alloc>;
2749
2750template <typename CharT, typename Traits, typename Alloc = allocator<CharT>>
2751basic_string(basic_string_view<CharT, Traits>, typename allocator_traits<Alloc>::size_type,
2753#endif
2754
2755template <typename CharT, typename Traits, typename Alloc>
2759 tmp.append(rhs);
2760 return _NEFORCE move(tmp);
2761}
2762
2763template <typename CharT, typename Traits, typename Alloc>
2764NEFORCE_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator+(const CharT* lhs,
2767 tmp.append(rhs);
2768 return _NEFORCE move(tmp);
2769}
2770template <typename CharT, typename Traits, typename Alloc>
2772 const CharT* rhs) {
2774 tmp.append(rhs);
2775 return _NEFORCE move(tmp);
2776}
2777
2778template <typename CharT, typename Traits, typename Alloc>
2779NEFORCE_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator+(const basic_string_view<CharT, Traits>& lhs,
2782 tmp.append(rhs);
2783 return _NEFORCE move(tmp);
2784}
2785template <typename CharT, typename Traits, typename Alloc>
2787 const basic_string_view<CharT, Traits>& rhs) {
2789 tmp.append(rhs);
2790 return _NEFORCE move(tmp);
2791}
2792
2793template <typename CharT, typename Traits, typename Alloc>
2794NEFORCE_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator+(CharT lhs,
2797 tmp.append(rhs);
2798 return _NEFORCE move(tmp);
2799}
2800template <typename CharT, typename Traits, typename Alloc>
2802 CharT rhs) {
2804 tmp.append(1, rhs);
2805 return _NEFORCE move(tmp);
2806}
2807
2808template <typename CharT, typename Traits, typename Alloc>
2811 return _NEFORCE move(lhs.append(rhs));
2812}
2813template <typename CharT, typename Traits, typename Alloc>
2817 tmp.append(_NEFORCE move(rhs));
2818 return _NEFORCE move(tmp);
2819}
2820
2821template <typename CharT, typename Traits, typename Alloc>
2824 basic_string<CharT, Traits, Alloc> tmp(_NEFORCE move(lhs));
2825 if (_NEFORCE addressof(lhs) != _NEFORCE addressof(rhs)) {
2826 tmp.append(_NEFORCE move(rhs));
2827 } else {
2828 tmp.append(lhs);
2829 }
2830 return _NEFORCE move(tmp);
2831}
2832
2833template <typename CharT, typename Traits, typename Alloc>
2834NEFORCE_CONSTEXPR20 basic_string<CharT, Traits, Alloc> operator+(const CharT* lhs,
2837 tmp.append(_NEFORCE move(rhs));
2838 return _NEFORCE move(tmp);
2839}
2840template <typename CharT, typename Traits, typename Alloc>
2842 const CharT* rhs) {
2843 return _NEFORCE move(lhs.append(rhs));
2844}
2845
2846template <typename CharT, typename Traits, typename Alloc>
2849 tmp.append(_NEFORCE move(rhs));
2850 return _NEFORCE move(tmp);
2851}
2852template <typename CharT, typename Traits, typename Alloc>
2854 return _NEFORCE move(lhs.append(rhs));
2855}
2856
2857template <typename CharT, typename Traits, typename Alloc>
2858NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const CharT* const lhs,
2859 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2860 return rhs.equal_to(lhs);
2861}
2862template <typename CharT, typename Traits, typename Alloc>
2863NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const basic_string<CharT, Traits, Alloc>& lhs,
2864 const CharT* const rhs) noexcept {
2865 return lhs.equal_to(rhs);
2866}
2867template <typename CharT, typename Traits, typename Alloc>
2868NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const basic_string_view<CharT, Traits>& lhs,
2869 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2870 return rhs.equal_to(lhs);
2871}
2872template <typename CharT, typename Traits, typename Alloc>
2873NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const basic_string<CharT, Traits, Alloc>& lhs,
2874 const basic_string_view<CharT, Traits>& rhs) noexcept {
2875 return lhs.equal_to(rhs);
2876}
2877
2878template <typename CharT, typename Traits, typename Alloc>
2879NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const CharT* const lhs,
2880 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2881 return !(lhs == rhs);
2882}
2883template <typename CharT, typename Traits, typename Alloc>
2884NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const basic_string<CharT, Traits, Alloc>& lhs,
2885 const CharT* const rhs) noexcept {
2886 return !(lhs == rhs);
2887}
2888template <typename CharT, typename Traits, typename Alloc>
2889NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const basic_string_view<CharT, Traits>& lhs,
2890 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2891 return !(lhs == rhs);
2892}
2893template <typename CharT, typename Traits, typename Alloc>
2894NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const basic_string<CharT, Traits, Alloc>& lhs,
2895 const basic_string_view<CharT, Traits>& rhs) noexcept {
2896 return !(lhs == rhs);
2897}
2898
2899template <typename CharT, typename Traits, typename Alloc>
2900NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const CharT* const lhs,
2901 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2902 return 0 < rhs.compare(lhs);
2903}
2904template <typename CharT, typename Traits, typename Alloc>
2905NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const basic_string<CharT, Traits, Alloc>& lhs,
2906 const CharT* const rhs) noexcept {
2907 return lhs.compare(rhs) < 0;
2908}
2909template <typename CharT, typename Traits, typename Alloc>
2910NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const basic_string_view<CharT, Traits>& lhs,
2911 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2912 return 0 < rhs.compare(lhs);
2913}
2914template <typename CharT, typename Traits, typename Alloc>
2915NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const basic_string<CharT, Traits, Alloc>& lhs,
2916 const basic_string_view<CharT, Traits>& rhs) noexcept {
2917 return lhs.compare(rhs) < 0;
2918}
2919
2920template <typename CharT, typename Traits, typename Alloc>
2921NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>(const CharT* const lhs,
2922 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2923 return rhs < lhs;
2924}
2925template <typename CharT, typename Traits, typename Alloc>
2926NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>(const basic_string<CharT, Traits, Alloc>& lhs,
2927 const CharT* const rhs) noexcept {
2928 return rhs < lhs;
2929}
2930template <typename CharT, typename Traits, typename Alloc>
2931NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>(const basic_string_view<CharT, Traits>& lhs,
2932 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2933 return rhs < lhs;
2934}
2935template <typename CharT, typename Traits, typename Alloc>
2936NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>(const basic_string<CharT, Traits, Alloc>& lhs,
2937 const basic_string_view<CharT, Traits>& rhs) noexcept {
2938 return rhs < lhs;
2939}
2940
2941template <typename CharT, typename Traits, typename Alloc>
2942NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<=(const CharT* const lhs,
2943 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2944 return !(lhs > rhs);
2945}
2946template <typename CharT, typename Traits, typename Alloc>
2947NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<=(const basic_string<CharT, Traits, Alloc>& lhs,
2948 const CharT* const rhs) noexcept {
2949 return !(lhs > rhs);
2950}
2951template <typename CharT, typename Traits, typename Alloc>
2952NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<=(const basic_string_view<CharT, Traits>& lhs,
2953 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2954 return !(lhs > rhs);
2955}
2956template <typename CharT, typename Traits, typename Alloc>
2957NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<=(const basic_string<CharT, Traits, Alloc>& lhs,
2958 const basic_string_view<CharT, Traits>& rhs) noexcept {
2959 return !(lhs > rhs);
2960}
2961
2962template <typename CharT, typename Traits, typename Alloc>
2963NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>=(const CharT* const lhs,
2964 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2965 return !(rhs < lhs);
2966}
2967template <typename CharT, typename Traits, typename Alloc>
2968NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>=(const basic_string<CharT, Traits, Alloc>& lhs,
2969 const CharT* const rhs) noexcept {
2970 return !(rhs < lhs);
2971}
2972template <typename CharT, typename Traits, typename Alloc>
2973NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>=(const basic_string_view<CharT, Traits>& lhs,
2974 const basic_string<CharT, Traits, Alloc>& rhs) noexcept {
2975 return !(rhs < lhs);
2976}
2977template <typename CharT, typename Traits, typename Alloc>
2978NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator>=(const basic_string<CharT, Traits, Alloc>& lhs,
2979 const basic_string_view<CharT, Traits>& rhs) noexcept {
2980 return !(rhs < lhs);
2981}
2982
2983
2984extern template class basic_string<char>;
2985extern template class basic_string<wchar_t>;
2986#ifdef NEFORCE_STANDARD_20
2987extern template class basic_string<char8_t>;
2988#endif
2989extern template class basic_string<char16_t>;
2990extern template class basic_string<char32_t>;
2991 // String
2993
2994NEFORCE_END_NAMESPACE__
2995#endif // NEFORCE_CORE_STRING_BASIC_STRING_HPP__
分配器特性
基本字符串视图模板
NEFORCE_NODISCARD constexpr int compare(const basic_string_view view) const noexcept
比较字符串视图
基础字符串模板
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const view_type &view, const size_type off, const size_type count) const noexcept
从后向前查找指定长度的字符串视图
Traits traits_type
字符特征类型
NEFORCE_CONSTEXPR20 basic_string & uppercase() noexcept(noexcept(_NEFORCE transform(begin(), end(), begin(), _NEFORCE to_uppercase< CharT >)))
转换为大写
NEFORCE_CONSTEXPR20 basic_string & append(const_pointer str, size_type n)
追加字符数组的指定长度
NEFORCE_CONSTEXPR20 basic_string & replace(iterator first, iterator last, Iterator first2, Iterator last2)
替换迭代器范围为另一个迭代器范围
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const basic_string &other) const noexcept
检查是否以另一个字符串开头
NEFORCE_CONSTEXPR20 basic_string & trim_left() noexcept
去除左侧空白字符
CharT * pointer
指针类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference front() noexcept
访问第一个字符
NEFORCE_CONSTEXPR20 basic_string & replace(iterator first, iterator last, const size_type n, const value_type value)
替换迭代器范围为多个相同字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(view_type view) const noexcept
检查是否以字符串视图开头
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const basic_string &other, const size_type off=0) const noexcept
查找第一个出现在字符集合中的字符
NEFORCE_CONSTEXPR20 basic_string & append(const basic_string &other, size_type position)
追加另一个字符串的子串
NEFORCE_CONSTEXPR20 ~basic_string()
析构函数
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reverse_iterator rend() noexcept
获取反向结束迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(const_pointer str) const noexcept
检查是否包含C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT value, const size_type off=npos) const noexcept
查找最后一个等于指定字符的位置
NEFORCE_CONSTEXPR20 basic_string & assign(const basic_string &other)
赋值另一个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference back() noexcept
访问最后一个字符
NEFORCE_CONSTEXPR20 void reserve(const size_type n)
预留容量
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator begin() const noexcept
获取常量起始迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT value, const size_type n=0) const noexcept
查找字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 view_type view() const noexcept
NEFORCE_CONSTEXPR20 basic_string(const_pointer str)
从C风格字符串构造
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference at(const size_type n) const noexcept
带边界检查的常量访问
NEFORCE_CONSTEXPR20 basic_string & lowercase() noexcept(noexcept(_NEFORCE transform(begin(), end(), begin(), _NEFORCE to_lowercase< CharT >)))
转换为小写
NEFORCE_CONSTEXPR20 basic_string & assign(const_pointer str)
赋值C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference operator[](const size_type n) const noexcept
常量下标访问操作符
NEFORCE_CONSTEXPR20 basic_string(basic_string &&other) noexcept
移动构造函数
NEFORCE_CONSTEXPR20 bool equal_to(const CharT *str) const noexcept
与C风格字符串相等比较
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const CharT *str) const
比较子串与C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const basic_string &other, const size_type n=0) const noexcept
查找子串
NEFORCE_CONSTEXPR20 iterator erase(iterator first, iterator last) noexcept
删除迭代器范围
NEFORCE_CONSTEXPR20 basic_string()
默认构造函数
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const view_type &view, const size_type off=0) const noexcept
查找第一个不在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator rend() const noexcept
获取常量反向结束迭代器
ptrdiff_t difference_type
差值类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const basic_string &other, const size_type off=0) const noexcept
查找第一个不在字符集合中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 basic_string repeat(size_type n) const noexcept
重复当前字符串n次
CharT & reference
引用类型
NEFORCE_CONSTEXPR20 basic_string(size_type n, int32_t value)
构造函数,指定大小和32位整数值
NEFORCE_CONSTEXPR20 void swap(basic_string &other) noexcept
交换两个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(const basic_string &other) const noexcept
检查是否包含另一个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(const basic_string &other) const noexcept
检查是否以另一个字符串结尾
NEFORCE_CONSTEXPR20 basic_string & operator+=(std::initializer_list< value_type > ilist)
追加初始化列表
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT *str, const size_type off, const size_type n) const noexcept
查找最后一个出现在指定字符数组中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT *str, const size_type off, const size_type count) const noexcept
查找指定长度的子串
const CharT * const_pointer
常量指针类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const basic_string &other, const size_type off=npos) const noexcept
查找最后一个不在字符集合中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type length() const noexcept
获取字符串长度
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 iterator end() noexcept
获取结束迭代器
NEFORCE_CONSTEXPR20 basic_string(Iterator first, Iterator last)
从迭代器范围构造
NEFORCE_CONSTEXPR20 basic_string(const basic_string &other, size_type position)
从子串构造
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator rbegin() const noexcept
获取常量反向起始迭代器
NEFORCE_CONSTEXPR20 basic_string & assign(const_pointer str, const size_type n)
赋值字符数组的指定长度
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator crend() const noexcept
获取常量反向结束迭代器
NEFORCE_CONSTEXPR20 basic_string & append(view_type view, size_type n)
追加字符串视图的指定长度
NEFORCE_CONSTEXPR20 basic_string & erase(size_type position=0, size_type n=npos) noexcept
删除指定范围内的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT value, const size_type n=npos) const noexcept
从后向前查找字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const view_type &view, const size_type off=0) const noexcept
从后向前查找字符串视图
NEFORCE_CONSTEXPR20 basic_string(size_type n, int64_t value)
构造函数,指定大小和64位整数值
NEFORCE_CONSTEXPR20 void pop_back() noexcept
删除末尾字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_pointer data() const noexcept
获取常量数据指针
NEFORCE_CONSTEXPR20 basic_string & append(value_type value)
追加单个字符
NEFORCE_CONSTEXPR20 basic_string(size_type n, value_type value)
构造函数,指定大小和填充字符
NEFORCE_CONSTEXPR20 basic_string & operator+=(const value_type value)
追加单个字符
basic_string_view< CharT, Traits > view_type
字符串视图类型
NEFORCE_CONSTEXPR20 basic_string(std::initializer_list< value_type > ilist)
从初始化列表构造
NEFORCE_CONSTEXPR20 basic_string & append(basic_string &&other)
追加移动字符串
NEFORCE_CONSTEXPR20 iterator insert(iterator position, Iterator first, Iterator last)
插入迭代器范围
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const basic_string &other) const
比较子串与另一个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const view_type &view, const size_type off=npos) const noexcept
查找最后一个出现在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const view_type &view, const size_type off, const size_type n) const noexcept
查找最后一个不在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator<(const basic_string &rhs) const noexcept
小于比较操作符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const view_type &view, const size_type off, const size_type count) const noexcept
查找指定长度的字符串视图
NEFORCE_CONSTEXPR20 basic_string & replace(const size_type position, const size_type n1, const size_type n2, const value_type value)
替换子串为多个相同字符
NEFORCE_CONSTEXPR20 basic_string & replace(const size_type position, const size_type n1, const_pointer str, const size_type n2)
替换子串为指定长度的字符数组
NEFORCE_CONSTEXPR20 basic_string & replace(const size_type position, const size_type n, const basic_string &other)
替换子串为另一个字符串
NEFORCE_CONSTEXPR20 basic_string & trim_right() noexcept
去除右侧空白字符
NEFORCE_CONSTEXPR20 bool equal_to(const view_type view) const noexcept
与字符串视图相等比较
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const CharT *str) const noexcept
比较C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT *str, const size_type off, const size_type n) const noexcept
从后向前查找指定长度的子串
NEFORCE_CONSTEXPR20 basic_string & trim_left_if(Pred pred)
根据谓词去除左侧字符
NEFORCE_CONSTEXPR20 basic_string & append(size_type n, value_type value)
追加多个相同字符
NEFORCE_CONSTEXPR20 basic_string & operator=(const_pointer str)
C风格字符串赋值运算符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type size() const noexcept
获取字符数
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(view_type view) const noexcept
检查是否包含字符串视图
NEFORCE_CONSTEXPR20 basic_string & append(view_type view)
追加字符串视图
NEFORCE_CONSTEXPR20 basic_string & operator=(view_type view)
字符串视图赋值运算符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const view_type &view, const size_type off, const size_type n) const noexcept
查找最后一个出现在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type max_size() const noexcept
获取最大可能大小
NEFORCE_CONSTEXPR20 basic_string & append(const_pointer str)
追加C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT value, const size_type off=npos) const noexcept
查找最后一个不等于指定字符的位置
NEFORCE_CONSTEXPR20 void push_back(value_type value)
在末尾插入字符
NEFORCE_CONSTEXPR20 basic_string & operator=(basic_string &&other) noexcept
移动赋值运算符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT *str, const size_type off=npos) const noexcept
查找最后一个不在C风格字符串中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const CharT *str, size_type count) const
比较子串与指定长度的字符数组
NEFORCE_CONSTEXPR20 size_type copy(pointer dest, const size_type count, size_type position=0) const
复制字符到目标缓冲区
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reverse_iterator rbegin() noexcept
获取反向起始迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator cbegin() const noexcept
获取常量起始迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 basic_string substr(const size_type off=0, size_type count=npos) const
获取子串
NEFORCE_CONSTEXPR20 basic_string & assign(const view_type &view)
赋值字符串视图
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator cend() const noexcept
获取常量结束迭代器
NEFORCE_CONSTEXPR20 basic_string(view_type view, const size_type n)
从字符串视图构造(指定长度)
NEFORCE_CONSTEXPR20 bool equal_to(const basic_string &other) const noexcept
相等比较
NEFORCE_CONSTEXPR20 basic_string & operator=(std::initializer_list< value_type > ilist)
初始化列表赋值运算符
NEFORCE_CONSTEXPR20 basic_string & append(basic_string &&other, size_type position)
追加移动字符串的子串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const view_type &view, const size_type off, const size_type n) const noexcept
查找第一个出现在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT *str, const size_type off=0) const noexcept
查找第一个出现在C风格字符串中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference at(const size_type n) noexcept
带边界检查的访问
NEFORCE_CONSTEXPR20 basic_string & trim_right_if(Pred pred)
根据谓词去除右侧字符
NEFORCE_CONSTEXPR20 basic_string & append(basic_string &&other, size_type position, size_type n)
追加移动字符串的子串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference operator[](const size_type n) noexcept
下标访问操作符
NEFORCE_CONSTEXPR20 basic_string & append(const basic_string &other, size_type position, size_type n)
追加另一个字符串的子串
NEFORCE_CONSTEXPR20 basic_string & insert(size_type position, size_type n, value_type value)
在指定位置插入多个相同字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const view_type &view, const size_type off=0) const noexcept
查找字符串视图
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const basic_string &other, const size_type off=npos) const noexcept
查找最后一个出现在字符集合中的字符
NEFORCE_CONSTEXPR20 iterator erase(iterator first, const size_type n) noexcept
删除指定数量的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const value_type value) const noexcept
检查是否以指定字符开头
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(view_type view) const noexcept
检查是否以字符串视图结尾
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reverse_iterator crbegin() const noexcept
获取常量反向起始迭代器
NEFORCE_CONSTEXPR20 basic_string & operator+=(basic_string &&other)
追加移动字符串
NEFORCE_CONSTEXPR20 basic_string & assign(Iterator first, Iterator last)
赋值迭代器范围
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const basic_string &other) const noexcept
比较另一个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type capacity() const noexcept
获取容量
NEFORCE_CONSTEXPR20 basic_string & operator=(const basic_string &other)
拷贝赋值运算符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const view_type &view) const noexcept
比较字符串视图
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference back() const noexcept
常量访问最后一个字符
NEFORCE_CONSTEXPR20 basic_string & operator+=(const basic_string &other)
追加另一个字符串
basic_string_iterator< false, basic_string > iterator
迭代器类型
NEFORCE_CONSTEXPR20 basic_string & trim_if(Predicate pred)
根据谓词去除两侧字符
NEFORCE_CONSTEXPR20 basic_string & operator+=(view_type view)
追加字符串视图
NEFORCE_CONSTEXPR20 void shrink_to_fit()
收缩容量以适应当前大小
NEFORCE_CONSTEXPR20 void resize(size_type n, value_type value)
调整大小
NEFORCE_CONSTEXPR20 basic_string & replace(const size_type position, const size_type n, const_pointer str)
替换子串为C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_of(const CharT *str, const size_type off=npos) const noexcept
查找最后一个出现在C风格字符串中的字符
NEFORCE_CONSTEXPR20 basic_string & append(std::initializer_list< value_type > ilist)
追加初始化列表
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(value_type value) const noexcept
检查是否以指定字符结尾
size_t size_type
大小类型
NEFORCE_CONSTEXPR20 iterator insert(iterator position, value_type value)
插入单个字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 iterator begin() noexcept
获取起始迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find(const CharT *str, const size_type off=0) const noexcept
查找C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const CharT *str, const size_type off=npos) const noexcept
从后向前查找C风格字符串
NEFORCE_CONSTEXPR20 basic_string & trim() noexcept
去除两侧空白字符
NEFORCE_CONSTEXPR20 basic_string & replace(iterator first, iterator last, const basic_string &other)
替换迭代器范围为另一个字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_iterator end() const noexcept
获取常量结束迭代器
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const CharT *str, const size_type off, const size_type n) const noexcept
查找最后一个不在指定字符数组中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const basic_string &rhs) const noexcept
相等比较操作符
NEFORCE_CONSTEXPR20 void reverse() noexcept
反转字符串
NEFORCE_CONSTEXPR20 basic_string & assign(basic_string &&other)
赋值移动字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT *str, const size_type off=0) const noexcept
查找第一个不在C风格字符串中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT value, const size_type off=0) const noexcept
查找第一个不等于指定字符的位置
NEFORCE_CONSTEXPR20 iterator erase(iterator position) noexcept
删除指定位置的字符
NEFORCE_CONSTEXPR20 basic_string & replace(iterator first, iterator last, const_pointer str)
替换迭代器范围为C风格字符串
const CharT & const_reference
常量引用类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const_reference front() const noexcept
常量访问第一个字符
NEFORCE_CONSTEXPR20 basic_string(const_pointer str, const size_type n)
从字符数组构造(指定长度)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT *str, const size_type off, const size_type n) const noexcept
查找第一个出现在指定字符数组中的字符
NEFORCE_CONSTEXPR20 basic_string & replace(const size_type position1, const size_type n1, const basic_string &str, const size_type position2, const size_type n2=npos)
替换子串为另一个字符串的子串
NEFORCE_CONSTEXPR20 basic_string & operator+=(const_pointer str)
追加C风格字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool contains(value_type value) const noexcept
检查是否包含指定字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const CharT value, const size_type off=0) const noexcept
查找第一个等于指定字符的位置
basic_string_iterator< true, basic_string > const_iterator
常量迭代器类型
NEFORCE_CONSTEXPR20 basic_string(view_type view)
从字符串视图构造
NEFORCE_CONSTEXPR20 size_type count(value_type value, const size_type position=0) const noexcept
NEFORCE_CONSTEXPR20 basic_string & assign(std::initializer_list< value_type > ilist)
赋值初始化列表
CharT value_type
值类型
NEFORCE_CONSTEXPR20 basic_string & assign(const size_type n, value_type value)
赋值多个相同字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 int compare(const size_type off, const size_type n, const basic_string &other, const size_type roff, const size_type count) const
比较子串与另一个字符串的子串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool empty() const noexcept
检查是否为空
static constexpr size_type npos
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_t to_hash() const noexcept
计算哈希值
NEFORCE_CONSTEXPR20 basic_string & replace(iterator first, iterator last, const_pointer str, const size_type n)
替换迭代器范围为指定长度的字符数组
NEFORCE_CONSTEXPR20 basic_string & append(Iterator first, Iterator last)
追加迭代器范围
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const view_type &view, const size_type off, const size_type n) const noexcept
查找第一个不在字符串视图中的字符
NEFORCE_CONSTEXPR20 basic_string(const basic_string &other)
拷贝构造函数
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool starts_with(const_pointer str) const noexcept
检查是否以C风格字符串开头
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 pointer data() noexcept
获取数据指针
NEFORCE_CONSTEXPR20 void resize(const size_type n)
调整大小(默认填充0)
NEFORCE_CONSTEXPR20 void clear() noexcept
清空字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_not_of(const CharT *str, const size_type off, const size_type n) const noexcept
查找第一个不在指定字符数组中的字符
NEFORCE_CONSTEXPR20 basic_string & append(const basic_string &other)
追加另一个字符串
NEFORCE_CONSTEXPR20 basic_string(const basic_string &other, size_type position, size_type n)
从子串构造(指定长度)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type rfind(const basic_string &other, const size_type off=npos) const noexcept
从后向前查找子串
NEFORCE_CONSTEXPR20 basic_string(size_type n)
构造函数,指定大小
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_last_not_of(const view_type &view, const size_type off=npos) const noexcept
查找最后一个不在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type find_first_of(const view_type &view, const size_type off=0) const noexcept
查找第一个出现在字符串视图中的字符
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 view_type view(const size_type off, size_type count=npos) const noexcept
获取子串视图
_NEFORCE reverse_iterator< const_iterator > const_reverse_iterator
常量反向迭代器类型
Alloc allocator_type
分配器类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool ends_with(const_pointer str) const noexcept
检查是否以C风格字符串结尾
_NEFORCE reverse_iterator< iterator > reverse_iterator
反向迭代器类型
压缩对实现
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
NEFORCE_INLINE17 constexpr bool is_standard_layout_v
is_standard_layout的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_array_v
is_array的便捷变量模板
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 CharT to_uppercase(const CharT c) noexcept
将字符转换为大写
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 CharT to_lowercase(const CharT c) noexcept
将字符转换为小写
constexpr size_t char_traits_find_first_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找第一个出现在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_rfind(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
从后向前查找子序列
constexpr size_t char_traits_find_last_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找最后一个出现在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找最后一个不在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_rfind_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
从后向前查找单个字符
constexpr size_t char_traits_rfind_not_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
查找最后一个不等于指定字符的位置
constexpr int char_traits_compare(const char_traits_ptr_t< Traits > lhs, const size_t lh_size, const char_traits_ptr_t< Traits > rhs, const size_t rh_size) noexcept
比较两个字符序列(三路比较)
constexpr size_t char_traits_find(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
在字符序列中查找子序列
constexpr size_t char_traits_find_not_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
查找第一个不等于指定字符的位置
constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找第一个不在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_find_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
在字符序列中查找单个字符
constexpr bool char_traits_equal(const char_traits_ptr_t< Traits > lhs, const size_t lh_size, const char_traits_ptr_t< Traits > rhs, const size_t rh_size) noexcept
比较两个字符序列是否相等
NEFORCE_PURE_FUNCTION NEFORCE_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)))
返回两个值中的较小者
long long int64_t
64位有符号整数类型
int int32_t
32位有符号整数类型
#define NEFORCE_DEBUG_VERIFY(CON, MESG)
调试模式断言
NEFORCE_CONSTEXPR14 size_t FNV_hash_string(const CharT *str, const size_t len) noexcept
字符串类型的FNV哈希
NEFORCE_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
NEFORCE_INLINE17 constexpr bool is_iter_v
检查类型是否为迭代器
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
NEFORCE_NODISCARD constexpr normal_iterator< Iterator > operator+(iter_difference_t< normal_iterator< Iterator > > n, const normal_iterator< Iterator > &iter) noexcept
加法运算符
uint64_t size_t
无符号大小类型
int64_t ptrdiff_t
指针差类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
constexpr void iter_swap(Iterator1 a, Iterator2 b) noexcept(noexcept(_NEFORCE swap(*a, *b)))
交换迭代器指向的元素
void swap()=delete
删除无参数的swap重载
NEFORCE_INLINE17 constexpr bool is_allocator_v
is_allocator的便捷变量模板
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
NEFORCE_INLINE17 constexpr bool is_trivial_v
is_trivial的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_same_v
is_same的便捷变量模板
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
NEFORCE_CONSTEXPR20 Iterator2 uninitialized_copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制元素到未初始化内存
NEFORCE_CONSTEXPR20 pair< Iterator1, Iterator2 > uninitialized_copy_n(Iterator1 first, size_t count, Iterator2 result)
复制指定数量的元素到未初始化内存
标准分配器
字符串视图类型别名和实用函数
typename real_size< Alloc, difference_type >::type size_type
大小类型
static NEFORCE_NODISCARD constexpr bool eq(const char_type lhs, const char_type rhs) noexcept
相等比较
static constexpr char_type * assign(char_type *const str, const size_t count, const char_type chr) noexcept
将字符序列中的每个字符设置为指定值
static NEFORCE_NODISCARD constexpr int compare(const char_type *lhs, const char_type *rhs, size_t count) noexcept
比较两个字符序列
static constexpr char_type * move(char_type *dest, const char_type *srcs, const size_t count) noexcept
移动字符序列
static constexpr char_type * copy(char_type *dest, const char_type *srcs, const size_t count) noexcept
复制字符序列
static NEFORCE_NODISCARD constexpr size_t length(const char_type *str) noexcept
计算字符串长度
conditional_t< IsConst, typename container_type::const_pointer, typename container_type::pointer > pointer
指针类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 difference_type distance_to(const basic_string_iterator &other) const noexcept
计算距离操作
NEFORCE_CONSTEXPR20 void decrement() noexcept
递减操作
conditional_t< IsConst, typename container_type::const_reference, typename container_type::reference > reference
引用类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference operator[](difference_type n) const noexcept
下标访问操作符
contiguous_iterator_tag iterator_category
迭代器类别
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 const container_type * container() const noexcept
获取关联容器
typename container_type::size_type size_type
大小类型
typename container_type::value_type value_type
值类型
String container_type
容器类型
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 reference dereference() const noexcept
解引用操作
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 pointer base() const noexcept
获取底层指针
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool less_than(const basic_string_iterator &rhs) const noexcept
小于比较
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool equal(const basic_string_iterator &rhs) const noexcept
相等比较
NEFORCE_CONSTEXPR20 void increment() noexcept
递增操作
NEFORCE_CONSTEXPR20 void advance(difference_type off) noexcept
前进操作
typename container_type::difference_type difference_type
差值类型
压缩对主模板,使用EBCO优化
constexpr compressed_pair & get_base() noexcept
获取基类引用
连续迭代器标签
默认构造标签
通用接口,同时具备可比较和可哈希功能
NEFORCE_NODISCARD constexpr bool operator>=(const T &rhs) const noexcept(noexcept(!(derived()< rhs)))
大于等于比较运算符
NEFORCE_NODISCARD constexpr bool operator>(const T &rhs) const noexcept(noexcept(rhs< derived()))
大于比较运算符
NEFORCE_NODISCARD constexpr bool operator!=(const T &rhs) const noexcept(noexcept(!(*this==rhs)))
不等比较运算符
NEFORCE_NODISCARD constexpr bool operator<=(const T &rhs) const noexcept(noexcept(!(derived() > rhs)))
小于等于比较运算符
迭代器接口模板
未初始化内存操作