#pragma once #include #include namespace utempl { template struct ConstexprString; } // namespace utempl template struct fmt::formatter> : public fmt::formatter { constexpr auto parse(format_parse_context& ctx) const { return ctx.begin(); }; inline constexpr auto format(const utempl::ConstexprString& str, auto& ctx) const { return fmt::formatter::format({str.begin()}, ctx); }; }; namespace utempl { template struct ConstexprString { std::array data; inline constexpr auto begin() -> char* { return this->data.begin(); }; inline constexpr auto begin() const -> const char* { return this->data.begin(); }; inline constexpr auto end() -> char* { return this->data.end(); }; inline constexpr auto end() const -> const char* { return this->data.end(); }; static constexpr auto kSize = Size == 0 ? 0 : Size - 1; inline constexpr ConstexprString() = default; inline constexpr ConstexprString(const char (&data)[Size]) : data{} { std::ranges::copy_n(data, Size, this->data.begin()); }; inline constexpr ConstexprString(std::string data) : data{} { std::ranges::copy_n(data.begin(), Size, this->data.begin()); }; inline constexpr ConstexprString(std::array data) : data(std::move(data)) {}; inline constexpr auto size() const { return Size == 0 ? 0 : Size - 1; }; inline constexpr operator std::string_view() const & { return {this->begin()}; }; inline constexpr bool operator==(std::string_view other) const { return static_cast(*this) == other; }; inline constexpr bool operator==(const ConstexprString& other) const { return static_cast(*this) == static_cast(other); }; template inline constexpr bool operator==(const ConstexprString& other) const { return false; }; inline constexpr bool operator==(const std::string& other) const { return static_cast(*this) == other; }; template inline constexpr auto operator+(const ConstexprString& other) -> ConstexprString { ConstexprString response; std::ranges::copy_n(this->begin(), Size - 1, response.begin()); std::ranges::copy_n(other.begin(), SSize, response.begin() + Size - 1); return response; }; inline constexpr ConstexprString(const ConstexprString&) = default; inline constexpr ConstexprString(ConstexprString&&) = default; }; template inline constexpr auto operator<<(std::ostream& stream, const ConstexprString& str) -> std::ostream& { stream << static_cast(str); return stream; }; template inline constexpr auto CreateStringWith(char c) { ConstexprString str = {}; for(std::size_t i = 0; i < Count; i++) { str.data[i] = c; }; str.data[Count] = '\0'; return str; }; template ConstexprString(const char (&data)[Size]) -> ConstexprString; } // namespace utempl