From 8b72fcd0d2e02725fa1a58b265afa3485568be09 Mon Sep 17 00:00:00 2001 From: Ivan Lazaric Date: Sun, 20 Sep 2026 23:21:52 +0200 Subject: [PATCH] Make `format_custom()` constexpr to improve constexpr formatting Added test shows a simple example when this matters. --- include/fmt/core.h | 5 +++-- test/compile-test.cc | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index f0815206..4dff1da0 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -2275,8 +2275,9 @@ template class value { // Formats an argument of a custom type, such as a user-defined class. template - static void format_custom(void* arg, parse_context& parse_ctx, - Context& ctx) { + static FMT_CONSTEXPR void format_custom(void* arg, + parse_context& parse_ctx, + Context& ctx) { auto f = formatter(); parse_ctx.advance_to(f.parse(parse_ctx)); using qualified_type = diff --git a/test/compile-test.cc b/test/compile-test.cc index c3331273..77a7bce2 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -494,3 +494,27 @@ TEST(compile_test, format_as) { // compiled field path rather than the to_string fast path. EXPECT_EQ("[42]", fmt::format(FMT_COMPILE("[{}]"), type_with_format_as{42})); } + +#if FMT_CPLUSPLUS >= 202000L +struct consteval_printable {}; + +template<> +struct fmt::formatter { + bool debug = false; + consteval auto parse(auto& ctx) { + if (ctx.begin() != ctx.end() && *ctx.begin() == '?') { + debug = true; + ctx.advance_to(ctx.begin() + 1); + } + return ctx.begin(); + } + consteval auto format(consteval_printable, auto& ctx) const { + return fmt::formatter{}.format(debug ? "debug" : "regular", ctx); + } +}; + +static_assert(fmt::format(FMT_COMPILE("{}"), consteval_printable{}) == "regular"); +static_assert(fmt::format(FMT_COMPILE("[{}]"), consteval_printable{}) == "[regular]"); +static_assert(fmt::format(FMT_COMPILE("{:?}"), consteval_printable{}) == "debug"); +static_assert(fmt::format(FMT_COMPILE("[{:?}]"), consteval_printable{}) == "[debug]"); +#endif // FMT_CPLUSPLUS >= 202000L