This commit is contained in:
Victor Zverovich 2024-09-08 10:00:25 -07:00
parent 2d3ba32e79
commit 047bf75c24
2 changed files with 55 additions and 22 deletions

View File

@ -2812,29 +2812,29 @@ template <typename Char = char> struct runtime_format_string {
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
/// A compile-time format string.
template <typename Char, typename... T> struct fstring {
template <typename... T> struct fstring {
private:
static constexpr int num_static_named_args =
detail::count_static_named_args<T...>();
using checker = detail::format_string_checker<
Char, static_cast<int>(sizeof...(T)), num_static_named_args,
char, static_cast<int>(sizeof...(T)), num_static_named_args,
num_static_named_args != detail::count_named_args<T...>()>;
using arg_pack = detail::arg_pack<T...>;
public:
basic_string_view<Char> str;
string_view str;
using t = fstring;
// Reports a compile-time error if S is not a valid format string for T.
template <size_t N>
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const Char (&s)[N]) : str(s, N - 1) {
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const char (&s)[N]) : str(s, N - 1) {
using namespace detail;
static_assert(count<(std::is_base_of<view, remove_reference_t<T>>::value &&
std::is_reference<T>::value)...>() == 0,
"passing views as lvalues is disallowed");
if (FMT_USE_CONSTEVAL) parse_format_string<Char>(s, checker(s, arg_pack()));
if (FMT_USE_CONSTEVAL) parse_format_string<char>(s, checker(s, arg_pack()));
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(
FMT_USE_CONSTEVAL && sizeof(s) != 0,
@ -2842,11 +2842,10 @@ template <typename Char, typename... T> struct fstring {
#endif
}
template <typename S,
FMT_ENABLE_IF(
std::is_convertible<const S&, basic_string_view<Char>>::value)>
FMT_ENABLE_IF(std::is_convertible<const S&, string_view>::value)>
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
if (FMT_USE_CONSTEVAL)
detail::parse_format_string<Char>(s, checker(s, arg_pack()));
detail::parse_format_string<char>(s, checker(s, arg_pack()));
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(
FMT_USE_CONSTEVAL && sizeof(s) != 0,
@ -2855,23 +2854,21 @@ template <typename Char, typename... T> struct fstring {
}
template <typename S,
FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
std::is_same<typename S::char_type, Char>::value)>
std::is_same<typename S::char_type, char>::value)>
FMT_ALWAYS_INLINE fstring(const S&) : str(S()) {
FMT_CONSTEXPR auto sv = basic_string_view<Char>(S());
FMT_CONSTEXPR auto sv = string_view(S());
FMT_CONSTEXPR int ignore =
(parse_format_string(sv, checker(sv, arg_pack())), 0);
detail::ignore_unused(ignore);
}
fstring(runtime_format_string<Char> fmt) : str(fmt.str) {}
fstring(runtime_format_string<> fmt) : str(fmt.str) {}
// Returning by reference generates better code in debug mode.
FMT_ALWAYS_INLINE operator const basic_string_view<Char>&() const {
return str;
}
auto get() const -> basic_string_view<Char> { return str; }
FMT_ALWAYS_INLINE operator const string_view&() const { return str; }
auto get() const -> string_view { return str; }
};
template <typename... T> using format_string = typename fstring<char, T...>::t;
template <typename... T> using format_string = typename fstring<T...>::t;
template <typename T, typename Char = char>
using is_formattable = bool_constant<

View File

@ -65,11 +65,49 @@ using wformat_context = buffered_context<wchar_t>;
using wformat_args = basic_format_args<wformat_context>;
using wmemory_buffer = basic_memory_buffer<wchar_t>;
template <typename Char, typename... T> struct basic_fstring {
private:
basic_string_view<Char> str_;
static constexpr int num_static_named_args =
detail::count_static_named_args<T...>();
using checker = detail::format_string_checker<
Char, static_cast<int>(sizeof...(T)), num_static_named_args,
num_static_named_args != detail::count_named_args<T...>()>;
using arg_pack = detail::arg_pack<T...>;
public:
using t = basic_fstring;
template <typename S,
FMT_ENABLE_IF(
std::is_convertible<const S&, basic_string_view<Char>>::value)>
FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_fstring(const S& s) : str_(s) {
if (FMT_USE_CONSTEVAL)
detail::parse_format_string<Char>(s, checker(s, arg_pack()));
}
template <typename S,
FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
std::is_same<typename S::char_type, Char>::value)>
FMT_ALWAYS_INLINE basic_fstring(const S&) : str_(S()) {
FMT_CONSTEXPR auto sv = basic_string_view<Char>(S());
FMT_CONSTEXPR int ignore =
(parse_format_string(sv, checker(sv, arg_pack())), 0);
detail::ignore_unused(ignore);
}
basic_fstring(runtime_format_string<Char> fmt) : str_(fmt.str) {}
operator basic_string_view<Char>() const { return str_; }
auto get() const -> basic_string_view<Char> { return str_; }
};
template <typename Char, typename... T>
using basic_format_string = fstring<Char, T...>;
using basic_format_string = basic_fstring<Char, T...>;
template <typename... T>
using wformat_string = typename fstring<wchar_t, T...>::t;
using wformat_string = typename basic_format_string<wchar_t, T...>::t;
inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
return {{s}};
}
@ -318,14 +356,12 @@ inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) {
}
template <typename... T>
void print(std::wostream& os, typename fstring<wchar_t, T...>::t fmt,
T&&... args) {
void print(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
vprint(os, fmt, fmt::make_format_args<buffered_context<wchar_t>>(args...));
}
template <typename... T>
void println(std::wostream& os, typename fstring<wchar_t, T...>::t fmt,
T&&... args) {
void println(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
print(os, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
}