qb  2.0.0.0
C++17 Actor Framework
qb Issue Watch Star Fork Follow @isndev
Loading...
Searching...
No Matches
string.h
Go to the documentation of this file.
1
25
26#include <algorithm>
27#include <array>
28#include <cstring>
29#include <iostream>
30#include <limits>
32#include <string>
33#include <stdexcept>
34
35#ifndef QB_STRING_H_
36#define QB_STRING_H_
37
38namespace qb {
39
40namespace internal {
52template <std::size_t _Size, bool fill8 = (_Size <= std::numeric_limits<uint8_t>::max()),
53 bool fill16 = (_Size <= std::numeric_limits<uint16_t>::max())>
54struct best_size {
55 using type = std::size_t;
56};
57
61template <std::size_t _Size>
63 using type = uint8_t;
64};
65
69template <std::size_t _Size>
71 using type = uint16_t;
72};
73} // namespace internal
74
85template <std::size_t _Size = 30>
86class string : public std::array<char, _Size + 1> {
87 static_assert(_Size > 0, "String size must be greater than 0");
88
89 using base_t = std::array<char, _Size + 1>;
90 using size_type = typename internal::best_size<_Size + 1>::type;
91
92public:
93 // Type aliases for compatibility with std::string
94 using value_type = char;
95 using reference = char&;
96 using const_reference = const char&;
97 using pointer = char*;
98 using const_pointer = const char*;
99 using iterator = typename base_t::iterator;
100 using const_iterator = typename base_t::const_iterator;
101 using reverse_iterator = typename base_t::reverse_iterator;
102 using const_reverse_iterator = typename base_t::const_reverse_iterator;
103 using difference_type = typename base_t::difference_type;
104
105 static constexpr std::size_t npos = std::numeric_limits<std::size_t>::max();
106
107private:
108 size_type _size = 0;
109
110public:
116 constexpr string() noexcept
117 : base_t{'\0'} {}
118
125 template <std::size_t N>
126 constexpr string(const char (&str)[N]) noexcept {
127 assign(str, N - 1);
128 }
129
136 template <typename T>
137 string(T const &rhs) noexcept {
138 assign(rhs);
139 }
140
147 string(const char* str, std::size_t size) noexcept {
148 assign(str, size);
149 }
150
156 string(const char* str) noexcept {
157 assign(str);
158 }
159
166 string(std::size_t count, char ch) noexcept {
167 _size = static_cast<size_type>(std::min(count, static_cast<std::size_t>(_Size)));
168 std::fill_n(base_t::data(), _size, ch);
169 base_t::data()[_size] = '\0';
170 }
171
175 string(const string& other) noexcept = default;
176
180 string(string&& other) noexcept = default;
181
185 string& operator=(const string& other) noexcept = default;
186
190 string& operator=(string&& other) noexcept = default;
191
199 string &
200 assign(char const *rhs, std::size_t size) noexcept {
201 _size = static_cast<size_type>(std::min(size, static_cast<std::size_t>(_Size)));
202
203 std::memcpy(base_t::data(), rhs, _size);
204 base_t::data()[_size] = '\0';
205
206 return *this;
207 }
208
216 template <std::size_t N>
217 constexpr string &
218 assign(const char (&str)[N]) noexcept {
219 return assign(str, N - 1);
220 }
221
229 template <typename T>
230 string &
231 assign(T const &rhs) noexcept {
232 return assign(rhs.data(), rhs.size());
233 }
234
241 string &
242 assign(char const *rhs) noexcept {
243 return assign(rhs, std::strlen(rhs));
244 }
245
253 string &
254 assign(std::size_t count, char ch) noexcept {
255 _size = static_cast<size_type>(std::min(count, static_cast<std::size_t>(_Size)));
256 std::fill_n(base_t::data(), _size, ch);
257 base_t::data()[_size] = '\0';
258 return *this;
259 }
260
268 template <std::size_t N>
269 constexpr string &
270 operator=(const char (&str)[N]) noexcept {
271 return assign(str, N - 1);
272 }
273
281 template <typename T>
282 string &
283 operator=(T const &rhs) noexcept {
284 return assign(rhs);
285 }
286
293 string &
294 operator=(char const *rhs) noexcept {
295 return assign(rhs);
296 }
297
304 string &
305 operator=(char ch) noexcept {
306 return assign(1, ch);
307 }
308
314 operator std::string() const noexcept {
315 return {base_t::data(), _size};
316 }
317
323 operator std::string_view() const noexcept {
324 return {base_t::data(), _size};
325 }
326
327 // Element access
335 reference at(std::size_t pos) {
336 if (pos >= _size) {
337 throw std::out_of_range("qb::string::at: index out of range");
338 }
339 return base_t::data()[pos];
340 }
341
349 const_reference at(std::size_t pos) const {
350 if (pos >= _size) {
351 throw std::out_of_range("qb::string::at: index out of range");
352 }
353 return base_t::data()[pos];
354 }
355
362 reference operator[](std::size_t pos) noexcept {
363 return base_t::data()[pos];
364 }
365
372 const_reference operator[](std::size_t pos) const noexcept {
373 return base_t::data()[pos];
374 }
375
381 reference front() noexcept {
382 return base_t::data()[0];
383 }
384
390 const_reference front() const noexcept {
391 return base_t::data()[0];
392 }
393
399 reference back() noexcept {
400 return base_t::data()[_size - 1];
401 }
402
408 const_reference back() const noexcept {
409 return base_t::data()[_size - 1];
410 }
411
417 pointer data() noexcept {
418 return base_t::data();
419 }
420
426 const_pointer data() const noexcept {
427 return base_t::data();
428 }
429
435 [[nodiscard]] const_pointer c_str() const noexcept {
436 return base_t::data();
437 }
438
439 // Iterators
445 iterator end() noexcept {
446 return base_t::begin() + _size;
447 }
448
454 const_iterator end() const noexcept {
455 return base_t::begin() + _size;
456 }
457
463 const_iterator cend() const noexcept {
464 return base_t::cbegin() + _size;
465 }
466
472 reverse_iterator rbegin() noexcept {
473 return std::reverse_iterator(end());
474 }
475
481 const_reverse_iterator rbegin() const noexcept {
482 return std::reverse_iterator(end());
483 }
484
490 const_reverse_iterator crbegin() const noexcept {
491 return std::reverse_iterator(cend());
492 }
493
494 // Capacity
500 [[nodiscard]] constexpr bool empty() const noexcept {
501 return _size == 0;
502 }
503
509 [[nodiscard]] constexpr std::size_t size() const noexcept {
510 return _size;
511 }
512
518 [[nodiscard]] constexpr std::size_t length() const noexcept {
519 return _size;
520 }
521
527 [[nodiscard]] constexpr std::size_t max_size() const noexcept {
528 return _Size;
529 }
530
536 [[nodiscard]] constexpr std::size_t capacity() const noexcept {
537 return _Size;
538 }
539
540 // Operations
546 void clear() noexcept {
547 *base_t::begin() = '\0';
548 _size = 0;
549 }
550
557 void resize(std::size_t count, char ch = '\0') noexcept {
558 count = std::min(count, static_cast<std::size_t>(_Size));
559
560 if (count > _size) {
561 std::fill(base_t::data() + _size, base_t::data() + count, ch);
562 }
563
564 _size = static_cast<size_type>(count);
565 base_t::data()[_size] = '\0';
566 }
567
573 void swap(string& other) noexcept {
574 base_t temp_data = *this;
575 size_type temp_size = _size;
576
577 *this = other;
578 _size = other._size;
579
580 other = temp_data;
581 other._size = temp_size;
582 }
583
584 // String operations
592 string substr(std::size_t pos = 0, std::size_t len = npos) const {
593 if (pos > _size) {
594 throw std::out_of_range("qb::string::substr: position out of range");
595 }
596
597 std::size_t actual_len = std::min(len, _size - pos);
598 string result;
599 result.assign(base_t::data() + pos, actual_len);
600 return result;
601 }
602
609 int compare(const string& str) const noexcept {
610 return std::strcmp(base_t::data(), str.c_str());
611 }
612
619 int compare(const char* str) const noexcept {
620 return std::strcmp(base_t::data(), str);
621 }
622
631 int compare(std::size_t pos, std::size_t len, const string& str) const {
632 return substr(pos, len).compare(str);
633 }
634
635 // Search operations
643 std::size_t find(const string& str, std::size_t pos = 0) const noexcept {
644 return find(str.c_str(), pos);
645 }
646
654 std::size_t find(const char* str, std::size_t pos = 0) const noexcept {
655 if (pos >= _size) return npos;
656
657 const char* result = std::strstr(base_t::data() + pos, str);
658 return result ? static_cast<std::size_t>(result - base_t::data()) : npos;
659 }
660
668 std::size_t find(char ch, std::size_t pos = 0) const noexcept {
669 if (pos >= _size) return npos;
670
671 const char* result = std::strchr(base_t::data() + pos, ch);
672 return (result && result < base_t::data() + _size) ?
673 static_cast<std::size_t>(result - base_t::data()) : npos;
674 }
675
683 std::size_t rfind(const char* str, std::size_t pos = npos) const noexcept {
684 std::size_t str_len = std::strlen(str);
685 if (str_len > _size) return npos;
686
687 std::size_t start = std::min(pos, _size - str_len);
688
689 for (std::size_t i = start + 1; i > 0; --i) {
690 if (std::strncmp(base_t::data() + i - 1, str, str_len) == 0) {
691 return i - 1;
692 }
693 }
694 return npos;
695 }
696
704 std::size_t rfind(char ch, std::size_t pos = npos) const noexcept {
705 if (_size == 0) return npos;
706
707 std::size_t start = std::min(pos, static_cast<std::size_t>(_size - 1));
708
709 for (std::size_t i = start + 1; i > 0; --i) {
710 if (base_t::data()[i - 1] == ch) {
711 return i - 1;
712 }
713 }
714 return npos;
715 }
716
717 // Modifiers
724 string& append(const string& str) noexcept {
725 return append(str.c_str(), str.size());
726 }
727
734 string& append(const char* str) noexcept {
735 return append(str, std::strlen(str));
736 }
737
745 string& append(const char* str, std::size_t len) noexcept {
746 std::size_t new_size = std::min(_size + len, static_cast<std::size_t>(_Size));
747 std::size_t actual_len = new_size - _size;
748
749 std::memcpy(base_t::data() + _size, str, actual_len);
750 _size = static_cast<size_type>(new_size);
751 base_t::data()[_size] = '\0';
752
753 return *this;
754 }
755
762 string& append(char ch) noexcept {
763 return append(1, ch);
764 }
765
773 string& append(std::size_t count, char ch) noexcept {
774 std::size_t new_size = std::min(_size + count, static_cast<std::size_t>(_Size));
775 std::size_t actual_count = new_size - _size;
776
777 std::fill_n(base_t::data() + _size, actual_count, ch);
778 _size = static_cast<size_type>(new_size);
779 base_t::data()[_size] = '\0';
780
781 return *this;
782 }
783
789 void push_back(char ch) noexcept {
790 if (_size < _Size) {
791 base_t::data()[_size] = ch;
792 ++_size;
793 base_t::data()[_size] = '\0';
794 }
795 }
796
800 void pop_back() noexcept {
801 if (_size > 0) {
802 --_size;
803 base_t::data()[_size] = '\0';
804 }
805 }
806
813 string& operator+=(const string& str) noexcept {
814 return append(str);
815 }
816
823 string& operator+=(const char* str) noexcept {
824 return append(str);
825 }
826
833 string& operator+=(char ch) noexcept {
834 push_back(ch);
835 return *this;
836 }
837
838 // C++20 features
845 bool starts_with(const char* prefix) const noexcept {
846 std::size_t prefix_len = std::strlen(prefix);
847 return _size >= prefix_len && std::strncmp(base_t::data(), prefix, prefix_len) == 0;
848 }
849
856 bool starts_with(const string& prefix) const noexcept {
857 return starts_with(prefix.c_str());
858 }
859
866 bool starts_with(char ch) const noexcept {
867 return _size > 0 && base_t::data()[0] == ch;
868 }
869
876 bool ends_with(const char* suffix) const noexcept {
877 std::size_t suffix_len = std::strlen(suffix);
878 return _size >= suffix_len &&
879 std::strncmp(base_t::data() + _size - suffix_len, suffix, suffix_len) == 0;
880 }
881
888 bool ends_with(const string& suffix) const noexcept {
889 return ends_with(suffix.c_str());
890 }
891
898 bool ends_with(char ch) const noexcept {
899 return _size > 0 && base_t::data()[_size - 1] == ch;
900 }
901
908 bool contains(const char* str) const noexcept {
909 return find(str) != npos;
910 }
911
918 bool contains(const string& str) const noexcept {
919 return find(str) != npos;
920 }
921
928 bool contains(char ch) const noexcept {
929 return find(ch) != npos;
930 }
931
932 // Comparison operators
940 template <typename T>
941 bool operator==(T const &rhs) const noexcept {
942 return rhs == base_t::data();
943 }
944
951 bool operator==(char const *rhs) const noexcept {
952 return std::strcmp(base_t::data(), rhs) == 0;
953 }
954
961 bool operator==(const string& rhs) const noexcept {
962 return _size == rhs._size && std::strcmp(base_t::data(), rhs.c_str()) == 0;
963 }
964
971 bool operator!=(const string& rhs) const noexcept {
972 return !(*this == rhs);
973 }
974
981 bool operator!=(const char* rhs) const noexcept {
982 return !(*this == rhs);
983 }
984
991 bool operator<(const string& rhs) const noexcept {
992 return compare(rhs) < 0;
993 }
994
1001 bool operator<(const char* rhs) const noexcept {
1002 return compare(rhs) < 0;
1003 }
1004
1011 bool operator>(const string& rhs) const noexcept {
1012 return compare(rhs) > 0;
1013 }
1014
1021 bool operator>(const char* rhs) const noexcept {
1022 return compare(rhs) > 0;
1023 }
1024
1031 bool operator<=(const string& rhs) const noexcept {
1032 return compare(rhs) <= 0;
1033 }
1034
1041 bool operator<=(const char* rhs) const noexcept {
1042 return compare(rhs) <= 0;
1043 }
1044
1051 bool operator>=(const string& rhs) const noexcept {
1052 return compare(rhs) >= 0;
1053 }
1054
1061 bool operator>=(const char* rhs) const noexcept {
1062 return compare(rhs) >= 0;
1063 }
1064};
1065
1066// Non-member functions
1067
1077template <std::size_t _Size1, std::size_t _Size2>
1078string<std::max(_Size1, _Size2)> operator+(const string<_Size1>& lhs, const string<_Size2>& rhs) noexcept {
1079 string<std::max(_Size1, _Size2)> result(lhs);
1080 result.append(rhs);
1081 return result;
1082}
1083
1092template <std::size_t _Size>
1093string<_Size> operator+(const string<_Size>& lhs, const char* rhs) noexcept {
1094 string<_Size> result(lhs);
1095 result.append(rhs);
1096 return result;
1097}
1098
1107template <std::size_t _Size>
1108string<_Size> operator+(const char* lhs, const string<_Size>& rhs) noexcept {
1109 string<_Size> result(lhs);
1110 result.append(rhs);
1111 return result;
1112}
1113
1122template <std::size_t _Size>
1123string<_Size> operator+(const string<_Size>& lhs, char rhs) noexcept {
1124 string<_Size> result(lhs);
1125 result.push_back(rhs);
1126 return result;
1127}
1128
1137template <std::size_t _Size>
1138string<_Size> operator+(char lhs, const string<_Size>& rhs) noexcept {
1139 string<_Size> result(1, lhs);
1140 result.append(rhs);
1141 return result;
1142}
1143
1151template <std::size_t _Size>
1152void swap(string<_Size>& lhs, string<_Size>& rhs) noexcept {
1153 lhs.swap(rhs);
1154}
1155
1164template <std::size_t _Size>
1165std::ostream &
1166operator<<(std::ostream &os, qb::string<_Size> const &str) noexcept {
1167 os << str.c_str();
1168 return os;
1169}
1170
1179template <std::size_t _Size>
1180std::istream &
1181operator>>(std::istream &is, qb::string<_Size> &str) noexcept {
1182 std::string temp;
1183 is >> temp;
1184 str = temp;
1185 return is;
1186}
1187
1188// Equality operators for reverse comparisons
1189template <std::size_t _Size>
1190bool operator==(const char* lhs, const string<_Size>& rhs) noexcept {
1191 return rhs == lhs;
1192}
1193
1194template <std::size_t _Size>
1195bool operator!=(const char* lhs, const string<_Size>& rhs) noexcept {
1196 return rhs != lhs;
1197}
1198
1199} // namespace qb
1200
1201#endif // QB_STRING_H_
Platform, compiler, and C++ feature detection macros for the QB Framework.
Fixed-size string with optimized storage.
Definition string.h:86
void pop_back() noexcept
Remove last character.
Definition string.h:800
const_reverse_iterator crbegin() const noexcept
Get const reverse iterator to the beginning of the string.
Definition string.h:490
reference back() noexcept
Access last character.
Definition string.h:399
bool operator!=(const char *rhs) const noexcept
Inequality comparison with C-style string.
Definition string.h:981
reference at(std::size_t pos)
Access character at index with bounds checking.
Definition string.h:335
string(const string &other) noexcept=default
Copy constructor.
reverse_iterator rbegin() noexcept
Get reverse iterator to the beginning of the string.
Definition string.h:472
bool ends_with(const string &suffix) const noexcept
Check if string ends with given suffix.
Definition string.h:888
bool contains(const char *str) const noexcept
Check if string contains given substring.
Definition string.h:908
string(T const &rhs) noexcept
Constructor from string-like object.
Definition string.h:137
string & operator=(char const *rhs) noexcept
Assignment operator for C-style strings.
Definition string.h:294
string(const char *str) noexcept
Constructor from C-style string.
Definition string.h:156
constexpr std::size_t capacity() const noexcept
Get the capacity.
Definition string.h:536
string & append(const char *str, std::size_t len) noexcept
Append C-style string with length.
Definition string.h:745
bool operator>(const char *rhs) const noexcept
Greater than comparison with C-style string.
Definition string.h:1021
string & append(std::size_t count, char ch) noexcept
Append multiple characters.
Definition string.h:773
reference front() noexcept
Access first character.
Definition string.h:381
const_reference at(std::size_t pos) const
Access character at index with bounds checking (const version)
Definition string.h:349
const_reference operator[](std::size_t pos) const noexcept
Access character at index (no bounds checking, const version)
Definition string.h:372
string & operator+=(const char *str) noexcept
Append operator for C-style string.
Definition string.h:823
string & assign(T const &rhs) noexcept
Assign from string-like object.
Definition string.h:231
std::size_t find(const string &str, std::size_t pos=0) const noexcept
Find substring.
Definition string.h:643
constexpr string() noexcept
Default constructor.
Definition string.h:116
void push_back(char ch) noexcept
Add character to end.
Definition string.h:789
bool starts_with(char ch) const noexcept
Check if string starts with given character.
Definition string.h:866
std::size_t rfind(char ch, std::size_t pos=npos) const noexcept
Find last occurrence of character.
Definition string.h:704
bool operator>(const string &rhs) const noexcept
Greater than comparison.
Definition string.h:1011
bool operator<=(const char *rhs) const noexcept
Less than or equal comparison with C-style string.
Definition string.h:1041
string & operator=(string &&other) noexcept=default
Move assignment operator.
bool contains(char ch) const noexcept
Check if string contains given character.
Definition string.h:928
const_reference front() const noexcept
Access first character (const version)
Definition string.h:390
bool operator<(const string &rhs) const noexcept
Less than comparison.
Definition string.h:991
bool operator!=(const string &rhs) const noexcept
Inequality comparison.
Definition string.h:971
string & assign(std::size_t count, char ch) noexcept
Assign with fill.
Definition string.h:254
void resize(std::size_t count, char ch='\0') noexcept
Resize the string.
Definition string.h:557
const_pointer data() const noexcept
Get pointer to underlying data (const version)
Definition string.h:426
bool operator<=(const string &rhs) const noexcept
Less than or equal comparison.
Definition string.h:1031
constexpr string & operator=(const char(&str)[N]) noexcept
Assignment operator for C-style string literals.
Definition string.h:270
const_reference back() const noexcept
Access last character (const version)
Definition string.h:408
string(string &&other) noexcept=default
Move constructor.
const_iterator end() const noexcept
Get const iterator to the end of the string.
Definition string.h:454
string & operator+=(char ch) noexcept
Append operator for character.
Definition string.h:833
bool ends_with(char ch) const noexcept
Check if string ends with given character.
Definition string.h:898
string & append(const string &str) noexcept
Append string.
Definition string.h:724
bool operator==(const string &rhs) const noexcept
Equality comparison with another qb::string.
Definition string.h:961
string & operator+=(const string &str) noexcept
Append operator.
Definition string.h:813
constexpr std::size_t length() const noexcept
Get the string length (alias for size())
Definition string.h:518
string & append(char ch) noexcept
Append character.
Definition string.h:762
bool contains(const string &str) const noexcept
Check if string contains given substring.
Definition string.h:918
iterator end() noexcept
Get iterator to the end of the string.
Definition string.h:445
string(std::size_t count, char ch) noexcept
Fill constructor.
Definition string.h:166
std::size_t rfind(const char *str, std::size_t pos=npos) const noexcept
Find last occurrence of substring.
Definition string.h:683
constexpr string & assign(const char(&str)[N]) noexcept
Assign from C-style string literal.
Definition string.h:218
string & operator=(T const &rhs) noexcept
Assignment operator for string-like objects.
Definition string.h:283
string & assign(char const *rhs) noexcept
Assign from C-style string.
Definition string.h:242
std::size_t find(const char *str, std::size_t pos=0) const noexcept
Find C-style string.
Definition string.h:654
bool ends_with(const char *suffix) const noexcept
Check if string ends with given suffix.
Definition string.h:876
bool starts_with(const string &prefix) const noexcept
Check if string starts with given prefix.
Definition string.h:856
int compare(const char *str) const noexcept
Compare with C-style string.
Definition string.h:619
const_reverse_iterator rbegin() const noexcept
Get const reverse iterator to the beginning of the string.
Definition string.h:481
pointer data() noexcept
Get pointer to underlying data.
Definition string.h:417
bool operator==(T const &rhs) const noexcept
Equality comparison with string-like object.
Definition string.h:941
std::size_t find(char ch, std::size_t pos=0) const noexcept
Find character.
Definition string.h:668
bool operator<(const char *rhs) const noexcept
Less than comparison with C-style string.
Definition string.h:1001
int compare(std::size_t pos, std::size_t len, const string &str) const
Compare substring with another string.
Definition string.h:631
const_iterator cend() const noexcept
Get const iterator to the end of the string.
Definition string.h:463
constexpr bool empty() const noexcept
Check if the string is empty.
Definition string.h:500
bool operator>=(const string &rhs) const noexcept
Greater than or equal comparison.
Definition string.h:1051
bool operator>=(const char *rhs) const noexcept
Greater than or equal comparison with C-style string.
Definition string.h:1061
bool starts_with(const char *prefix) const noexcept
Check if string starts with given prefix.
Definition string.h:845
const_pointer c_str() const noexcept
Get C-style string representation.
Definition string.h:435
constexpr string(const char(&str)[N]) noexcept
Constructor from C-style string literal.
Definition string.h:126
string & operator=(const string &other) noexcept=default
Copy assignment operator.
void clear() noexcept
Clear the string.
Definition string.h:546
int compare(const string &str) const noexcept
Compare with another string.
Definition string.h:609
string & assign(char const *rhs, std::size_t size) noexcept
Assign from C-style string and size.
Definition string.h:200
constexpr std::size_t max_size() const noexcept
Get the maximum possible size.
Definition string.h:527
void swap(string &other) noexcept
Swap contents with another string.
Definition string.h:573
bool operator==(char const *rhs) const noexcept
Equality comparison with C-style string.
Definition string.h:951
string & append(const char *str) noexcept
Append C-style string.
Definition string.h:734
constexpr std::size_t size() const noexcept
Get the string length.
Definition string.h:509
string substr(std::size_t pos=0, std::size_t len=npos) const
Extract substring.
Definition string.h:592
string(const char *str, std::size_t size) noexcept
Constructor from C-style string and size.
Definition string.h:147
string & operator=(char ch) noexcept
Assignment operator for single character.
Definition string.h:305
reference operator[](std::size_t pos) noexcept
Access character at index (no bounds checking)
Definition string.h:362
std::ostream & operator<<(std::ostream &os, qb::Actor const &actor)
Stream output operator for Actor objects.
json::string_t string
JSON string type from nlohmann::json.
Definition json.h:67
std::istream & operator>>(std::istream &is, qb::string< _Size > &str) noexcept
Input stream operator for qb::string.
Definition string.h:1181
string< std::max(_Size1, _Size2)> operator+(const string< _Size1 > &lhs, const string< _Size2 > &rhs) noexcept
Concatenation operator.
Definition string.h:1078
void swap(string< _Size > &lhs, string< _Size > &rhs) noexcept
Swap function for strings.
Definition string.h:1152
Determines the optimal integer type for size storage based on max capacity.
Definition string.h:54