14#include <nlohmann/json.hpp>
20template <
typename T, T...xs>
22 static constexpr const T
value[
sizeof...(xs)+1] = {xs..., T() };
38 typename Traits = std::char_traits<CharT>
41 std::basic_string_view<CharT,Traits>
view;
67 :
view(
reify<CharT,xs...>::value,sizeof...(xs)) {}
94 operator CharT const * () const noexcept {
99 operator std::basic_string_view<CharT,Traits>() const noexcept {
104 operator std::basic_string<CharT,Traits>() const noexcept {
119 if (i >=
view.size())
throw std::out_of_range(
"basic_static_string::at");
157 explicit operator bool () const noexcept {
return view; }
166 return self.view.data() == that.view.data();
168 return (self.view.data() == that.view.data()) || (self.view == that.view);
176 return self.view.data() != that.view.data();
178 return (self.view.data() != that.view.data()) && (self.view != that.view);
201 auto end() const noexcept {
return view.end(); }
229 static constexpr size_type npos = std::basic_string_view<CharT,Traits>::npos;
232template <
typename CharT,
typename Traits>
238template <
typename CharT, CharT...xs>
300 operator const
char * () const noexcept {
return p; }
306 const char *
data() const noexcept {
return p; }
324 auto begin() const noexcept {
return p; }
327 auto end() const noexcept {
return p + strlen(
p); }
335 auto cend() const noexcept {
return p + strlen(
p); }
339 auto rbegin() const noexcept {
return std::reverse_iterator<const char *>(
end()); }
343 auto rend() const noexcept {
return std::reverse_iterator<const char *>(
begin()); }
347 auto crbegin() const noexcept {
return std::reverse_iterator<const char *>(
end()); }
351 auto crend() const noexcept {
return std::reverse_iterator<const char *>(
begin()); }
364# pragma GCC diagnostic push
365# pragma GCC diagnostic ignored "-Wpedantic"
368# pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
375template <
class T, T ...xs>
380template <one_of_t<
char> T, T ...xs>
386# pragma GCC diagnostic pop
397 template <
typename CharT,
typename Traits>
400 return reinterpret_cast<size_t>(s.data());
406 return reinterpret_cast<size_t>(s.data());
412 template<
class CharT,
class Traits >
413 inline constexpr bool enable_borrowed_range<::ein::basic_static_string<CharT, Traits>> =
true;
415 template<
class CharT,
class Traits >
416 inline constexpr bool enable_view<::ein::basic_static_string<CharT, Traits>> =
true;
419 inline constexpr bool enable_borrowed_range<::ein::static_c_string> =
true;
422 inline constexpr bool enable_view<::ein::static_c_string> =
true;
429#define EIN_STR(name) \
430 (([]<typename CharT> static constexpr { \
431 if constexpr (std::is_same_v<CharT, char>) { \
432 return #name ## _ss; \
433 } else if constexpr (std::is_same_v<CharT, wchar_t>) { \
434 return L## #name ##_ss; \
435 } else if constexpr (std::is_same_v<CharT, char8_t>) { \
436 return u8## #name ##_ss; \
437 } else if constexpr (std::is_same_v<CharT, char16_t>) { \
438 return u## #name ##_ss; \
439 } else if constexpr (std::is_same_v<CharT, char32_t>) { \
440 return U## #name ##_ss; \
442 }).template operator()<TestType>())
444TEMPLATE_TEST_CASE(
"static_string",
"[static_string]",
char,
wchar_t,
char8_t,
char16_t,
char32_t) {
448 SECTION(
"constructors and conversions") {
450 constexpr string_t str = EIN_STR(hello);
451 CHECK(str == EIN_STR(hello));
452 CHECK(str != EIN_STR(world));
455 CHECK(str.data()[5] ==
typename string_t::value_type(0));
458 SECTION(
"element access") {
459 constexpr string_t str = EIN_STR(abcdef);
460 CHECK(str.front() ==
'a');
461 CHECK(str.back() ==
'f');
462 CHECK(str[1] ==
'b');
463 CHECK(str.at(2) ==
'c');
466 SECTION(
"comparisons") {
467 constexpr string_t str1 = EIN_STR(compare);
468 constexpr string_t str2 = EIN_STR(compare);
469 constexpr string_t str3 = EIN_STR(different);
475 SECTION(
"iterators") {
476 constexpr string_t str = EIN_STR(iterate);
477 std::basic_string<TestType> result;
480 CHECK(result == EIN_STR(iterate).data());
483 std::basic_string<typename string_t::value_type> reverse_result;
484 for (
auto it = str.rbegin(); it != str.rend(); ++it)
485 reverse_result += *it;
486 CHECK(reverse_result == EIN_STR(etareti).data());
489 SECTION(
"I/O operations") {
490 constexpr string_t str = EIN_STR(output);
491 std::basic_ostringstream<TestType> oss;
493 CHECK(oss.str()[3] ==
'p');
statically known interned strings these have O(1) comparison for equality
constexpr auto cend() const noexcept
consteval basic_static_string(std::integer_sequence< CharT, xs... >)
constexpr friend void swap(basic_static_string &x, basic_static_string &y) noexcept
constexpr CharT const & at(size_type i) const
access the specified character with bounds checking
CharT const & const_reference
std::basic_string_view< CharT, Traits > view
constexpr auto cbegin() const noexcept
constexpr size_type length() const noexcept
constexpr basic_static_string(std::basic_string_view< CharT, Traits > view)
constexpr auto crbegin() const noexcept
friend constexpr bool operator==(basic_static_string self, basic_static_string that) noexcept
constexpr CharT const & operator[](size_type i) const noexcept
access the specified character
std::reverse_iterator< const_iterator > const_reverse_iterator
std::ptrdiff_t difference_type
constexpr const_pointer data() const noexcept
const_reverse_iterator reverse_iterator
constexpr basic_static_string() noexcept=default
constexpr bool empty() const noexcept
constexpr size_type size() const noexcept
constexpr const_reference front() const noexcept
Returns reference to the first character in the static_string.
constexpr auto begin() const noexcept
constexpr const_reference back() const noexcept
constexpr auto rend() const noexcept
constexpr auto end() const noexcept
constexpr auto crend() const noexcept
CharT const * const_pointer
friend constexpr basic_ostream< CharT, Traits > & operator<<(basic_ostream< CharT, Traits > &os, basic_static_string< CharT, Traits > v)
input/output
static constexpr size_type npos
CharT const * const_iterator
constexpr size_type max_size() const noexcept
constexpr auto rbegin() const noexcept
friend constexpr bool operator!=(basic_static_string self, basic_static_string that) noexcept
std::ptrdiff_t difference_type
constexpr auto crbegin() const noexcept
O(n)
constexpr friend bool operator!=(static_c_string x, static_c_string y) noexcept
std::reverse_iterator< const_iterator > const_reverse_iterator
constexpr auto end() const noexcept
friend void swap(static_c_string &x, static_c_string &y) noexcept
constexpr auto rbegin() const noexcept
O(n)
constexpr auto crend() const noexcept
O(1)
ein_reinitializes constexpr static_c_string & operator=(static_c_string const &) noexcept=default
constexpr auto begin() const noexcept
O(1)
char const * const_iterator
constexpr auto cend() const noexcept
O(1)
char const & const_reference
std::char_traits< char > traits_type
char const * const_pointer
constexpr friend bool operator==(static_c_string x, static_c_string y) noexcept
constexpr const char * data() const noexcept
const_reverse_iterator reverse_iterator
constexpr auto rend() const noexcept
O(1)
constexpr static_c_string() noexcept=default
constexpr auto cbegin() const noexcept
O(1)
type T is one of the candidates
#define ein_reinitializes
[[clang::reinitializes]]
#define ein_artificial
[[artificial]].
#define ein_inline
inline [[always_inline]]
#define ein_nodiscard
C++17 [[nodiscard]].
#define ein_const
[[const]] is not const
basic_static_string< char > static_string
void to_json(nlohmann::json &j, const basic_static_string< CharT, Traits > &s)
static constexpr const T value[sizeof...(xs)+1]
constexpr size_t operator()(::ein::basic_static_string< CharT, Traits > const &s) const noexcept
constexpr size_t operator()(::ein::static_c_string s) const noexcept