diff --git a/include/fmt/base.h b/include/fmt/base.h index 9d8c54a9..bce0307c 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -2753,7 +2753,8 @@ inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } /// A compile-time format string. template class fstring { private: - basic_string_view str_; + const Char* str_; + size_t size_; static constexpr int num_static_named_args = detail::count_static_named_args(); @@ -2768,10 +2769,9 @@ template class fstring { using t = fstring; // Reports a compile-time error if S is not a valid format string for T. - template >::value)> - FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str_(s) { + template + FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const Char (&s)[N]) + : str_(s), size_(N - 1) { using namespace detail; static_assert(count<(std::is_base_of>::value && std::is_reference::value)...>() == 0, @@ -2779,23 +2779,43 @@ template class fstring { if (FMT_USE_CONSTEVAL) parse_format_string(s, checker(s, arg_pack())); #ifdef FMT_ENFORCE_COMPILE_STRING static_assert( - FMT_USE_CONSTEVAL && sizeof(S) != 0, + FMT_USE_CONSTEVAL && sizeof(s) != 0, + "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING"); +#endif + } + template >::value)> + FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) { + auto sv = basic_string_view(s); + str_ = sv.data(); + size_ = sv.size(); + if (FMT_USE_CONSTEVAL) + detail::parse_format_string(s, checker(s, arg_pack())); +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert( + FMT_USE_CONSTEVAL && sizeof(s) != 0, "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING"); #endif } template ::value&& std::is_same::value)> - FMT_ALWAYS_INLINE fstring(const S& s) : str_(s) { - FMT_CONSTEXPR auto fmt = basic_string_view(S()); + FMT_ALWAYS_INLINE fstring(const S&) { + FMT_CONSTEXPR auto sv = basic_string_view(S()); + str_ = sv.data(); + size_ = sv.size(); FMT_CONSTEXPR int ignore = - (parse_format_string(fmt, checker(fmt, arg_pack())), 0); + (parse_format_string(sv, checker(sv, arg_pack())), 0); detail::ignore_unused(ignore); } - fstring(runtime_format_string fmt) : str_(fmt.str) {} + fstring(runtime_format_string fmt) + : str_(fmt.str.data()), size_(fmt.str.size()) {} - FMT_ALWAYS_INLINE operator basic_string_view() const { return str_; } - auto get() const -> basic_string_view { return str_; } + FMT_ALWAYS_INLINE operator basic_string_view() const { + return {str_, size_}; + } + auto get() const -> basic_string_view { return {str_, size_}; } }; template using format_string = typename fstring::t;