diff --git a/include/fmt/compile.h b/include/fmt/compile.h index ea9ef97e..becf0fe0 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -469,7 +469,7 @@ template struct spec_field { formatter fmt; template - constexpr OutputIt format(OutputIt out, const Args&... args) { + constexpr OutputIt format(OutputIt out, const Args&... args) const { // This ensures that the argument type is convertile to `const T&`. const T& arg = get(args...); const auto& vargs = @@ -488,7 +488,7 @@ template struct concat { using char_type = typename L::char_type; template - constexpr OutputIt format(OutputIt out, const Args&... args) { + constexpr OutputIt format(OutputIt out, const Args&... args) const { out = lhs.format(out, args...); return rhs.format(out, args...); } @@ -635,7 +635,7 @@ FMT_DEPRECATED auto compile(const Args&... args) template ::value)> -FMT_INLINE std::basic_string format(CompiledFormat& cf, +FMT_INLINE std::basic_string format(const CompiledFormat& cf, const Args&... args) { basic_memory_buffer buffer; cf.format(detail::buffer_appender(buffer), args...); @@ -644,7 +644,7 @@ FMT_INLINE std::basic_string format(CompiledFormat& cf, template ::value)> -constexpr OutputIt format_to(OutputIt out, CompiledFormat& cf, +constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, const Args&... args) { return cf.format(out, args...); } @@ -674,14 +674,14 @@ FMT_INLINE std::basic_string format(const S&, return fmt::to_string(detail::first(args...)); } #endif - auto compiled = detail::compile(S()); + constexpr auto compiled = detail::compile(S()); return format(compiled, std::forward(args)...); } template ::value)> -constexpr OutputIt format_to(OutputIt out, CompiledFormat& cf, +constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, const Args&... args) { using char_type = typename CompiledFormat::char_type; using context = format_context_t; @@ -692,7 +692,7 @@ constexpr OutputIt format_to(OutputIt out, CompiledFormat& cf, template ::value)> FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, const Args&... args) { - auto compiled = detail::compile(S()); + constexpr auto compiled = detail::compile(S()); return format_to(out, compiled, args...); } @@ -714,7 +714,7 @@ template ::value)> format_to_n_result format_to_n(OutputIt out, size_t n, const S&, const Args&... args) { - auto compiled = detail::compile(S()); + constexpr auto compiled = detail::compile(S()); auto it = format_to(detail::truncating_iterator(out, n), compiled, args...); return {it.base(), it.count()}; diff --git a/include/fmt/format.h b/include/fmt/format.h index 774d5a4b..8c67805a 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3539,6 +3539,20 @@ struct formatter + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec( + specs.precision, specs.precision_ref, ctx); + using af = detail::arg_formatter; + return visit_format_arg(af(ctx, nullptr, &specs), + detail::make_arg(val)); + } + template FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) { @@ -3556,13 +3570,14 @@ struct formatter specs_; }; -#define FMT_FORMAT_AS(Type, Base) \ - template \ - struct formatter : formatter { \ - template \ - auto format(Type const& val, FormatContext& ctx) -> decltype(ctx.out()) { \ - return formatter::format(static_cast(val), ctx); \ - } \ +#define FMT_FORMAT_AS(Type, Base) \ + template \ + struct formatter : formatter { \ + template \ + auto format(Type const& val, FormatContext& ctx) const \ + -> decltype(ctx.out()) { \ + return formatter::format(static_cast(val), ctx); \ + } \ } FMT_FORMAT_AS(signed char, int); @@ -3582,7 +3597,7 @@ FMT_FORMAT_AS(std::byte, unsigned); template struct formatter : formatter { template - auto format(void* val, FormatContext& ctx) -> decltype(ctx.out()) { + auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(val, ctx); } }; @@ -3590,7 +3605,7 @@ struct formatter : formatter { template struct formatter : formatter, Char> { template - FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) + FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter, Char>::format(val, ctx); }