mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-08 12:20:06 +00:00
Cleanup format API
This commit is contained in:
parent
ab44ee7521
commit
6f62db098a
@ -837,7 +837,7 @@ struct format_specs : basic_specs {
|
||||
*/
|
||||
template <typename Char = char> class parse_context {
|
||||
private:
|
||||
basic_string_view<Char> format_str_;
|
||||
basic_string_view<Char> fmt_;
|
||||
int next_arg_id_;
|
||||
|
||||
enum { use_constexpr_cast = !FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200 };
|
||||
@ -848,22 +848,20 @@ template <typename Char = char> class parse_context {
|
||||
using char_type = Char;
|
||||
using iterator = const Char*;
|
||||
|
||||
explicit constexpr parse_context(basic_string_view<Char> format_str,
|
||||
explicit constexpr parse_context(basic_string_view<Char> fmt,
|
||||
int next_arg_id = 0)
|
||||
: format_str_(format_str), next_arg_id_(next_arg_id) {}
|
||||
: fmt_(fmt), next_arg_id_(next_arg_id) {}
|
||||
|
||||
/// Returns an iterator to the beginning of the format string range being
|
||||
/// parsed.
|
||||
constexpr auto begin() const noexcept -> iterator {
|
||||
return format_str_.begin();
|
||||
}
|
||||
constexpr auto begin() const noexcept -> iterator { return fmt_.begin(); }
|
||||
|
||||
/// Returns an iterator past the end of the format string range being parsed.
|
||||
constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
|
||||
constexpr auto end() const noexcept -> iterator { return fmt_.end(); }
|
||||
|
||||
/// Advances the begin iterator to `it`.
|
||||
FMT_CONSTEXPR void advance_to(iterator it) {
|
||||
format_str_.remove_prefix(detail::to_unsigned(it - begin()));
|
||||
fmt_.remove_prefix(detail::to_unsigned(it - begin()));
|
||||
}
|
||||
|
||||
/// Reports an error if using the manual argument indexing; otherwise returns
|
||||
@ -1273,10 +1271,10 @@ class compile_parse_context : public parse_context<Char> {
|
||||
using base = parse_context<Char>;
|
||||
|
||||
public:
|
||||
explicit FMT_CONSTEXPR compile_parse_context(
|
||||
basic_string_view<Char> format_str, int num_args, const type* types,
|
||||
int next_arg_id = 0)
|
||||
: base(format_str, next_arg_id), num_args_(num_args), types_(types) {}
|
||||
explicit FMT_CONSTEXPR compile_parse_context(basic_string_view<Char> fmt,
|
||||
int num_args, const type* types,
|
||||
int next_arg_id = 0)
|
||||
: base(fmt, next_arg_id), num_args_(num_args), types_(types) {}
|
||||
|
||||
constexpr auto num_args() const -> int { return num_args_; }
|
||||
constexpr auto arg_type(int id) const -> type { return types_[id]; }
|
||||
|
@ -2133,7 +2133,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
detail::arg_ref<Char> width_ref_;
|
||||
detail::arg_ref<Char> precision_ref_;
|
||||
bool localized_ = false;
|
||||
basic_string_view<Char> format_str_;
|
||||
basic_string_view<Char> fmt_;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
@ -2159,7 +2159,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
++it;
|
||||
}
|
||||
end = detail::parse_chrono_format(it, end, checker);
|
||||
format_str_ = {it, detail::to_unsigned(end - it)};
|
||||
fmt_ = {it, detail::to_unsigned(end - it)};
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -2169,7 +2169,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
auto specs = specs_;
|
||||
auto precision = specs.precision;
|
||||
specs.precision = -1;
|
||||
auto begin = format_str_.begin(), end = format_str_.end();
|
||||
auto begin = fmt_.begin(), end = fmt_.end();
|
||||
// As a possible future optimization, we could avoid extra copying if width
|
||||
// is not specified.
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
@ -2200,7 +2200,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
detail::arg_ref<Char> width_ref_;
|
||||
|
||||
protected:
|
||||
basic_string_view<Char> format_str_;
|
||||
basic_string_view<Char> fmt_;
|
||||
|
||||
template <typename Duration, typename FormatContext>
|
||||
auto do_format(const std::tm& tm, FormatContext& ctx,
|
||||
@ -2215,7 +2215,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
|
||||
auto w =
|
||||
detail::tm_writer<decltype(out), Char, Duration>(loc, out, tm, subsecs);
|
||||
detail::parse_chrono_format(format_str_.begin(), format_str_.end(), w);
|
||||
detail::parse_chrono_format(fmt_.begin(), fmt_.end(), w);
|
||||
return detail::write(
|
||||
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
|
||||
}
|
||||
@ -2235,8 +2235,8 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
}
|
||||
|
||||
end = detail::parse_chrono_format(it, end, detail::tm_format_checker());
|
||||
// Replace the default format_str only if the new spec is not empty.
|
||||
if (end != it) format_str_ = {it, detail::to_unsigned(end - it)};
|
||||
// Replace the default format string only if the new spec is not empty.
|
||||
if (end != it) fmt_ = {it, detail::to_unsigned(end - it)};
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -2250,7 +2250,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename Char, typename Duration>
|
||||
struct formatter<sys_time<Duration>, Char> : formatter<std::tm, Char> {
|
||||
FMT_CONSTEXPR formatter() {
|
||||
this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>();
|
||||
this->fmt_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
@ -2292,7 +2292,7 @@ struct formatter<utc_time<Duration>, Char>
|
||||
template <typename Duration, typename Char>
|
||||
struct formatter<local_time<Duration>, Char> : formatter<std::tm, Char> {
|
||||
FMT_CONSTEXPR formatter() {
|
||||
this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>();
|
||||
this->fmt_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
|
@ -964,6 +964,14 @@ class basic_memory_buffer : public detail::buffer<T> {
|
||||
|
||||
using memory_buffer = basic_memory_buffer<char>;
|
||||
|
||||
template <typename Char, size_t SIZE>
|
||||
FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)
|
||||
-> std::basic_string<Char> {
|
||||
auto size = buf.size();
|
||||
detail::assume(size < std::basic_string<Char>().max_size());
|
||||
return std::basic_string<Char>(buf.data(), size);
|
||||
}
|
||||
|
||||
// A writer to a buffered stream. It doesn't own the underlying stream.
|
||||
class writer {
|
||||
private:
|
||||
@ -3880,11 +3888,39 @@ FMT_API void report_error(format_func func, int error_code,
|
||||
template <typename T>
|
||||
struct has_format_as
|
||||
: bool_constant<!std::is_same<format_as_t<T>, void>::value> {};
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
|
||||
-> thousands_sep_result<char>;
|
||||
extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
|
||||
-> thousands_sep_result<wchar_t>;
|
||||
extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
|
||||
extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
|
||||
#endif // FMT_HEADER_ONLY
|
||||
|
||||
FMT_END_EXPORT
|
||||
|
||||
template <typename T, typename Char, type TYPE>
|
||||
template <typename FormatContext>
|
||||
FMT_CONSTEXPR auto native_formatter<T, Char, TYPE>::format(
|
||||
const T& val, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
if (!specs_.dynamic())
|
||||
return write<Char>(ctx.out(), val, specs_, ctx.locale());
|
||||
auto specs = format_specs(specs_);
|
||||
handle_dynamic_spec(specs.dynamic_width(), specs.width, specs_.width_ref,
|
||||
ctx);
|
||||
handle_dynamic_spec(specs.dynamic_precision(), specs.precision,
|
||||
specs_.precision_ref, ctx);
|
||||
return write<Char>(ctx.out(), val, specs, ctx.locale());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
FMT_API auto vsystem_error(int error_code, string_view format_str,
|
||||
format_args args) -> std::system_error;
|
||||
FMT_API auto vsystem_error(int error_code, string_view fmt, format_args args)
|
||||
-> std::system_error;
|
||||
|
||||
/**
|
||||
* Constructs `std::system_error` with a message formatted with
|
||||
@ -4196,80 +4232,6 @@ template <typename T, typename Char = char> struct nested_formatter {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts `value` to `std::string` using the default format for type `T`.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* std::string answer = fmt::to_string(42);
|
||||
*/
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
|
||||
!detail::has_format_as<T>::value)>
|
||||
inline auto to_string(const T& value) -> std::string {
|
||||
auto buffer = memory_buffer();
|
||||
detail::write<char>(appender(buffer), value);
|
||||
return {buffer.data(), buffer.size()};
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
FMT_NODISCARD inline auto to_string(T value) -> std::string {
|
||||
// The buffer should be large enough to store the number including the sign
|
||||
// or "false" for bool.
|
||||
constexpr int max_size = detail::digits10<T>() + 2;
|
||||
char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
|
||||
char* begin = buffer;
|
||||
return std::string(begin, detail::write<char>(begin, value));
|
||||
}
|
||||
|
||||
template <typename Char, size_t SIZE>
|
||||
FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)
|
||||
-> std::basic_string<Char> {
|
||||
auto size = buf.size();
|
||||
detail::assume(size < std::basic_string<Char>().max_size());
|
||||
return std::basic_string<Char>(buf.data(), size);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
|
||||
detail::has_format_as<T>::value)>
|
||||
inline auto to_string(const T& value) -> std::string {
|
||||
return to_string(format_as(value));
|
||||
}
|
||||
|
||||
FMT_END_EXPORT
|
||||
|
||||
namespace detail {
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
|
||||
-> thousands_sep_result<char>;
|
||||
extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
|
||||
-> thousands_sep_result<wchar_t>;
|
||||
extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
|
||||
extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
|
||||
#endif // FMT_HEADER_ONLY
|
||||
|
||||
FMT_END_EXPORT
|
||||
|
||||
template <typename T, typename Char, type TYPE>
|
||||
template <typename FormatContext>
|
||||
FMT_CONSTEXPR auto native_formatter<T, Char, TYPE>::format(
|
||||
const T& val, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
if (!specs_.dynamic())
|
||||
return write<Char>(ctx.out(), val, specs_, ctx.locale());
|
||||
auto specs = format_specs(specs_);
|
||||
handle_dynamic_spec(specs.dynamic_width(), specs.width, specs_.width_ref,
|
||||
ctx);
|
||||
handle_dynamic_spec(specs.dynamic_precision(), specs.precision,
|
||||
specs_.precision_ref, ctx);
|
||||
return write<Char>(ctx.out(), val, specs, ctx.locale());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<detail::float128, Char>
|
||||
: detail::native_formatter<detail::float128, Char,
|
||||
@ -4298,32 +4260,15 @@ constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> {
|
||||
} // namespace literals
|
||||
#endif // FMT_USE_USER_LITERALS
|
||||
|
||||
FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
|
||||
|
||||
/**
|
||||
* Formats `args` according to specifications in `fmt` and returns the result
|
||||
* as a string.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* #include <fmt/format.h>
|
||||
* std::string message = fmt::format("The answer is {}.", 42);
|
||||
*/
|
||||
template <typename... T>
|
||||
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
|
||||
-> std::string {
|
||||
return vformat(fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
|
||||
inline auto vformat(const Locale& loc, string_view fmt, format_args args)
|
||||
auto vformat(const Locale& loc, string_view fmt, format_args args)
|
||||
-> std::string {
|
||||
return detail::vformat(loc, fmt, args);
|
||||
}
|
||||
|
||||
template <typename Locale, typename... T,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
|
||||
inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
|
||||
FMT_INLINE auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
|
||||
-> std::string {
|
||||
return fmt::vformat(loc, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
@ -4343,7 +4288,7 @@ template <typename OutputIt, typename Locale, typename... T,
|
||||
detail::is_locale<Locale>::value)>
|
||||
FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
|
||||
format_string<T...> fmt, T&&... args) -> OutputIt {
|
||||
return vformat_to(out, loc, fmt.str, vargs<T...>{{args...}});
|
||||
return fmt::vformat_to(out, loc, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
template <typename Locale, typename... T,
|
||||
@ -4357,6 +4302,54 @@ FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc,
|
||||
return buf.count();
|
||||
}
|
||||
|
||||
FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
|
||||
|
||||
/**
|
||||
* Formats `args` according to specifications in `fmt` and returns the result
|
||||
* as a string.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* #include <fmt/format.h>
|
||||
* std::string message = fmt::format("The answer is {}.", 42);
|
||||
*/
|
||||
template <typename... T>
|
||||
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
|
||||
-> std::string {
|
||||
return vformat(fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `value` to `std::string` using the default format for type `T`.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* std::string answer = fmt::to_string(42);
|
||||
*/
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
FMT_NODISCARD auto to_string(T value) -> std::string {
|
||||
// The buffer should be large enough to store the number including the sign
|
||||
// or "false" for bool.
|
||||
constexpr int max_size = detail::digits10<T>() + 2;
|
||||
char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
|
||||
char* begin = buffer;
|
||||
return std::string(buffer, detail::write<char>(begin, value));
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
|
||||
!detail::has_format_as<T>::value)>
|
||||
FMT_NODISCARD auto to_string(const T& value) -> std::string {
|
||||
auto buffer = memory_buffer();
|
||||
detail::write<char>(appender(buffer), value);
|
||||
return {buffer.data(), buffer.size()};
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
|
||||
detail::has_format_as<T>::value)>
|
||||
FMT_NODISCARD auto to_string(const T& value) -> std::string {
|
||||
return to_string(format_as(value));
|
||||
}
|
||||
|
||||
FMT_END_EXPORT
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
|
@ -118,7 +118,7 @@ FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||
const char* message) noexcept;
|
||||
}
|
||||
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
|
||||
format_args args);
|
||||
|
||||
/**
|
||||
@ -164,8 +164,8 @@ inline auto system_category() noexcept -> const std::error_category& {
|
||||
// std::system is not available on some platforms such as iOS (#2248).
|
||||
#ifdef __OSX__
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
void say(const S& format_str, Args&&... args) {
|
||||
std::system(format("say \"{}\"", format(format_str, args...)).c_str());
|
||||
void say(const S& fmt, Args&&... args) {
|
||||
std::system(format("say \"{}\"", format(fmt, args...)).c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -162,11 +162,11 @@ auto join(const std::tuple<T...>& tuple, basic_string_view<wchar_t> sep)
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
auto vformat(basic_string_view<Char> format_str,
|
||||
auto vformat(basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> std::basic_string<Char> {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
detail::vformat_to(buf, fmt, args);
|
||||
return to_string(buf);
|
||||
}
|
||||
|
||||
@ -188,8 +188,8 @@ template <typename S, typename... T,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
|
||||
!std::is_same<Char, wchar_t>::value)>
|
||||
auto format(const S& format_str, T&&... args) -> std::basic_string<Char> {
|
||||
return vformat(detail::to_string_view(format_str),
|
||||
auto format(const S& fmt, T&&... args) -> std::basic_string<Char> {
|
||||
return vformat(detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -210,9 +210,9 @@ template <typename Locale, typename S, typename... T,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format(const Locale& loc, const S& format_str, T&&... args)
|
||||
inline auto format(const Locale& loc, const S& fmt, T&&... args)
|
||||
-> std::basic_string<Char> {
|
||||
return vformat(loc, detail::to_string_view(format_str),
|
||||
return vformat(loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -220,10 +220,10 @@ template <typename OutputIt, typename S,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
auto vformat_to(OutputIt out, const S& format_str,
|
||||
auto vformat_to(OutputIt out, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args) -> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, detail::to_string_view(format_str), args);
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args);
|
||||
return detail::get_iterator(buf, out);
|
||||
}
|
||||
|
||||
@ -242,12 +242,11 @@ template <typename Locale, typename S, typename OutputIt, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to(OutputIt out, const Locale& loc, const S& format_str,
|
||||
inline auto vformat_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
vformat_to(buf, detail::to_string_view(format_str), args,
|
||||
detail::locale_ref(loc));
|
||||
vformat_to(buf, detail::to_string_view(fmt), args, detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf, out);
|
||||
}
|
||||
|
||||
@ -256,23 +255,22 @@ template <typename OutputIt, typename Locale, typename S, typename... T,
|
||||
bool enable = detail::is_output_iterator<OutputIt, Char>::value &&
|
||||
detail::is_locale<Locale>::value &&
|
||||
detail::is_exotic_char<Char>::value>
|
||||
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
|
||||
inline auto format_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
T&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, loc, detail::to_string_view(format_str),
|
||||
return vformat_to(out, loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to_n(OutputIt out, size_t n,
|
||||
basic_string_view<Char> format_str,
|
||||
inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
detail::vformat_to(buf, fmt, args);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user