diff --git a/include/fmt/compile.h b/include/fmt/compile.h index ab630ca8..475c584d 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -173,8 +173,6 @@ class compiled_format { compiled_format() = delete; - using context = buffer_context; - template auto vformat_to(Range out, basic_format_args args) const -> typename Context::iterator { @@ -203,8 +201,7 @@ class compiled_format { case format_part_t::kind::arg_name: { advance_parse_context_to_specification(parse_ctx, part); - const auto named_arg_id = value.str; - format_arg(parse_ctx, ctx, named_arg_id); + format_arg(parse_ctx, ctx, value.str); } break; case format_part_t::kind::replacement: { const auto& arg_id_value = value.repl.arg_id.val; @@ -242,10 +239,8 @@ class compiled_format { template void format_arg(basic_parse_context& parse_ctx, Context& ctx, Id arg_id) const { - parse_ctx.check_arg_id(arg_id); - const auto stopped_at = - visit_format_arg(arg_formatter(ctx), ctx.arg(arg_id)); - ctx.advance_to(stopped_at); + ctx.advance_to(visit_format_arg(arg_formatter(ctx, &parse_ctx), + ctx.arg(arg_id))); } template @@ -359,6 +354,7 @@ FMT_CONSTEXPR auto compile(S format_str) } #endif +// Compiles the format string which must be a string literal. template auto compile(const Char (&format_str)[N]) -> internal::compiled_format< std::basic_string, internal::runtime_parts_provider, Args...> { diff --git a/test/compile-test.cc b/test/compile-test.cc index 73de9a55..91559858 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -152,3 +152,17 @@ TEST(CompileTest, FormattedSize) { auto f = fmt::compile("{:10}"); EXPECT_EQ(fmt::formatted_size(f, 42), 10); } + +struct formattable {}; + +template <> +struct fmt::formatter : formatter { + auto format(formattable, format_context& ctx) -> decltype(ctx.out()) { + return formatter::format("foo", ctx); + } +}; + +TEST(CompileTest, FormatUserDefinedType) { + auto f = fmt::compile("{}"); + EXPECT_EQ(fmt::format(f, formattable()), "foo"); +}