#pragma once #if __cplusplus >= 202002L #include #include #include #include #include #include namespace stdx { inline namespace v1 { template struct ct_string { CONSTEVAL ct_string() = default; // NOLINTNEXTLINE(*-avoid-c-arrays, google-explicit-constructor) CONSTEVAL explicit(false) ct_string(char const (&str)[N]) { for (auto i = std::size_t{}; i < N; ++i) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*) value[i] = str[i]; } } CONSTEVAL explicit(true) ct_string(char const *str, std::size_t sz) { for (auto i = std::size_t{}; i < sz; ++i) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*) value[i] = str[i]; } } CONSTEVAL explicit(true) ct_string(std::string_view str) : ct_string{str.data(), str.size()} {} [[nodiscard]] constexpr auto begin() LIFETIMEBOUND { return value.begin(); } [[nodiscard]] constexpr auto end() LIFETIMEBOUND { return value.end() - 1; } [[nodiscard]] constexpr auto begin() const LIFETIMEBOUND { return value.begin(); } [[nodiscard]] constexpr auto end() const LIFETIMEBOUND { return value.end() - 1; } [[nodiscard]] constexpr auto rbegin() const LIFETIMEBOUND { return ++value.rbegin(); } [[nodiscard]] constexpr auto rend() const LIFETIMEBOUND { return value.rend(); } constexpr static std::integral_constant capacity{}; constexpr static std::integral_constant size{}; constexpr static std::integral_constant empty{}; constexpr explicit(true) operator std::string_view() const { return std::string_view{value.data(), size()}; } std::array value{}; }; template [[nodiscard]] constexpr auto operator==(ct_string const &lhs, ct_string const &rhs) -> bool { return static_cast(lhs) == static_cast(rhs); } template