20 #include <string_view>
26 template<
class char_t,
class traits_t =
string_traits::traits<
char_t>>
32 template<
class string_traits_t>
35 using size_type =
typename string_traits_t::size_type;
36 static constexpr size_type nSBOSize =
37 sizeof(
typename string_traits_t::value_type) * string_traits_t::small_string_size();
38 static constexpr
bool bShrinkToFitWhenSmall = string_traits_t::shrink_to_fit_when_small();
39 static constexpr
bool bPreserveContents =
true;
41 static constexpr size_type growth_strategy(size_type nOldCapacity) noexcept
43 return nOldCapacity + nOldCapacity / 2;
47 (nSBOSize & (nSBOSize - 1)) == 0,
48 "The buffer size should be such that the final size of the structure is aligned");
51 template<
class char_t>
52 using ostream = std::basic_ostream<char_t>;
54 template<
class char_t>
55 using istream = std::basic_istream<char_t>;
61 template<
class char_t,
class traits_t>
81 template<
class char_t,
class traits_t>
84 template<
class _
char_t,
class _traits_t>
85 friend qx::details::istream<_char_t>& ::operator>>(
86 qx::details::istream<_char_t>& is,
90 using traits_type = traits_t;
91 using value_type =
typename traits_type::value_type;
92 using pointer =
typename traits_type::pointer;
93 using const_pointer =
typename traits_type::const_pointer;
94 using reference =
typename traits_type::reference;
95 using const_reference =
typename traits_type::const_reference;
96 using difference_type =
typename traits_type::difference_type;
97 using size_type =
typename traits_type::size_type;
98 using string_view = basic_string_view<value_type>;
99 using sstream_type = std::basic_stringstream<value_type>;
100 using views = std::vector<string_view>;
101 template<
class... args_t>
102 using format_string_type =
typename traits_type::template format_string<args_t...>;
104 static constexpr size_type npos = std::numeric_limits<size_type>::max();
116 basic_string(size_type nSymbols, value_type chSymbol) noexcept;
123 basic_string(const_pointer pszSource, size_type nSymbols) noexcept;
149 template<
class fwd_it_t>
150 basic_string(fwd_it_t itFirst, fwd_it_t itLast) noexcept;
157 template<range_of_t_c<
char_t>
string_t>
165 void assign(size_type nSymbols, value_type chSymbol) noexcept;
172 void assign(const_pointer pszSource, size_type nSymbols) noexcept;
178 void assign(const_pointer pszSource) noexcept;
198 template<
class fwd_it_t>
199 void assign(fwd_it_t itFirst, fwd_it_t itLast) noexcept;
206 template<range_of_t_c<
char_t>
string_t>
207 void assign(
const string_t& str) noexcept;
216 template<
class... args_t>
217 requires format_acceptable_args_c<char_t, args_t...>
218 void format(
const format_string_type<std::type_identity_t<args_t>...> sFormat, args_t&&... args) noexcept;
228 template<
class... args_t>
229 requires format_acceptable_args_c<char_t, args_t...>
231 const format_string_type<std::type_identity_t<args_t>...> sFormat,
232 args_t&&... args) noexcept;
241 template<
class... args_t>
242 requires format_acceptable_args_c<char_t, args_t...>
243 void append_format(
const format_string_type<std::type_identity_t<args_t>...> sFormat, args_t&&... args) noexcept;
252 template<
class... args_t>
253 requires format_acceptable_args_c<char_t, args_t...>
254 void vformat(string_view svFormat, args_t&&... args);
264 template<
class... args_t>
265 requires format_acceptable_args_c<char_t, args_t...>
275 template<
class... args_t>
276 requires format_acceptable_args_c<char_t, args_t...>
290 size_type
reserve(size_type nCapacity) noexcept;
300 void free() noexcept;
308 string_view
substr(size_type nPos, size_type nSymbols = npos) const noexcept;
324 value_type
front() const noexcept;
330 value_type
back() const noexcept;
337 size_type
length() const noexcept;
343 const_pointer
c_str() const noexcept;
349 size_type
capacity() const noexcept;
355 static constexpr size_type
max_size() noexcept;
369 std::optional<to_t>
to(const_pointer pszFormat =
nullptr) const noexcept;
378 size_type
copy(pointer pDest, size_type nCount, size_type nPos = 0) const noexcept;
385 template<class from_t>
386 void from(const from_t& data);
394 template<class from_t>
401 void append(value_type chSymbol) noexcept;
408 void append(const_pointer pszStr, size_type nStrSize = npos) noexcept;
422 template<class fwd_it_t>
423 void append(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
430 template<range_of_t_c<char_t> string_t>
431 void append(const string_t& sStr) noexcept;
439 size_type
insert(size_type nPos, value_type chSymbol) noexcept;
448 size_type
insert(size_type nPos, const_pointer pszWhat, size_type nSymbols = npos) noexcept;
466 template<class fwd_it_t>
467 size_type
insert(size_type nPos, fwd_it_t itWhatBegin, fwd_it_t itWhatEnd) noexcept;
476 template<range_of_t_c<char_t> string_t>
477 size_type
insert(size_type nPos, string_t sWhat) noexcept;
494 size_type
insert(
const_iterator itPos, const_pointer pszWhat, size_type nSymbols = npos) noexcept;
512 template<class fwd_it_t>
522 template<range_of_t_c<char_t> string_t>
529 void push_back(value_type chSymbol) noexcept;
535 void push_front(value_type chSymbol) noexcept;
554 void erase(size_type nPos) noexcept;
561 void erase(size_type nPos, size_type nSymbols) noexcept;
586 size_type
trim_left(value_type chSymbol) noexcept;
593 size_type
trim_left(const_pointer pszStr) noexcept;
601 size_type
trim_left(const_pointer pszStr, size_type nStrSize) noexcept;
617 template<class fwd_it_t>
618 size_type
trim_left(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
626 template<range_of_t_c<char_t> string_t>
627 size_type
trim_left(const string_t& sStr) noexcept;
640 size_type
trim_right(value_type chSymbol) noexcept;
647 size_type
trim_right(const_pointer pszStr) noexcept;
655 size_type
trim_right(const_pointer pszStr, size_type nStrSize) noexcept;
671 template<class fwd_it_t>
672 size_type
trim_right(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
680 template<range_of_t_c<char_t> string_t>
681 size_type
trim_right(const string_t& sStr) noexcept;
687 size_type
trim() noexcept;
694 size_type
trim(value_type chSymbol) noexcept;
701 size_type
trim(const_pointer pszStr) noexcept;
709 size_type
trim(const_pointer pszStr, size_type nStrSize) noexcept;
725 template<class fwd_it_t>
726 size_type
trim(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
734 template<range_of_t_c<char_t> string_t>
735 size_type
trim(const string_t& sStr) noexcept;
744 size_type
remove(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) noexcept;
755 const_pointer pszStr,
756 size_type nBegin = 0,
757 size_type nEnd = npos,
758 size_type nStrSize = npos) noexcept;
767 size_type
remove(const
basic_string& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
778 template<class fwd_it_t>
779 size_type
remove(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin = 0, size_type nEnd = npos) noexcept;
789 template<range_of_t_c<char_t> string_t>
790 size_type
remove(const string_t& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
805 bool remove_prefix(const_pointer pszStr, size_type nStrSize = npos) noexcept;
821 template<class fwd_it_t>
822 bool remove_prefix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
830 template<range_of_t_c<char_t> string_t>
846 bool remove_suffix(const_pointer pszStr, size_type nStrSize = npos) noexcept;
862 template<class fwd_it_t>
863 bool remove_suffix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
871 template<range_of_t_c<char_t> string_t>
881 size_type
remove_all(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) noexcept;
892 const_pointer pszStr,
893 size_type nBegin = 0,
894 size_type nEnd = npos,
895 size_type nStrSize = npos) noexcept;
915 template<class fwd_it_t>
916 size_type
remove_all(fwd_it_t itFirst, fwd_it_t itLast, size_type nBegin = 0, size_type nEnd = npos) noexcept;
926 template<range_of_t_c<char_t> string_t>
927 size_type
remove_all(const string_t& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
938 size_type
replace(size_type nBegin, size_type nSize, const_pointer pszReplace,
size_t nReplaceSize) noexcept;
949 template<class replace_string_t>
950 size_type
replace(size_type nBegin, size_type nSize, const replace_string_t& sReplace) noexcept;
962 template<class find_string_t, class replace_string_t>
964 const find_string_t& sFind,
965 const replace_string_t& sReplace,
966 size_type nBegin = 0,
967 size_type nEnd = npos) noexcept;
979 template<class find_string_t, class replace_string_t>
981 const find_string_t& sFind,
982 const replace_string_t& sReplace,
983 size_type nBegin = 0,
984 size_type nEnd = npos) noexcept;
995 int compare(value_type chSymbol) const noexcept;
1006 int compare(const_pointer pszStr) const noexcept;
1018 int compare(const_pointer pStr, size_type nStrSize) const noexcept;
1042 template<class fwd_it_t>
1043 int compare(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1055 template<range_of_t_c<char_t> string_t>
1056 int compare(const string_t& sStr) const noexcept;
1065 size_type
find(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1075 size_type
find(const_pointer pszWhat, size_type nBegin = 0, size_type nWhatSize = npos, size_type nEnd = npos)
1085 size_type
find(const
basic_string& sWhat, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1096 template<class fwd_it_t>
1097 size_type
find(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0, size_type nEnd = npos)
1108 template<range_of_t_c<char_t> string_t>
1109 size_type
find(string_t sWhat, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1119 size_type
rfind(value_type chSymbol, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1130 size_type
rfind(const_pointer pszWhat, size_type nBegin = npos, size_type nWhatSize = npos, size_type nEnd = 0)
1141 size_type
rfind(const
basic_string& sWhat, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1153 template<class fwd_it_t>
1154 size_type
rfind(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = npos, size_type nEnd = 0)
1166 template<range_of_t_c<char_t> string_t>
1167 size_type
rfind(string_t sWhat, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1175 size_type
find_first_of(value_type chSymbol, size_type nBegin = 0) const noexcept;
1184 size_type
find_first_of(const_pointer pszWhat, size_type nBegin, size_type nWhatSize) const noexcept;
1192 size_type
find_first_of(const_pointer pszWhat, size_type nBegin = 0) const noexcept;
1210 template<class fwd_it_t>
1211 size_type
find_first_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0) const noexcept;
1220 template<range_of_t_c<char_t> string_t>
1221 size_type
find_first_of(string_t sWhat, size_type nBegin = 0) const noexcept;
1229 size_type
find_last_of(value_type chSymbol, size_type nEnd = 0) const noexcept;
1238 size_type
find_last_of(const_pointer pszWhat, size_type nEnd, size_type nWhatSize) const noexcept;
1246 size_type
find_last_of(const_pointer pszWhat, size_type nEnd = 0) const noexcept;
1264 template<class fwd_it_t>
1265 size_type
find_last_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nEnd = 0) const noexcept;
1274 template<range_of_t_c<char_t> string_t>
1275 size_type
find_last_of(string_t sWhat, size_type nEnd = 0) const noexcept;
1283 size_type
find_first_not_of(value_type chSymbol, size_type nBegin = 0) const noexcept;
1292 size_type
find_first_not_of(const_pointer pszWhat, size_type nBegin, size_type nWhatSize) const noexcept;
1300 size_type
find_first_not_of(const_pointer pszWhat, size_type nBegin = 0) const noexcept;
1318 template<class fwd_it_t>
1319 size_type
find_first_not_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0) const noexcept;
1328 template<range_of_t_c<char_t> string_t>
1329 size_type
find_first_not_of(string_t sWhat, size_type nBegin = 0) const noexcept;
1337 size_type
find_last_not_of(value_type chSymbol, size_type nEnd = 0) const noexcept;
1346 size_type
find_last_not_of(const_pointer pszWhat, size_type nEnd, size_type nWhatSize) const noexcept;
1354 size_type
find_last_not_of(const_pointer pszWhat, size_type nEnd = 0) const noexcept;
1372 template<class fwd_it_t>
1373 size_type
find_last_not_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nEnd = 0) const noexcept;
1382 template<range_of_t_c<char_t> string_t>
1383 size_type
find_last_not_of(string_t sWhat, size_type nEnd = 0) const noexcept;
1390 views
split(const value_type chSeparator) const noexcept;
1398 views
split(const_pointer pszSeparator, size_type nSepLen = npos) const noexcept;
1414 template<class fwd_it_t>
1415 views
split(fwd_it_t itSepFirst, fwd_it_t itSepLast) const noexcept;
1423 template<range_of_t_c<char_t> string_t>
1424 views
split(const string_t& sSeparator) const noexcept;
1431 bool starts_with(value_type chSymbol) const noexcept;
1439 bool starts_with(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1455 template<class fwd_it_t>
1456 bool starts_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1464 template<range_of_t_c<char_t> string_t>
1465 bool starts_with(const string_t& sStr) const noexcept;
1472 bool ends_with(value_type chSymbol) const noexcept;
1480 bool ends_with(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1496 template<class fwd_it_t>
1497 bool ends_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1505 template<range_of_t_c<char_t> string_t>
1506 bool ends_with(const string_t& sStr) const noexcept;
1514 bool contains(value_type chSymbol) const noexcept;
1523 bool contains(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1541 template<class fwd_it_t>
1542 bool contains(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1551 template<range_of_t_c<char_t> string_t>
1552 bool contains(const string_t& sStr) const noexcept;
1554 basic_string& operator=(const_pointer pszSource) noexcept;
1557 template<range_of_t_c<char_t> string_t>
1558 basic_string& operator=(const string_t& sStr) noexcept;
1560 basic_string& operator+=(value_type chSymbol) noexcept;
1561 basic_string& operator+=(const_pointer pszSource) noexcept;
1563 template<range_of_t_c<char_t> string_t>
1564 basic_string& operator+=(const string_t& sStr) noexcept;
1566 bool operator==(value_type chSymbol) const noexcept;
1567 bool operator==(const_pointer pszSource) const noexcept;
1568 bool operator==(const
basic_string& sStr) const noexcept;
1569 template<range_of_t_c<char_t> string_t>
1570 bool operator==(const string_t& sStr) const noexcept;
1572 bool operator!=(value_type chSymbol) const noexcept;
1573 bool operator!=(const_pointer pszSource) const noexcept;
1574 bool operator!=(const
basic_string& sStr) const noexcept;
1575 template<range_of_t_c<char_t> string_t>
1576 bool operator!=(const string_t& sStr) const noexcept;
1578 bool operator<(value_type chSymbol) const noexcept;
1579 bool operator<(const_pointer pszSource) const noexcept;
1580 bool operator<(const
basic_string& sStr) const noexcept;
1581 template<range_of_t_c<char_t> string_t>
1582 bool operator<(const string_t& sStr) const noexcept;
1584 bool operator<=(value_type chSymbol) const noexcept;
1585 bool operator<=(const_pointer pszSource) const noexcept;
1586 bool operator<=(const
basic_string& sStr) const noexcept;
1587 template<range_of_t_c<char_t> string_t>
1588 bool operator<=(const string_t& sStr) const noexcept;
1590 bool operator>(value_type chSymbol) const noexcept;
1591 bool operator>(const_pointer pszSource) const noexcept;
1592 bool operator>(const
basic_string& sStr) const noexcept;
1593 template<range_of_t_c<char_t> string_t>
1594 bool operator>(const string_t& sStr) const noexcept;
1596 bool operator>=(value_type chSymbol) const noexcept;
1597 bool operator>=(const_pointer pszSource) const noexcept;
1598 bool operator>=(const
basic_string& sStr) const noexcept;
1599 template<range_of_t_c<char_t> string_t>
1600 bool operator>=(const string_t& sStr) const noexcept;
1602 reference operator[](size_type nSymbol) noexcept;
1603 const_reference operator[](size_type nSymbol) const noexcept;
1605 operator string_view() const noexcept;
1607 explicit operator
bool() const noexcept;
1616 bool _resize(size_type nSymbols) noexcept;
1624 template<class searcher_t>
1625 size_type _trim_left(const searcher_t& searcher) noexcept;
1633 template<class searcher_t>
1634 size_type _trim_right(const searcher_t& searcher) noexcept;
1642 template<class searcher_t>
1643 size_type _trim(const searcher_t& searcher) noexcept;
1653 template<class comparator_t>
1654 size_type _find(size_type nBegin, size_type nEnd, const comparator_t& comparator) const noexcept;
1664 template<class comparator_t>
1665 size_type _rfind(size_type nBegin, size_type nEnd, const comparator_t& comparator) const noexcept;
1677 template<class incrementer_t, class fwd_it_t>
1678 size_type _find_first_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin, const incrementer_t& incrementer)
1691 template<class incrementer_t, class fwd_it_t>
1692 size_type _find_last_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nEnd, const incrementer_t& incrementer)
1705 template<class incrementer_t, class fwd_it_t>
1706 size_type _find_first_not_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin, const incrementer_t& incrementer)
1719 template<class incrementer_t, class fwd_it_t>
1720 size_type _find_last_not_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nEnd, const incrementer_t& incrementer)
1729 template<class string_view_like_t>
1730 static size_type _get_string_view_like_size(const string_view_like_t& sValue) noexcept;
1738 template<class string_view_like_t>
1739 static const_pointer _get_string_view_like_data(const string_view_like_t& sValue) noexcept;
1742 sbo_bytes<details::string_sbo_traits<traits_t>> m_Data;
1751 #include <qx/containers/string/string.inl>
void push_back(value_type chSymbol) noexcept
Insert char in the end of the string.
void erase(iterator itFirst, iterator itLast) noexcept
Erase substring.
size_type find(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) const noexcept
Find substring.
bool remove_prefix(value_type chSymbol) noexcept
Remove string prefix if matches.
size_type remove_all(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) noexcept
Remove all occurrences of a substring in a string.
std::optional< to_t > to(const_pointer pszFormat=nullptr) const noexcept
Convert string to specified type.
int compare(value_type chSymbol) const noexcept
Performs a binary comparison of the characters.
size_type find_last_of(value_type chSymbol, size_type nEnd=0) const noexcept
Find last position of character.
void push_front(value_type chSymbol) noexcept
Insert char in the beginning of the string.
size_type capacity() const noexcept
Get allocated memory size (including null terminator)
value_type pop_back() noexcept
Erase last char and return it.
size_type copy(pointer pDest, size_type nCount, size_type nPos=0) const noexcept
Copies a substring [nPos, nPos + nCount) to character string pointed to by pDest.
views split(const value_type chSeparator) const noexcept
Split string by separator.
requires format_acceptable_args_c< char_t, args_t... > void append_format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args) noexcept
Append the formatted string to the current one.
size_type rfind(value_type chSymbol, size_type nBegin=npos, size_type nEnd=0) const noexcept
Find substring (reverse direction)
size_type length() const noexcept
Get string length.
void free() noexcept
Clear string and free allocated memory.
void from(const from_t &data)
Construct string from custom type.
size_type trim_right() noexcept
Trim the string to the right (whitespace characters)
requires format_acceptable_args_c< char_t, args_t... > void vformat(string_view svFormat, args_t &&... args)
Clear the string and format it with the format string and the args.
void assign(size_type nSymbols, value_type chSymbol) noexcept
Assign by filling.
size_type replace_all(const find_string_t &sFind, const replace_string_t &sReplace, size_type nBegin=0, size_type nEnd=npos) noexcept
Replace all occurrences of sFind with sReplace.
bool ends_with(value_type chSymbol) const noexcept
Check if current string ends with char.
void swap(basic_string &sOther) noexcept
Swap this str and other.
value_type pop_front() noexcept
Erase first char and return it.
void append(value_type chSymbol) noexcept
Append char.
size_type trim() noexcept
Trim the string to the both sides (whitespace characters)
void to_upper() noexcept
Convert string to uppercase.
void shrink_to_fit() noexcept
Fit allocated size to string's actual size.
static basic_string static_from(const from_t &data)
Construct string from custom type and get it.
size_type find_last_not_of(value_type chSymbol, size_type nEnd=0) const noexcept
Finds the last character not equal to chSymbol.
size_type trim_left() noexcept
Trim the string to the left (whitespace characters)
size_type reserve(size_type nCapacity) noexcept
Reserve memory for the string.
requires format_acceptable_args_c< char_t, args_t... > void append_vformat(string_view svFormat, args_t &&... args)
Append the formatted string to the current one.
string_view substr(size_type nPos, size_type nSymbols=npos) const noexcept
Get substring.
void to_lower() noexcept
Convert string to lowercase.
size_type insert(size_type nPos, value_type chSymbol) noexcept
Insert substring.
bool remove_suffix(value_type chSymbol) noexcept
Remove string suffix if matches.
const_pointer c_str() const noexcept
Get pointer to string zero terminated.
requires static format_acceptable_args_c< char_t, args_t... > basic_string static_format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args) noexcept
Create a string by formatting it with the format string and the args.
requires static format_acceptable_args_c< char_t, args_t... > basic_string static_vformat(string_view svFormat, args_t &&... args)
Create a string by formatting it with the format string and the args.
size_type remove(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) noexcept
Remove the first occurrence of a substring in a string.
static constexpr size_type max_size() noexcept
Get the theoretical maximum of string size.
bool starts_with(value_type chSymbol) const noexcept
Check if current string starts with char.
value_type front() const noexcept
Get first char of the string.
value_type back() const noexcept
Get last char of the string.
size_type replace(size_type nBegin, size_type nSize, const_pointer pszReplace, size_t nReplaceSize) noexcept
Replace a substring with a given string.
size_type find_first_of(value_type chSymbol, size_type nBegin=0) const noexcept
Find first position of character.
size_type find_first_not_of(value_type chSymbol, size_type nBegin=0) const noexcept
Finds the first character not equal to chSymbol.
requires format_acceptable_args_c< char_t, args_t... > void format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args) noexcept
Clear the string and format it with the format string and the args.
Const random access iterator type.
Non-const random access iterator type.
A type erased small buffer object that works with raw data.
requires(same_variadic_args_v< args_t... >) const expr auto coalesce(args_t &&... args)
Coalesce function, C# a ?? b analogue.
Check that tuple type contains T.