conststr 0.2.1
Loading...
Searching...
No Matches
conststr.hpp
Go to the documentation of this file.
1/* MIT License
2 *
3 * Copyright (c) 2024 Nichts Hsu
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
225#ifndef CONSTSTR_HPP
226#define CONSTSTR_HPP
227
228#include <algorithm>
229#include <concepts>
230#include <cstddef>
231#include <iostream>
232#include <iterator>
233#include <string_view>
234#include <tuple>
235#include <type_traits>
236
240namespace conststr {
241
245namespace meta {
252template <typename... Ts>
253using first_t = std::tuple_element_t<0, std::tuple<Ts...>>;
254
261template <auto... Vs>
263 std::remove_cvref_t<std::tuple_element_t<0, decltype(std::tuple{Vs...})>>;
264
271template <auto... Vs>
272constexpr auto first_v = [](auto first, auto...) { return first; }(Vs...);
273
280template <typename... Ts>
281using last_t = std::tuple_element_t<sizeof...(Ts) - 1, std::tuple<Ts...>>;
282
289template <auto... Vs>
290using last_t_of = std::remove_cvref_t<
291 std::tuple_element_t<sizeof...(Vs) - 1, decltype(std::tuple{Vs...})>>;
292
299template <auto... Vs>
300constexpr auto last_v = (Vs, ...);
301
306template <typename... Ts>
307concept all_same = (std::same_as<first_t<Ts...>, Ts> && ...);
312template <auto... Vs>
313concept all_same_of = all_same<std::remove_cvref_t<decltype(Vs)>...>;
314
319template <typename T>
320concept hashable = requires(std::hash<std::remove_cvref_t<T>> hash,
321 const std::remove_cvref_t<T> &obj) { hash(obj); };
322
330template <typename T, typename Elem, typename SizeT = std::size_t>
331concept viewer =
332 std::constructible_from<T, const Elem *, SizeT> && requires(const T &t) {
333 t.begin();
334 t.end();
335 t.rbegin();
336 t.rend();
337 t.size();
338 t[SizeT{}];
339 };
340} // namespace meta
341
345namespace charutils {
353template <typename T>
354concept char_like = std::is_trivial_v<T> && std::equality_comparable<T> &&
355 std::three_way_comparable<T> &&
356 requires { T('\0') + T('\x20') - T('\x20'); };
357
361template <char_like T>
362constexpr bool islower(T ch) {
363 return ch >= T('a') && ch <= T('z');
364}
365
369template <char_like T>
370constexpr bool issuper(T ch) {
371 return ch >= T('A') && ch <= T('Z');
372}
373
377template <char_like T>
378constexpr bool isdigit(T ch) {
379 return ch >= T('0') && ch <= T('9');
380}
381
385template <char_like T>
386constexpr bool isalpha(T ch) {
387 return islower(ch) || issuper(ch);
388}
389
393template <char_like T>
394constexpr bool isalnum(T ch) {
395 return isalpha(ch) || isdigit(ch);
396}
397
401template <char_like T>
402constexpr bool isxdigit(T ch) {
403 return isdigit(ch) || (ch >= T('a') && ch <= T('f')) ||
404 (ch >= T('A') && ch <= T('F'));
405}
406
410template <char_like T>
411constexpr bool iscntrl(T ch) {
412 return (ch >= T('\0') && ch <= T('\x1F')) || ch == T('\x7F');
413}
414
418template <char_like T>
419constexpr bool ispunct(T ch) {
420 return (ch >= T('!') && ch <= T('/')) || (ch >= T(':') && ch <= T('@')) ||
421 (ch >= T('[') && ch <= T('`')) || (ch >= T('{') && ch <= T('~'));
422}
423
427template <char_like T>
428constexpr bool isblank(T ch) {
429 return ch == T(' ') || ch == T('\t');
430}
431
435template <char_like T>
436constexpr bool isspace(T ch) {
437 return isblank(ch) || ch == T('\f') || ch == T('\n') || ch == T('\r') ||
438 ch == T('\v');
439}
440
444template <char_like T>
445constexpr bool isgraph(T ch) {
446 return isalnum(ch) || ispunct(ch);
447}
448
452template <char_like T>
453constexpr bool isprint(T ch) {
454 return isgraph(ch) || ch == T(' ');
455}
456
460template <char_like T>
461constexpr char toupper(T ch) {
462 return ch >= T('a') && ch <= T('z') ? ch - T('\x20') : ch;
463}
464
468template <char_like T>
469constexpr char tolower(T ch) {
470 return ch >= T('A') && ch <= T('Z') ? ch + T('\x20') : ch;
471}
472
476template <char_like T>
477constexpr char invert(T ch) {
478 return ch >= T('a') && ch <= T('z') ? ch - T('\x20')
479 : ch >= T('A') && ch <= T('Z') ? ch + T('\x20')
480 : ch;
481}
482
496template <char_like auto... Chs>
497constexpr bool is(meta::first_t_of<Chs...> ch)
498 requires meta::all_same_of<Chs...> && (sizeof...(Chs) > 1)
499{
500 return ((Chs == ch) || ...);
501}
502
515template <char_like auto Ch>
516constexpr decltype(Ch) just([[maybe_unused]] decltype(Ch) ignored) {
517 return Ch;
518}
519
526template <char_like To>
527constexpr auto cast =
528 [](char_like auto from) -> To { return static_cast<To>(from); };
529
546template <char_like auto... Chs>
548 requires meta::all_same_of<Chs...> && (sizeof...(Chs) > 1)
549{
550 return is<Chs...>(ch) ? meta::last_v<Chs...> : ch;
551}
552
569template <char_like auto... Chs>
571 requires meta::all_same_of<Chs...> && (sizeof...(Chs) > 1)
572{
573 return is<Chs...>(ch) ? ch : meta::last_v<Chs...>;
574}
575} // namespace charutils
576
577template <std::size_t N, charutils::char_like T, typename view>
578 requires meta::viewer<view, T>
579struct cstr;
580
585template <typename T>
586concept can_construct_cstr_from = requires(const T &t) { cstr{t}; };
587
594template <typename T, typename CharT>
596 std::same_as<typename decltype(cstr(std::declval<T>()))::value_type, CharT>;
597
605template <typename T, typename CharT, std::size_t Len>
607 std::same_as<typename decltype(cstr(std::declval<T>()))::value_type,
608 CharT> &&
609 (decltype(cstr(std::declval<T>()))::size() == Len);
610
616template <typename T>
617struct sv_selector {};
618
642template <typename T>
643constexpr auto sv = sv_selector<T>{};
644
654template <std::size_t N, charutils::char_like T = char,
655 typename view = std::basic_string_view<T>>
656 requires meta::viewer<view, T>
657struct cstr {
658 using value_type = T;
659 using size_type = std::size_t;
660 using difference_type = std::ptrdiff_t;
661 using reference = value_type &;
662 using const_reference = const value_type &;
663 using rreference = value_type &&;
664 using const_rreference = const value_type &&;
665 using pointer = value_type *;
666 using const_pointer = const value_type *;
667 using iterator = value_type *;
668 using const_iterator = const value_type *;
669 using reverse_iterator = std::reverse_iterator<iterator>;
670 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
671 using view_type = view;
672
673 template <typename UnaryOperation>
674 using operation_result =
675 std::remove_cvref_t<std::invoke_result_t<UnaryOperation, value_type>>;
676
680 static constexpr value_type nul = value_type('\0');
681
685 static constexpr size_type npos = N;
686
692 constexpr cstr(
693 [[maybe_unused]] const sv_selector<view_type> &svs = {}) noexcept
694 : _str{nul} {}
695
708 constexpr cstr(
709 const value_type (&str)[N + 1],
710 [[maybe_unused]] const sv_selector<view_type> &svs = {}) noexcept {
711 for (size_type i = 0; i < N; ++i) _str[i] = str[i];
712 _str[N] = nul;
713 }
714
721 constexpr cstr(
722 const value_type &ch,
723 [[maybe_unused]] const sv_selector<view_type> &svs = {}) noexcept {
724 fill(ch);
725 }
726
733 constexpr cstr(std::convertible_to<value_type> auto... vs)
734 : _str{vs..., nul} {}
735
739 constexpr cstr(const cstr &) = default;
740
744 template <typename V2>
745 constexpr cstr(const cstr<N, value_type, V2> &other) {
746 std::copy_n(other.begin(), size(), begin());
747 _str[N] = nul;
748 };
749
753 constexpr ~cstr() = default;
754
758 template <can_construct_cstr_t_n_from<value_type, N> Str>
759 constexpr cstr &operator=(const Str &str) {
760 auto other = cstr(str);
761 std::copy_n(other.begin(), size(), begin());
762 return *this;
763 };
764
769 constexpr void fill(const value_type &ch) noexcept {
770 std::fill_n(begin(), size(), ch);
771 _str[N] = nul;
772 }
773
779 template <typename V2>
780 constexpr void swap(cstr<N, value_type, V2> &other) noexcept {
781 std::swap_ranges(begin(), end(), other.begin());
782 }
783
788 static constexpr size_type size() noexcept { return N; }
789
795 static constexpr size_type length() noexcept { return size(); }
796
803 static constexpr size_type max_size() noexcept { return size(); }
804
813 static constexpr bool empty() noexcept { return size() == 0; }
814
820 constexpr pointer data() noexcept { return _str; }
821
827 constexpr const_pointer data() const noexcept { return _str; }
828
834 constexpr const_pointer c_str() const noexcept { return data(); }
835
840 constexpr iterator begin() noexcept { return data(); }
841
846 constexpr const_iterator begin() const noexcept { return data(); }
847
853 constexpr iterator end() noexcept { return data() + size(); }
854
860 constexpr const_iterator end() const noexcept { return data() + size(); }
861
866 constexpr const_iterator cbegin() const noexcept { return data(); }
867
873 constexpr const_iterator cend() const noexcept { return data() + size(); }
874
879 constexpr reverse_iterator rbegin() noexcept {
880 return reverse_iterator(end());
881 }
882
887 constexpr const_reverse_iterator rbegin() const noexcept {
888 return const_reverse_iterator(end());
889 }
890
896 constexpr reverse_iterator rend() noexcept {
897 return reverse_iterator(begin());
898 }
899
905 constexpr const_reverse_iterator rend() const noexcept {
906 return const_reverse_iterator(begin());
907 }
908
914 constexpr const_reverse_iterator crbegin() const noexcept {
915 return const_reverse_iterator(end());
916 }
917
923 constexpr const_reverse_iterator crend() const noexcept {
924 return const_reverse_iterator(begin());
925 }
926
932 constexpr reference operator[](size_type pos) noexcept { return _str[pos]; }
933
939 constexpr const_reference operator[](size_type pos) const noexcept {
940 return _str[pos];
941 }
942
948 template <size_type Idx>
949 constexpr reference get() & noexcept
950 requires(N > Idx)
951 {
952 return _str[Idx];
953 }
954
960 template <size_type Idx>
961 constexpr const_reference get() const & noexcept
962 requires(N > Idx)
963 {
964 return _str[Idx];
965 }
966
972 template <size_type Idx>
973 constexpr rreference get() && noexcept
974 requires(N > Idx)
975 {
976 return std::move(_str[Idx]);
977 }
978
984 template <size_type Idx>
985 constexpr const_rreference get() const && noexcept
986 requires(N > Idx)
987 {
988 return std::move(_str[Idx]);
989 }
990
996 constexpr reference front() noexcept { return *begin(); }
997
1003 constexpr const_reference front() const noexcept { return *cbegin(); }
1004
1010 constexpr reference back() noexcept {
1011 if constexpr (N > 0)
1012 return *(end() - 1);
1013 else
1014 return *end();
1015 }
1016
1022 constexpr const_reference back() const noexcept {
1023 if constexpr (N > 0)
1024 return *(cend() - 1);
1025 else
1026 return *cend();
1027 }
1028
1035 template <can_construct_cstr_t_from<value_type> Str>
1036 constexpr auto operator+(const Str &str) const noexcept {
1037 return append(str);
1038 }
1039
1047 template <std::size_t N2, typename V2>
1048 constexpr bool operator==(
1049 const cstr<N2, value_type, V2> &other) const noexcept {
1050 return false;
1051 }
1052
1060 template <typename V2>
1061 constexpr bool operator==(
1062 const cstr<N, value_type, V2> &other) const noexcept {
1063 if constexpr (std::equality_comparable<view_type>)
1064 return this->operator view_type() == other.operator view_type();
1065 else
1066 return std::equal(cbegin(), cend(), other.cbegin(), other.cend());
1067 }
1068
1075 constexpr bool operator==(const view_type &other) const noexcept {
1076 if constexpr (std::equality_comparable<view_type>)
1077 return this->operator view_type() == other;
1078 else
1079 return std::equal(cbegin(), cend(), other.begin(), other.end());
1080 }
1081
1091 template <std::size_t N2, typename V2>
1092 constexpr auto operator<=>(const cstr<N2, value_type, V2> &other) noexcept {
1093 if constexpr (std::three_way_comparable<view_type>)
1094 return this->operator view_type() <=> other.operator view_type();
1095 else
1096 return std::lexicographical_compare_three_way(
1097 cbegin(), cend(), other.cbegin(), other.cend());
1098 }
1099
1107 constexpr auto operator<=>(const view_type &other) const noexcept {
1108 if constexpr (std::three_way_comparable<view_type>)
1109 return this->operator view_type() <=> other;
1110 else
1111 return std::lexicographical_compare_three_way(
1112 cbegin(), cend(), other.begin(), other.end());
1113 }
1114
1118 constexpr operator view_type() const noexcept {
1119 return view_type(data(), size());
1120 }
1121
1127 template <meta::viewer<value_type, size_type> V2>
1128 constexpr auto with_view() const noexcept -> cstr<N, value_type, V2> {
1129 return cstr<N, value_type, V2>{*this};
1130 }
1131
1138 template <size_type Start, size_type Len = N>
1139 requires(N >= Start)
1140 constexpr auto substr() const noexcept {
1141 constexpr size_type size = std::min(Start + Len, N) - Start;
1143 for (size_type i = 0; i < size; ++i) ret[i] = _str[Start + i];
1144 return ret;
1145 };
1146
1153 template <size_type Len>
1154 constexpr auto cut() const noexcept -> cstr<Len, value_type, view_type> {
1155 return substr<0, Len>();
1156 }
1157
1163 template <size_type Len>
1164 constexpr auto remove_prefix() const noexcept {
1165 return substr<Len>();
1166 }
1167
1174 template <size_type Len>
1175 constexpr auto remove_suffix() const noexcept {
1176 return substr<0, N - Len>();
1177 }
1178
1188 template <size_type Count = 1>
1189 constexpr auto insert(size_type pos, const value_type &ch) const noexcept
1191 if (pos > N) pos = N;
1192 if constexpr (Count == 0)
1193 return *this;
1194 else {
1196 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1197 for (size_type i = pos; i < pos + Count; ++i) ret[i] = ch;
1198 for (size_type i = pos; i < N; ++i) ret[i + Count] = _str[i];
1199 return ret;
1200 }
1201 };
1202
1212 template <size_type Count = 1>
1213 constexpr auto insert(const_iterator iter,
1214 const value_type &ch) const noexcept
1216 size_type pos = to_pos(iter);
1217 if constexpr (Count == 0)
1218 return *this;
1219 else {
1221 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1222 for (size_type i = pos; i < pos + Count; ++i) ret[i] = ch;
1223 for (size_type i = pos; i < N; ++i) ret[i + Count] = _str[i];
1224 return ret;
1225 }
1226 };
1227
1237 template <can_construct_cstr_t_from<value_type> Str>
1238 constexpr auto insert(size_type pos, const Str &str) const noexcept {
1239 if (pos > N) pos = N;
1240
1241 auto other = conststr::cstr(str);
1242 constexpr size_type N2 = decltype(other)::size();
1244 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1245 for (size_type i = 0; i < N2; ++i) ret[i + pos] = other[i];
1246 for (size_type i = pos; i < N; ++i) ret[i + N2] = _str[i];
1247 return ret;
1248 }
1249
1259 template <can_construct_cstr_t_from<value_type> Str>
1260 constexpr auto insert(const_iterator iter, const Str &str) const noexcept {
1261 size_type pos = to_pos(iter);
1262 auto other = conststr::cstr(str);
1263 constexpr size_type N2 = decltype(other)::size();
1265 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1266 for (size_type i = 0; i < N2; ++i) ret[i + pos] = other[i];
1267 for (size_type i = pos; i < N; ++i) ret[i + N2] = _str[i];
1268 return ret;
1269 }
1270
1279 template <size_type Count = 1>
1280 constexpr auto append(const value_type &ch) const noexcept
1282 if constexpr (Count == 0)
1283 return *this;
1284 else {
1286 for (size_type i = 0; i < N; ++i) ret[i] = _str[i];
1287 for (size_type i = N; i < N + Count; ++i) ret[i] = ch;
1288 return ret;
1289 }
1290 }
1291
1300 template <can_construct_cstr_t_from<value_type> Str>
1301 constexpr auto append(const Str &str) const noexcept {
1302 return flatten(str);
1303 }
1304
1314 template <size_type... Sizes>
1315 constexpr auto flatten(
1316 const cstr<Sizes, value_type, view_type> &...strs) const noexcept {
1317 if constexpr (sizeof...(Sizes) == 0)
1318 return *this;
1319 else {
1320 constexpr size_type COUNT = sizeof...(strs) + 1;
1321 constexpr size_type LENGTHS[COUNT] = {N, Sizes...};
1322 constexpr size_type FLAT_LENGTH = N + (Sizes + ...);
1323
1325 const_pointer datas[COUNT] = {data(), strs.data()...};
1326 size_type index = 0;
1327 for (size_type i = 0; i < COUNT; i++)
1328 for (size_type j = 0; j < LENGTHS[i]; j++)
1329 flat[index++] = datas[i][j];
1330
1331 return flat;
1332 }
1333 }
1334
1345 template <can_construct_cstr_t_from<value_type>... Strs>
1346 constexpr auto flatten(const Strs &...strs) const noexcept {
1347 return flatten(conststr::cstr(strs)...);
1348 }
1349
1362 constexpr auto replace(size_type pos, const value_type &ch,
1363 size_type count = 1) const noexcept
1364 -> cstr<N, value_type, view_type> {
1365 if (pos > N) pos = N;
1367 size_type end = std::min(pos + count, N);
1368 for (size_type i = pos; i < end; ++i) ret[i] = ch;
1369 return ret;
1370 }
1371
1384 constexpr auto replace(const_iterator first, const_iterator last,
1385 const value_type &ch) const noexcept
1387 auto [pos, count] = to_pos_len(first, last);
1389 size_type end = std::min(pos + count, N);
1390 for (size_type i = pos; i < end; ++i) ret[i] = ch;
1391 return ret;
1392 }
1393
1404 constexpr auto replace(size_type pos, const view_type &str,
1405 size_type count = 1) const noexcept
1406 -> cstr<N, value_type, view_type> {
1407 if (pos > N) pos = N;
1409 size_type end = std::min(pos + count * str.size(), N);
1410 for (size_type i = 0; i < end - pos; ++i) ret[i] = str[i % str.size()];
1411 return ret;
1412 }
1413
1424 constexpr auto replace(const_iterator first, const_iterator last,
1425 const view_type &str) const noexcept
1427 auto [pos, count] = to_pos_len(first, last);
1428 return replace(pos, str, count);
1429 }
1430
1447 template <value_type... Chs>
1448 constexpr auto replace(size_type pos = 0, size_type len = N) const noexcept
1450 requires(sizeof...(Chs) > 0)
1451 {
1452 return transform(charutils::replace<Chs...>, pos, len);
1453 }
1454
1471 template <value_type... Chs>
1472 constexpr auto replace(const_iterator first,
1473 const_iterator last) const noexcept
1475 requires(sizeof...(Chs) > 0)
1476 {
1477 return transform(charutils::replace<Chs...>, first, last);
1478 }
1479
1489 constexpr auto erase(size_type pos) const noexcept
1490 -> cstr<N - 1, value_type, view_type> {
1491 if (pos >= N) return pop();
1492 cstr<N - 1, value_type, view_type> ret{};
1493 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1494 for (size_type i = pos; i < N - 1; ++i) ret[i] = _str[i + 1];
1495 return ret;
1496 }
1497
1507 constexpr auto erase(const_iterator iter) const noexcept
1508 -> cstr<N - 1, value_type, view_type> {
1509 size_type pos = to_pos(iter);
1510 cstr<N - 1, value_type, view_type> ret{};
1511 for (size_type i = 0; i < pos; ++i) ret[i] = _str[i];
1512 for (size_type i = pos; i < N - 1; ++i) ret[i] = _str[i + 1];
1513 return ret;
1514 }
1515
1523 constexpr auto push(const value_type &ch) const noexcept
1525 return append(ch);
1526 }
1527
1535 constexpr auto pop() const noexcept -> cstr<N - 1, value_type, view_type> {
1536 return cut<N - 1>();
1537 }
1538
1557 template <typename UnaryOperation, typename V2 = void>
1558 constexpr auto transform(
1559 UnaryOperation op, size_type pos = 0, size_type len = N,
1560 [[maybe_unused]] const sv_selector<V2> &svs = {}) const noexcept
1561 requires(meta::viewer<V2, operation_result<UnaryOperation>> ||
1562 (std::is_void_v<V2>))
1563 {
1564 using result_t = operation_result<UnaryOperation>;
1565 using view_t = std::conditional_t<
1566 std::is_void_v<V2>,
1567 std::conditional_t<std::is_same_v<value_type, result_t>, view_type,
1568 std::basic_string_view<result_t>>,
1569 V2>;
1570 if (pos > N) pos = N;
1572 auto begin = cbegin() + pos;
1573 auto end = cbegin() + std::min(pos + len, N);
1574 auto begin2 = ret.begin() + pos;
1575 std::transform(begin, end, begin2, op);
1576 return ret;
1577 }
1578
1597 template <typename UnaryOperation, typename V2 = void>
1598 constexpr auto transform(
1599 UnaryOperation op, const_iterator first, const_iterator last,
1600 [[maybe_unused]] const sv_selector<V2> &svs = {}) const noexcept
1601 requires(meta::viewer<V2, operation_result<UnaryOperation>> ||
1602 (std::is_void_v<V2>))
1603 {
1604 using result_t = operation_result<UnaryOperation>;
1605 using view_t = std::conditional_t<
1606 std::is_void_v<V2>,
1607 std::conditional_t<std::is_same_v<value_type, result_t>, view_type,
1608 std::basic_string_view<result_t>>,
1609 V2>;
1610 first = std::max(first, cbegin());
1611 last = std::min(last, cend());
1613 auto first2 = ret.begin() + (first - cbegin());
1614 std::transform(first, last, first2, op);
1615 return ret;
1616 }
1617
1627 template <charutils::char_like T2, typename V2 = void>
1628 constexpr auto cast(
1629 [[maybe_unused]] const sv_selector<V2> &svs = {}) const noexcept
1630 requires(meta::viewer<V2, T2> || (std::is_void_v<V2>))
1631 {
1632 return transform(charutils::cast<T2>, 0, N, sv<V2>);
1633 }
1634
1643 constexpr auto uppercase() const noexcept
1644 -> cstr<N, value_type, view_type> {
1645 return transform(charutils::toupper<value_type>);
1646 }
1647
1656 constexpr auto lowercase() const noexcept
1657 -> cstr<N, value_type, view_type> {
1658 return transform(charutils::tolower<value_type>);
1659 }
1660
1667 constexpr size_type find(const value_type &ch,
1668 size_type pos = 0) const noexcept {
1669 if (pos >= npos) return npos;
1670 return to_pos(std::find(cbegin() + pos, cend(), ch));
1671 }
1672
1679 constexpr size_type find(const view_type &str,
1680 size_type pos = 0) const noexcept {
1681 if (pos >= npos) return npos;
1682 return to_pos(
1683 std::search(cbegin() + pos, cend(), str.cbegin(), str.cend()));
1684 }
1685
1692 constexpr size_type rfind(const value_type &ch,
1693 size_type pos = npos) const noexcept {
1694 auto beg =
1695 pos >= npos ? crbegin() : const_reverse_iterator(cbegin() + pos);
1696 auto iter = std::find(beg, crend(), ch);
1697 return iter == crend() ? npos : to_pos(iter.base() - 1);
1698 }
1699
1706 constexpr size_type rfind(const view_type &str,
1707 size_type pos = npos) const noexcept {
1708 auto beg =
1709 pos >= npos ? crbegin() : const_reverse_iterator(cbegin() + pos);
1710 auto iter = std::search(beg, crend(), str.crbegin(), str.crend());
1711 return iter == crend() ? npos : to_pos(iter.base() - str.size());
1712 }
1713
1721 template <typename UnaryPredicate>
1722 constexpr size_type find_if(UnaryPredicate p,
1723 size_type pos = 0) const noexcept {
1724 if (pos >= npos) return npos;
1725 return to_pos(std::find_if(cbegin() + pos, cend(), p));
1726 }
1727
1735 template <typename UnaryPredicate>
1736 constexpr size_type rfind_if(UnaryPredicate p,
1737 size_type pos = npos) const noexcept {
1738 auto beg =
1739 pos >= npos ? crbegin() : const_reverse_iterator(begin() + pos);
1740 auto iter = std::find_if(beg, crend(), p);
1741 return iter == crend() ? npos : to_pos(iter.base() - 1);
1742 }
1743
1750 constexpr bool starts_with(const value_type &ch) const noexcept {
1751 if constexpr (N == 0)
1752 return false;
1753 else
1754 return front() == ch;
1755 }
1756
1763 constexpr bool starts_with(const view_type &str) const noexcept {
1764 if constexpr (requires { this->operator view_type().starts_with(str); })
1765 return this->operator view_type().starts_with(str);
1766 else if constexpr (std::equality_comparable<view_type>)
1767 return size() > str.size() && view_type(begin(), str.size()) == str;
1768 else
1769 return size() > str.size() &&
1770 std::equal(str.begin(), str.end(), begin());
1771 }
1772
1779 constexpr bool ends_with(const value_type &ch) const noexcept {
1780 if constexpr (N == 0)
1781 return false;
1782 else
1783 return back() == ch;
1784 }
1785
1792 constexpr bool ends_with(const view_type &str) const noexcept {
1793 if constexpr (requires { this->operator view_type().ends_with(str); })
1794 return this->operator view_type().ends_with(str);
1795 else if constexpr (std::equality_comparable<view_type>)
1796 return size() > str.size() &&
1797 view_type(end() - str.size(), str.size()) == str;
1798 else
1799 return size() > str.size() &&
1800 std::equal(str.begin(), str.end(), end() - str.size());
1801 }
1802
1810 constexpr bool contains(const value_type &ch) const noexcept {
1811 return find(ch) != npos;
1812 }
1813
1821 constexpr bool contains(const view_type &str) const noexcept {
1822 return find(str) != npos;
1823 }
1824
1829 value_type _str[N + 1];
1830
1831 private:
1832 inline constexpr size_t to_pos(const_iterator iter) const noexcept {
1833 return std::min(size_t(std::max(iter, cbegin()) - cbegin()), N);
1834 }
1835
1836 inline constexpr std::tuple<size_t, size_t> to_pos_len(
1837 const_iterator first, const_iterator last) const noexcept {
1838 size_t first_pos = to_pos(first);
1839 size_t last_pos = to_pos(last);
1840 return {first_pos, std::max(first_pos, last_pos) - first_pos};
1841 }
1842};
1843
1847template <charutils::char_like T, std::size_t N>
1848cstr(const T (&)[N]) -> cstr<N - 1, T, std::basic_string_view<T>>;
1849
1853template <charutils::char_like T, std::size_t N, meta::viewer<T> V>
1854cstr(const T (&)[N], const sv_selector<V> &) -> cstr<N - 1, T, V>;
1855
1859template <charutils::char_like T>
1861
1865template <charutils::char_like T, meta::viewer<T> V>
1866cstr(const T &ch, const sv_selector<V> &) -> cstr<1, T, V>;
1867
1874template <std::size_t Idx, charutils::char_like T, typename U, std::size_t N>
1875typename cstr<N, T, U>::reference get(cstr<N, T, U> &str) noexcept {
1876 return str.template get<Idx>();
1877}
1878
1885template <std::size_t Idx, charutils::char_like T, typename U, std::size_t N>
1886typename cstr<N, T, U>::const_reference get(const cstr<N, T, U> &str) noexcept {
1887 return str.template get<Idx>();
1888}
1889
1896template <std::size_t Idx, charutils::char_like T, typename U, std::size_t N>
1897typename cstr<N, T, U>::rreference get(cstr<N, T, U> &&str) noexcept {
1898 return str.template get<Idx>();
1899}
1900
1907template <std::size_t Idx, charutils::char_like T, typename U, std::size_t N>
1908const typename cstr<N, T, U>::const_rreference get(
1909 const cstr<N, T, U> &&str) noexcept {
1910 return str.template get<Idx>();
1911}
1912
1918template <charutils::char_like T, typename V1, typename V2, std::size_t N>
1919constexpr void swap(cstr<N, T, V1> &lhs, cstr<N, T, V2> &rhs) {
1920 lhs.swap(rhs);
1921}
1922
1932template <can_construct_cstr_from First, can_construct_cstr_from... Str>
1933constexpr auto flatten(const First &first, const Str &...strs)
1934 requires meta::all_same<
1935 typename decltype(cstr(std::declval<First>()))::value_type,
1936 typename decltype(cstr(std::declval<Str>()))::value_type...>
1937{
1938 return cstr(first).flatten(strs...);
1939}
1940
1944template <charutils::char_like T, typename U, std::size_t N>
1945std::ostream &operator<<(std::ostream &os, const cstr<N, T, U> &str) {
1946 os << static_cast<typename cstr<N, T, U>::view_type>(str);
1947 return os;
1948}
1949
1953namespace literal {
1959consteval auto operator""_cs(char ch) { return cstr<1, char>(ch); }
1960
1966consteval auto operator""_cs(char8_t ch) { return cstr<1, char8_t>(ch); }
1967
1973consteval auto operator""_cs(char16_t ch) { return cstr<1, char16_t>(ch); }
1974
1980consteval auto operator""_cs(char32_t ch) { return cstr<1, char32_t>(ch); }
1981
1987consteval auto operator""_cs(wchar_t ch) { return cstr<1, wchar_t>(ch); }
1988
1994template <cstr str>
1995consteval auto operator""_cs() {
1996 return str;
1997}
1998} // namespace literal
1999
2000} // namespace conststr
2001
2005template <conststr::charutils::char_like T, typename U, std::size_t N>
2006struct std::tuple_size<conststr::cstr<N, T, U>>
2007 : public std::integral_constant<std::size_t, N> {};
2008
2012template <std::size_t Idx, conststr::charutils::char_like T, typename U,
2013 std::size_t N>
2014struct std::tuple_element<Idx, conststr::cstr<N, T, U>> {
2015 static_assert(N > Idx);
2016 using type = T;
2017};
2018
2022template <conststr::charutils::char_like T, typename U, std::size_t N>
2023 requires conststr::meta::hashable<
2024 typename conststr::cstr<N, T, U>::view_type>
2025struct std::hash<conststr::cstr<N, T, U>> {
2026 std::size_t operator()(const conststr::cstr<N, T, U> &str) const noexcept {
2027 using view = typename conststr::cstr<N, T, U>::view_type;
2028 return std::hash<view>{}(static_cast<view>(str));
2029 }
2030};
2031
2032#endif
This concept is satisfied if cstr can be constructed from T.
Definition: conststr.hpp:586
This concept is satisfied if cstr can be constructed from T and the value_type of the cstr is CharT.
Definition: conststr.hpp:595
This concept is satisfied if cstr can be constructed from T and the value_type of the cstr is CharT a...
Definition: conststr.hpp:606
This concept is satisfied if T is a char-like type.
Definition: conststr.hpp:354
This concept is satisfied if all values of Vs... has the same type.
Definition: conststr.hpp:313
This concept is satisfied if all types of Ts... the same type.
Definition: conststr.hpp:307
This concept is satisfied if std::hash<T> has specialization.
Definition: conststr.hpp:320
This concept is satisfied if T is a view type to a constant contiguous sequence of Elem.
Definition: conststr.hpp:331
constexpr decltype(Ch) just(decltype(Ch) ignored)
No matter what the input is, always output Ch.
Definition: conststr.hpp:516
constexpr bool isspace(T ch)
constexpr re-implementation of std::isspace.
Definition: conststr.hpp:436
constexpr bool ispunct(T ch)
constexpr re-implementation of std::ispunct.
Definition: conststr.hpp:419
constexpr bool iscntrl(T ch)
constexpr re-implementation of std::iscntrl.
Definition: conststr.hpp:411
constexpr bool isblank(T ch)
constexpr re-implementation of std::isblank.
Definition: conststr.hpp:428
constexpr auto cast
Cast input character to the value of another character type.
Definition: conststr.hpp:527
constexpr char toupper(T ch)
constexpr re-implementation of std::toupper.
Definition: conststr.hpp:461
constexpr bool issuper(T ch)
constexpr re-implementation of std::issuper.
Definition: conststr.hpp:370
constexpr bool isalnum(T ch)
constexpr re-implementation of std::isalnum.
Definition: conststr.hpp:394
constexpr meta::last_t_of< Chs... > replace(meta::last_t_of< Chs... > ch)
Replace the input character if it is the same as one of variable template parameters.
Definition: conststr.hpp:547
constexpr bool islower(T ch)
constexpr re-implementation of std::islower.
Definition: conststr.hpp:362
constexpr bool isxdigit(T ch)
constexpr re-implementation of std::isxdigit.
Definition: conststr.hpp:402
constexpr bool isgraph(T ch)
constexpr re-implementation of std::isgraph.
Definition: conststr.hpp:445
constexpr char tolower(T ch)
constexpr re-implementation of std::tolower.
Definition: conststr.hpp:469
constexpr bool isalpha(T ch)
constexpr re-implementation of std::isalpha.
Definition: conststr.hpp:386
constexpr bool isprint(T ch)
constexpr re-implementation of std::isprint.
Definition: conststr.hpp:453
constexpr char invert(T ch)
Invert case of letter.
Definition: conststr.hpp:477
constexpr bool is(meta::first_t_of< Chs... > ch)
Check if input character the same as one of variable template parameters.
Definition: conststr.hpp:497
constexpr meta::last_t_of< Chs... > remain(meta::last_t_of< Chs... > ch)
Replace the input character if it is NOT one of variable template parameters.
Definition: conststr.hpp:570
constexpr bool isdigit(T ch)
constexpr re-implementation of std::isdigit.
Definition: conststr.hpp:378
constexpr auto last_v
Get the last value of variable template parameter pack.
Definition: conststr.hpp:300
std::remove_cvref_t< std::tuple_element_t< sizeof...(Vs) - 1, decltype(std::tuple{Vs...})> > last_t_of
Get the type of the last value of variable template parameter pack.
Definition: conststr.hpp:291
std::tuple_element_t< 0, std::tuple< Ts... > > first_t
Get the first type of class template parameter pack.
Definition: conststr.hpp:253
std::remove_cvref_t< std::tuple_element_t< 0, decltype(std::tuple{Vs...})> > first_t_of
Get the type of the first value of variable template parameter pack.
Definition: conststr.hpp:263
std::tuple_element_t< sizeof...(Ts) - 1, std::tuple< Ts... > > last_t
Get the last type of class template parameter pack.
Definition: conststr.hpp:281
constexpr auto first_v
Get the first value of variable template parameter pack.
Definition: conststr.hpp:272
The outermost namespace of this library to avoid identifier pollution.
Definition: conststr.hpp:240
constexpr void swap(cstr< N, T, V1 > &lhs, cstr< N, T, V2 > &rhs)
Satisfy the named requirement Swappable.
Definition: conststr.hpp:1919
constexpr auto flatten(const First &first, const Str &...strs)
Flatten multiple strings of different lengths.
Definition: conststr.hpp:1933
constexpr auto sv
String view type selector. Assist in type deduction of cstr.
Definition: conststr.hpp:643
cstr(const T(&)[N]) -> cstr< N - 1, T, std::basic_string_view< T > >
Deduction guide for cstr with default view type.
cstr< N, T, U >::reference get(cstr< N, T, U > &str) noexcept
Tuple-like interface, extracts the Idx-th element from the string.
Definition: conststr.hpp:1875
std::ostream & operator<<(std::ostream &os, const cstr< N, T, U > &str)
Output string to std::ostream.
Definition: conststr.hpp:1945
String type that can be evaluated in a constant context.
Definition: conststr.hpp:657
constexpr const_iterator begin() const noexcept
Get an iterator to the first character of the string.
Definition: conststr.hpp:846
constexpr auto operator<=>(const view_type &other) const noexcept
Compares the contents of two strings lexicographically.
Definition: conststr.hpp:1107
constexpr cstr(std::convertible_to< value_type > auto... vs)
Constructor for variable template parameter pack expansion.
Definition: conststr.hpp:733
constexpr const_iterator cbegin() const noexcept
Get an const iterator to the first character of the string.
Definition: conststr.hpp:866
constexpr auto cast(const sv_selector< V2 > &svs={}) const noexcept
Convert character type. Always be equivalent to transform(charutils::cast<T2>, 0, N,...
Definition: conststr.hpp:1628
constexpr size_type find(const value_type &ch, size_type pos=0) const noexcept
Find the first character equal to the given character.
Definition: conststr.hpp:1667
constexpr cstr(const value_type &ch, const sv_selector< view_type > &svs={}) noexcept
Construct string with N copies of character ch.
Definition: conststr.hpp:721
constexpr void fill(const value_type &ch) noexcept
Fill the string with the character ch.
Definition: conststr.hpp:769
constexpr reverse_iterator rend() noexcept
Get a reverse iterator to the character following the last character of the reversed string.
Definition: conststr.hpp:896
constexpr auto pop() const noexcept -> cstr< N - 1, value_type, view_type >
Pop the last character from the end of string. Always be equivalent to cut<size() - 1>().
Definition: conststr.hpp:1535
constexpr cstr(const sv_selector< view_type > &svs={}) noexcept
Default constructor, constructs string which is filled with '\0'.
Definition: conststr.hpp:692
constexpr const_reference back() const noexcept
Get the reference to the last character in the string.
Definition: conststr.hpp:1022
constexpr bool contains(const value_type &ch) const noexcept
Check if the string contains the given character. Always be equivalent to find(ch) !...
Definition: conststr.hpp:1810
constexpr size_type rfind(const view_type &str, size_type pos=npos) const noexcept
Find the last substring equal to the given substring.
Definition: conststr.hpp:1706
constexpr auto replace(size_type pos, const value_type &ch, size_type count=1) const noexcept -> cstr< N, value_type, view_type >
Replaces the characters in the range [pos, min(pos + count, size())) with character ch.
Definition: conststr.hpp:1362
constexpr auto insert(const_iterator iter, const Str &str) const noexcept
Insert another string before iterator iter.
Definition: conststr.hpp:1260
constexpr const_rreference get() const &&noexcept
Tuple-like interface, extracts the Idx-th element from the string.
Definition: conststr.hpp:985
constexpr reference front() noexcept
Get the reference to the first character in the string.
Definition: conststr.hpp:996
constexpr const_reference operator[](size_type pos) const noexcept
Get the reference to the character at specified location pos.
Definition: conststr.hpp:939
constexpr ~cstr()=default
Destructor. In fact, it does nothing.
constexpr auto insert(size_type pos, const value_type &ch) const noexcept -> cstr< N+Count, value_type, view_type >
Insert Count copies of character ch at the position pos.
Definition: conststr.hpp:1189
constexpr auto substr() const noexcept
Get the substring.
Definition: conststr.hpp:1140
constexpr bool ends_with(const value_type &ch) const noexcept
Check if the string ends with the given character.
Definition: conststr.hpp:1779
constexpr auto transform(UnaryOperation op, const_iterator first, const_iterator last, const sv_selector< V2 > &svs={}) const noexcept
Apply the given function to each character in the range [first, min(last, cend())).
Definition: conststr.hpp:1598
constexpr cstr & operator=(const Str &str)
Replaces the contents with a copy of another string.
Definition: conststr.hpp:759
constexpr size_type rfind(const value_type &ch, size_type pos=npos) const noexcept
Find the last character equal to the given character.
Definition: conststr.hpp:1692
constexpr auto uppercase() const noexcept -> cstr< N, value_type, view_type >
Convert all characters to uppercase. Always be equivalent to transform(charutils::toupper<value_type>...
Definition: conststr.hpp:1643
constexpr void swap(cstr< N, value_type, V2 > &other) noexcept
Swap the contents of this string with another string.
Definition: conststr.hpp:780
constexpr auto operator<=>(const cstr< N2, value_type, V2 > &other) noexcept
Compares the contents of two strings lexicographically.
Definition: conststr.hpp:1092
constexpr auto flatten(const Strs &...strs) const noexcept
Flatten multiple strings of different lengths.
Definition: conststr.hpp:1346
constexpr bool operator==(const cstr< N2, value_type, V2 > &other) const noexcept
Check if the contents of two strings are the same.
Definition: conststr.hpp:1048
constexpr auto replace(size_type pos=0, size_type len=N) const noexcept -> cstr< N, value_type, view_type > requires(sizeof...(Chs) > 0)
Replaces the characters in the range [pos, min(pos + len, size())) according to variable template par...
Definition: conststr.hpp:1448
constexpr bool starts_with(const view_type &str) const noexcept
Check if the string begins with the given substring.
Definition: conststr.hpp:1763
constexpr bool operator==(const cstr< N, value_type, V2 > &other) const noexcept
Check if the contents of two strings are the same.
Definition: conststr.hpp:1061
constexpr iterator end() noexcept
Get an iterator to the character following the last character of the string.
Definition: conststr.hpp:853
constexpr auto lowercase() const noexcept -> cstr< N, value_type, view_type >
Convert all characters to lowercase. Always be equivalent to transform(charutils::tolower<value_type>...
Definition: conststr.hpp:1656
constexpr auto remove_suffix() const noexcept
Remove Len bytes of suffix. Always be equivalent to substr<0, size() - Len>().
Definition: conststr.hpp:1175
value_type _str[N+1]
Underlying storage. Unless absolutely necessary, you should not access it directly....
Definition: conststr.hpp:1829
constexpr auto insert(const_iterator iter, const value_type &ch) const noexcept -> cstr< N+Count, value_type, view_type >
Insert Count copies of character ch before iterator iter.
Definition: conststr.hpp:1213
constexpr reference get() &noexcept
Tuple-like interface, extracts the Idx-th element from the string.
Definition: conststr.hpp:949
constexpr auto append(const value_type &ch) const noexcept -> cstr< N+Count, value_type, view_type >
Append Count copies of character ch at the end.
Definition: conststr.hpp:1280
constexpr reference back() noexcept
Get the reference to the last character in the string.
Definition: conststr.hpp:1010
static constexpr size_type npos
Indicator of the end of string.
Definition: conststr.hpp:685
constexpr bool ends_with(const view_type &str) const noexcept
Check if the string ends with the given substring.
Definition: conststr.hpp:1792
constexpr auto replace(const_iterator first, const_iterator last) const noexcept -> cstr< N, value_type, view_type > requires(sizeof...(Chs) > 0)
Replaces the characters in the range [max(first, cbegin()), min(last, cend())) according to variable ...
Definition: conststr.hpp:1472
constexpr auto append(const Str &str) const noexcept
Append another string at the end.
Definition: conststr.hpp:1301
constexpr auto remove_prefix() const noexcept
Remove Len bytes of prefix. Always be equivalent to substr<Len>().
Definition: conststr.hpp:1164
constexpr bool operator==(const view_type &other) const noexcept
Check if the contents of two strings are the same.
Definition: conststr.hpp:1075
constexpr const_pointer data() const noexcept
Get the pointer of the underlying array serving as the character storage.
Definition: conststr.hpp:827
constexpr const_reverse_iterator rend() const noexcept
Get a reverse iterator to the character following the last character of the reversed string.
Definition: conststr.hpp:905
constexpr rreference get() &&noexcept
Tuple-like interface, extracts the Idx-th element from the string.
Definition: conststr.hpp:973
constexpr auto with_view() const noexcept -> cstr< N, value_type, V2 >
Change view type.
Definition: conststr.hpp:1128
constexpr auto push(const value_type &ch) const noexcept -> cstr< N+1, value_type >
Push a character to the end of string. Always be equivalent to append(ch).
Definition: conststr.hpp:1523
static constexpr size_type max_size() noexcept
Get the maximum number of characters the string is able to hold. Always the same as size().
Definition: conststr.hpp:803
constexpr auto replace(const_iterator first, const_iterator last, const value_type &ch) const noexcept -> cstr< N, value_type, view_type >
Replaces the characters in the range [max(first, cbegin()), min(last, cend())) with character ch.
Definition: conststr.hpp:1384
constexpr size_type find_if(UnaryPredicate p, size_type pos=0) const noexcept
Find the first character for which predicate p returns true.
Definition: conststr.hpp:1722
constexpr auto transform(UnaryOperation op, size_type pos=0, size_type len=N, const sv_selector< V2 > &svs={}) const noexcept
Apply the given function to each character in the range [pos, min(pos + len, size())).
Definition: conststr.hpp:1558
static constexpr value_type nul
Null terminator with the value '\0'.
Definition: conststr.hpp:680
constexpr auto erase(size_type pos) const noexcept -> cstr< N - 1, value_type, view_type >
Remove the character at position pos.
Definition: conststr.hpp:1489
constexpr iterator begin() noexcept
Get an iterator to the first character of the string.
Definition: conststr.hpp:840
constexpr auto insert(size_type pos, const Str &str) const noexcept
Insert another string at the position pos.
Definition: conststr.hpp:1238
static constexpr bool empty() noexcept
Checks if string is empty.
Definition: conststr.hpp:813
constexpr auto erase(const_iterator iter) const noexcept -> cstr< N - 1, value_type, view_type >
Remove the character pointed by iter.
Definition: conststr.hpp:1507
constexpr const_reference front() const noexcept
Get the reference to the first character in the string.
Definition: conststr.hpp:1003
constexpr size_type rfind_if(UnaryPredicate p, size_type pos=npos) const noexcept
Find the last character for which predicate p returns true.
Definition: conststr.hpp:1736
constexpr cstr(const cstr< N, value_type, V2 > &other)
Copy from another string with different view type.
Definition: conststr.hpp:745
constexpr auto flatten(const cstr< Sizes, value_type, view_type > &...strs) const noexcept
Flatten multiple strings of different lengths.
Definition: conststr.hpp:1315
constexpr auto operator+(const Str &str) const noexcept
Concatenate the contents with another string.
Definition: conststr.hpp:1036
static constexpr size_type size() noexcept
Get size of string, without counting the null terminator.
Definition: conststr.hpp:788
constexpr const_reference get() const &noexcept
Tuple-like interface, extracts the Idx-th element from the string.
Definition: conststr.hpp:961
static constexpr size_type length() noexcept
Alternative API of size(). Get size of string, without counting the null terminator.
Definition: conststr.hpp:795
constexpr auto cut() const noexcept -> cstr< Len, value_type, view_type >
Get the substring containing first Len characters. Always be equivalent to substr<0,...
Definition: conststr.hpp:1154
constexpr const_reverse_iterator rbegin() const noexcept
Get a reverse iterator to the first character of the reversed string.
Definition: conststr.hpp:887
constexpr size_type find(const view_type &str, size_type pos=0) const noexcept
Find the first substring equal to the given substring.
Definition: conststr.hpp:1679
constexpr auto replace(size_type pos, const view_type &str, size_type count=1) const noexcept -> cstr< N, value_type, view_type >
Replaces the characters in the range [pos, min(pos + str.size() * count, size())) with another string...
Definition: conststr.hpp:1404
constexpr cstr(const cstr &)=default
Copy constructor.
constexpr pointer data() noexcept
Get the pointer of the underlying array serving as the character storage.
Definition: conststr.hpp:820
constexpr const_iterator cend() const noexcept
Get an const iterator to the character following the last character of the string.
Definition: conststr.hpp:873
constexpr reference operator[](size_type pos) noexcept
Get the reference to the character at specified location pos.
Definition: conststr.hpp:932
constexpr const_pointer c_str() const noexcept
Get the pointer to a null-terminated character array of contents. Always the same as data().
Definition: conststr.hpp:834
constexpr reverse_iterator rbegin() noexcept
Get a reverse iterator to the first character of the reversed string.
Definition: conststr.hpp:879
constexpr bool starts_with(const value_type &ch) const noexcept
Check if the string begins with the given character.
Definition: conststr.hpp:1750
constexpr auto replace(const_iterator first, const_iterator last, const view_type &str) const noexcept -> cstr< N, value_type, view_type >
Replaces the characters in the range [max(first, cbegin()), min(last, cend())) with another string st...
Definition: conststr.hpp:1424
constexpr cstr(const value_type(&str)[N+1], const sv_selector< view_type > &svs={}) noexcept
Construct string from string literal.
Definition: conststr.hpp:708
constexpr const_reverse_iterator crbegin() const noexcept
Get a const reverse iterator to the first character of the reversed string.
Definition: conststr.hpp:914
constexpr const_iterator end() const noexcept
Get an iterator to the character following the last character of the string.
Definition: conststr.hpp:860
constexpr bool contains(const view_type &str) const noexcept
Check if the string contains the given substring. Always be equivalent to find(str) !...
Definition: conststr.hpp:1821
constexpr const_reverse_iterator crend() const noexcept
Get a const reverse iterator to the character following the last character of the reversed string.
Definition: conststr.hpp:923
String view type selector. Just an empty struct.
Definition: conststr.hpp:617