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();
41 (nSBOSize & (nSBOSize - 1)) == 0,
42 "The buffer size should be such that the final size of the structure is aligned");
45 template<
class char_t>
46 using ostream = std::basic_ostream<char_t>;
48 template<
class char_t>
49 using istream = std::basic_istream<char_t>;
55 template<
class char_t,
class traits_t>
75 template<
class char_t,
class traits_t>
78 template<
class _
char_t,
class _traits_t>
79 friend qx::details::istream<_char_t>& ::operator>>(
80 qx::details::istream<_char_t>& is,
84 using traits_type = traits_t;
85 using value_type =
typename traits_type::value_type;
86 using pointer =
typename traits_type::pointer;
87 using const_pointer =
typename traits_type::const_pointer;
88 using reference =
typename traits_type::reference;
89 using const_reference =
typename traits_type::const_reference;
90 using difference_type =
typename traits_type::difference_type;
91 using size_type =
typename traits_type::size_type;
92 using string_view = std::basic_string_view<value_type>;
93 using sstream_type = std::basic_stringstream<value_type>;
94 using views = std::vector<string_view>;
95 template<
class... args_t>
96 using format_string_type =
typename traits_type::template format_string<args_t...>;
98 static constexpr size_type npos = std::numeric_limits<size_type>::max();
110 basic_string(size_type nSymbols, value_type chSymbol) noexcept;
117 basic_string(const_pointer pszSource, size_type nSymbols) noexcept;
143 template<
class fwd_it_t>
144 basic_string(fwd_it_t itFirst, fwd_it_t itLast) noexcept;
151 template<range_of_t_c<
char_t>
string_t>
159 void assign(size_type nSymbols, value_type chSymbol) noexcept;
166 void assign(const_pointer pszSource, size_type nSymbols) noexcept;
172 void assign(const_pointer pszSource) noexcept;
192 template<
class fwd_it_t>
193 void assign(fwd_it_t itFirst, fwd_it_t itLast) noexcept;
200 template<range_of_t_c<
char_t>
string_t>
201 void assign(
const string_t& str) noexcept;
210 template<
class... args_t>
211 requires format_acceptable_args_c<char_t, args_t...>
212 void format(
const format_string_type<std::type_identity_t<args_t>...> sFormat, args_t&&... args);
222 template<
class... args_t>
223 requires format_acceptable_args_c<char_t, args_t...>
225 const format_string_type<std::type_identity_t<args_t>...> sFormat,
235 template<
class... args_t>
236 requires format_acceptable_args_c<char_t, args_t...>
237 void append_format(
const format_string_type<std::type_identity_t<args_t>...> sFormat, args_t&&... args);
246 template<
class... args_t>
247 requires format_acceptable_args_c<char_t, args_t...>
248 void vformat(string_view svFormat, args_t&&... args);
258 template<
class... args_t>
259 requires format_acceptable_args_c<char_t, args_t...>
269 template<
class... args_t>
270 requires format_acceptable_args_c<char_t, args_t...>
284 size_type
reserve(size_type nCapacity) noexcept;
294 void free() noexcept;
302 string_view
substr(size_type nPos, size_type nSymbols = npos) const noexcept;
318 value_type
front() const noexcept;
324 value_type
back() const noexcept;
331 size_type
length() const noexcept;
337 const_pointer
c_str() const noexcept;
343 size_type
capacity() const noexcept;
349 static constexpr size_type
max_size() noexcept;
363 std::optional<to_t>
to(const_pointer pszFormat =
nullptr) const noexcept;
372 size_type
copy(pointer pDest, size_type nCount, size_type nPos = 0) const noexcept;
379 template<class from_t>
380 void from(const from_t& data);
388 template<class from_t>
395 void append(value_type chSymbol) noexcept;
402 void append(const_pointer pszStr, size_type nStrSize = npos) noexcept;
416 template<class fwd_it_t>
417 void append(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
424 template<range_of_t_c<char_t> string_t>
425 void append(const string_t& sStr) noexcept;
433 size_type
insert(size_type nPos, value_type chSymbol) noexcept;
442 size_type
insert(size_type nPos, const_pointer pszWhat, size_type nSymbols = npos) noexcept;
460 template<class fwd_it_t>
461 size_type
insert(size_type nPos, fwd_it_t itWhatBegin, fwd_it_t itWhatEnd) noexcept;
470 template<range_of_t_c<char_t> string_t>
471 size_type
insert(size_type nPos, string_t sWhat) noexcept;
488 size_type
insert(
const_iterator itPos, const_pointer pszWhat, size_type nSymbols = npos) noexcept;
506 template<class fwd_it_t>
516 template<range_of_t_c<char_t> string_t>
523 void push_back(value_type chSymbol) noexcept;
529 void push_front(value_type chSymbol) noexcept;
548 void erase(size_type nPos) noexcept;
555 void erase(size_type nPos, size_type nSymbols) noexcept;
580 size_type
trim_left(value_type chSymbol) noexcept;
587 size_type
trim_left(const_pointer pszStr) noexcept;
595 size_type
trim_left(const_pointer pszStr, size_type nStrSize) noexcept;
611 template<class fwd_it_t>
612 size_type
trim_left(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
620 template<range_of_t_c<char_t> string_t>
621 size_type
trim_left(const string_t& sStr) noexcept;
634 size_type
trim_right(value_type chSymbol) noexcept;
641 size_type
trim_right(const_pointer pszStr) noexcept;
649 size_type
trim_right(const_pointer pszStr, size_type nStrSize) noexcept;
665 template<class fwd_it_t>
666 size_type
trim_right(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
674 template<range_of_t_c<char_t> string_t>
675 size_type
trim_right(const string_t& sStr) noexcept;
681 size_type
trim() noexcept;
688 size_type
trim(value_type chSymbol) noexcept;
695 size_type
trim(const_pointer pszStr) noexcept;
703 size_type
trim(const_pointer pszStr, size_type nStrSize) noexcept;
719 template<class fwd_it_t>
720 size_type
trim(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
728 template<range_of_t_c<char_t> string_t>
729 size_type
trim(const string_t& sStr) noexcept;
738 size_type
remove(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) noexcept;
749 const_pointer pszStr,
750 size_type nBegin = 0,
751 size_type nEnd = npos,
752 size_type nStrSize = npos) noexcept;
761 size_type
remove(const
basic_string& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
772 template<class fwd_it_t>
773 size_type
remove(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin = 0, size_type nEnd = npos) noexcept;
783 template<range_of_t_c<char_t> string_t>
784 size_type
remove(const string_t& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
799 bool remove_prefix(const_pointer pszStr, size_type nStrSize = npos) noexcept;
815 template<class fwd_it_t>
816 bool remove_prefix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
824 template<range_of_t_c<char_t> string_t>
840 bool remove_suffix(const_pointer pszStr, size_type nStrSize = npos) noexcept;
856 template<class fwd_it_t>
857 bool remove_suffix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept;
865 template<range_of_t_c<char_t> string_t>
875 size_type
remove_all(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) noexcept;
886 const_pointer pszStr,
887 size_type nBegin = 0,
888 size_type nEnd = npos,
889 size_type nStrSize = npos) noexcept;
909 template<class fwd_it_t>
910 size_type
remove_all(fwd_it_t itFirst, fwd_it_t itLast, size_type nBegin = 0, size_type nEnd = npos) noexcept;
920 template<range_of_t_c<char_t> string_t>
921 size_type
remove_all(const string_t& sStr, size_type nBegin = 0, size_type nEnd = npos) noexcept;
932 size_type
replace(size_type nBegin, size_type nSize, const_pointer pszReplace,
size_t nReplaceSize) noexcept;
943 template<class replace_string_t>
944 size_type
replace(size_type nBegin, size_type nSize, const replace_string_t& sReplace) noexcept;
956 template<class find_string_t, class replace_string_t>
958 const find_string_t& sFind,
959 const replace_string_t& sReplace,
960 size_type nBegin = 0,
961 size_type nEnd = npos) noexcept;
973 template<class find_string_t, class replace_string_t>
975 const find_string_t& sFind,
976 const replace_string_t& sReplace,
977 size_type nBegin = 0,
978 size_type nEnd = npos) noexcept;
989 int compare(value_type chSymbol) const noexcept;
1000 int compare(const_pointer pszStr) const noexcept;
1012 int compare(const_pointer pStr, size_type nStrSize) const noexcept;
1036 template<class fwd_it_t>
1037 int compare(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1049 template<range_of_t_c<char_t> string_t>
1050 int compare(const string_t& sStr) const noexcept;
1059 size_type
find(value_type chSymbol, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1069 size_type
find(const_pointer pszWhat, size_type nBegin = 0, size_type nWhatSize = npos, size_type nEnd = npos)
1079 size_type
find(const
basic_string& sWhat, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1090 template<class fwd_it_t>
1091 size_type
find(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0, size_type nEnd = npos)
1102 template<range_of_t_c<char_t> string_t>
1103 size_type
find(string_t sWhat, size_type nBegin = 0, size_type nEnd = npos) const noexcept;
1113 size_type
rfind(value_type chSymbol, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1124 size_type
rfind(const_pointer pszWhat, size_type nBegin = npos, size_type nWhatSize = npos, size_type nEnd = 0)
1135 size_type
rfind(const
basic_string& sWhat, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1147 template<class fwd_it_t>
1148 size_type
rfind(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = npos, size_type nEnd = 0)
1160 template<range_of_t_c<char_t> string_t>
1161 size_type
rfind(string_t sWhat, size_type nBegin = npos, size_type nEnd = 0) const noexcept;
1169 size_type
find_first_of(value_type chSymbol, size_type nBegin = 0) const noexcept;
1178 size_type
find_first_of(const_pointer pszWhat, size_type nBegin, size_type nWhatSize) const noexcept;
1186 size_type
find_first_of(const_pointer pszWhat, size_type nBegin = 0) const noexcept;
1204 template<class fwd_it_t>
1205 size_type
find_first_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0) const noexcept;
1214 template<range_of_t_c<char_t> string_t>
1215 size_type
find_first_of(string_t sWhat, size_type nBegin = 0) const noexcept;
1223 size_type
find_last_of(value_type chSymbol, size_type nEnd = 0) const noexcept;
1232 size_type
find_last_of(const_pointer pszWhat, size_type nEnd, size_type nWhatSize) const noexcept;
1240 size_type
find_last_of(const_pointer pszWhat, size_type nEnd = 0) const noexcept;
1258 template<class fwd_it_t>
1259 size_type
find_last_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nEnd = 0) const noexcept;
1268 template<range_of_t_c<char_t> string_t>
1269 size_type
find_last_of(string_t sWhat, size_type nEnd = 0) const noexcept;
1277 size_type
find_first_not_of(value_type chSymbol, size_type nBegin = 0) const noexcept;
1286 size_type
find_first_not_of(const_pointer pszWhat, size_type nBegin, size_type nWhatSize) const noexcept;
1294 size_type
find_first_not_of(const_pointer pszWhat, size_type nBegin = 0) const noexcept;
1312 template<class fwd_it_t>
1313 size_type
find_first_not_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nBegin = 0) const noexcept;
1322 template<range_of_t_c<char_t> string_t>
1323 size_type
find_first_not_of(string_t sWhat, size_type nBegin = 0) const noexcept;
1331 size_type
find_last_not_of(value_type chSymbol, size_type nEnd = 0) const noexcept;
1340 size_type
find_last_not_of(const_pointer pszWhat, size_type nEnd, size_type nWhatSize) const noexcept;
1348 size_type
find_last_not_of(const_pointer pszWhat, size_type nEnd = 0) const noexcept;
1366 template<class fwd_it_t>
1367 size_type
find_last_not_of(fwd_it_t itWhatBegin, fwd_it_t itWhatEnd, size_type nEnd = 0) const noexcept;
1376 template<range_of_t_c<char_t> string_t>
1377 size_type
find_last_not_of(string_t sWhat, size_type nEnd = 0) const noexcept;
1384 views
split(const value_type chSeparator) const noexcept;
1392 views
split(const_pointer pszSeparator, size_type nSepLen = npos) const noexcept;
1408 template<class fwd_it_t>
1409 views
split(fwd_it_t itSepFirst, fwd_it_t itSepLast) const noexcept;
1417 template<range_of_t_c<char_t> string_t>
1418 views
split(const string_t& sSeparator) const noexcept;
1425 bool starts_with(value_type chSymbol) const noexcept;
1433 bool starts_with(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1449 template<class fwd_it_t>
1450 bool starts_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1458 template<range_of_t_c<char_t> string_t>
1459 bool starts_with(const string_t& sStr) const noexcept;
1466 bool ends_with(value_type chSymbol) const noexcept;
1474 bool ends_with(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1490 template<class fwd_it_t>
1491 bool ends_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1499 template<range_of_t_c<char_t> string_t>
1500 bool ends_with(const string_t& sStr) const noexcept;
1508 bool contains(value_type chSymbol) const noexcept;
1517 bool contains(const_pointer pszStr, size_type nStrSize = npos) const noexcept;
1535 template<class fwd_it_t>
1536 bool contains(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept;
1545 template<range_of_t_c<char_t> string_t>
1546 bool contains(const string_t& sStr) const noexcept;
1548 basic_string& operator=(const_pointer pszSource) noexcept;
1551 template<range_of_t_c<char_t> string_t>
1552 basic_string& operator=(const string_t& sStr) noexcept;
1554 basic_string& operator+=(value_type chSymbol) noexcept;
1555 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 bool operator==(value_type chSymbol) const noexcept;
1561 bool operator==(const_pointer pszSource) const noexcept;
1562 bool operator==(const
basic_string& sStr) const noexcept;
1563 template<range_of_t_c<char_t> string_t>
1564 bool operator==(const string_t& sStr) const 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 reference operator[](size_type nSymbol) noexcept;
1597 const_reference operator[](size_type nSymbol) const noexcept;
1599 operator string_view() const noexcept;
1601 explicit operator
bool() const noexcept;
1611 bool _resize(size_type nSymbols, sbo_resize_type eType = sbo_resize_type::common) noexcept;
1619 template<class searcher_t>
1620 size_type _trim_left(const searcher_t& searcher) noexcept;
1628 template<class searcher_t>
1629 size_type _trim_right(const searcher_t& searcher) noexcept;
1637 template<class searcher_t>
1638 size_type _trim(const searcher_t& searcher) noexcept;
1648 template<class comparator_t>
1649 size_type _find(size_type nBegin, size_type nEnd, const comparator_t& comparator) const noexcept;
1659 template<class comparator_t>
1660 size_type _rfind(size_type nBegin, size_type nEnd, const comparator_t& comparator) const noexcept;
1672 template<class incrementer_t, class fwd_it_t>
1673 size_type _find_first_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin, const incrementer_t& incrementer)
1686 template<class incrementer_t, class fwd_it_t>
1687 size_type _find_last_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nEnd, const incrementer_t& incrementer)
1700 template<class incrementer_t, class fwd_it_t>
1701 size_type _find_first_not_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nBegin, const incrementer_t& incrementer)
1714 template<class incrementer_t, class fwd_it_t>
1715 size_type _find_last_not_of(fwd_it_t itBegin, fwd_it_t itEnd, size_type nEnd, const incrementer_t& incrementer)
1724 template<class string_view_like_t>
1725 static size_type _get_string_view_like_size(const string_view_like_t& sValue) noexcept;
1733 template<class string_view_like_t>
1734 static const_pointer _get_string_view_like_data(const string_view_like_t& sValue) noexcept;
1737 sbo_bytes<details::string_sbo_traits<traits_t>> m_Data;
1748 template<class T, class char_t = char_type, class traits_t = string_traits::traits<char_t>>
1749 basic_string<char_t, traits_t> convert_to_string(const T& value);
1757 #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.
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.
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)
Append the formatted string to the current one.
void to_lower() noexcept
Convert string to lowercase.
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)
Clear the string and format it with the format string and the args.
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_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.
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)
Create a string by formatting it with the format string and the args.
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.
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.