diff --git a/include/fmt/format.h b/include/fmt/format.h index 751a1594..1093bb5b 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1205,7 +1205,7 @@ class value { custom_value custom; }; - constexpr value() {} + constexpr value() : int_value(0) {} value(bool val) { set(int_value, val); } value(short val) { set(int_value, val); } value(unsigned short val) { set(uint_value, val); } @@ -3267,7 +3267,7 @@ struct arg_ref { enum Kind { NONE, INDEX, NAME }; constexpr arg_ref() : kind(NONE), index(0) {} - explicit arg_ref(unsigned index) : kind(INDEX), index(index) {} + constexpr explicit arg_ref(unsigned index) : kind(INDEX), index(index) {} explicit arg_ref(basic_string_view name) : kind(NAME), name(name) {} constexpr arg_ref &operator=(unsigned index) { @@ -3300,17 +3300,17 @@ class dynamic_specs_handler : public: using char_type = typename ParseContext::char_type; - dynamic_specs_handler( + constexpr dynamic_specs_handler( dynamic_format_specs &specs, ParseContext &ctx) : specs_setter(specs), specs_(specs), context_(ctx) {} template - void on_dynamic_width(Id arg_id) { + constexpr void on_dynamic_width(Id arg_id) { specs_.width_ref = make_arg_ref(arg_id); } template - void on_dynamic_precision(Id arg_id) { + constexpr void on_dynamic_precision(Id arg_id) { specs_.precision_ref = make_arg_ref(arg_id); } @@ -3318,12 +3318,12 @@ class dynamic_specs_handler : using arg_ref_type = arg_ref; template - arg_ref_type make_arg_ref(Id arg_id) { + constexpr arg_ref_type make_arg_ref(Id arg_id) { context_.check_arg_id(arg_id); return arg_ref_type(arg_id); } - arg_ref_type make_arg_ref(auto_id) { + constexpr arg_ref_type make_arg_ref(auto_id) { const char *error = 0; auto index = context_.next_arg_index(error); if (error) diff --git a/test/format-test.cc b/test/format-test.cc index 48f6c439..e9826d38 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1693,6 +1693,8 @@ struct test_context { template constexpr void check_arg_id(Id) {} + + constexpr unsigned next_arg_index(const char *&) { return 33; } }; constexpr fmt::format_specs parse_specs(const char *s) { @@ -1719,3 +1721,29 @@ TEST(FormatTest, ConstexprSpecsHandler) { static_assert(parse_specs(".{0}").precision() == 22, ""); static_assert(parse_specs("d").type() == 'd', ""); } + +constexpr fmt::internal::dynamic_format_specs + parse_dynamic_specs(const char *s) { + fmt::internal::dynamic_format_specs specs; + test_context ctx; + fmt::internal::dynamic_specs_handler h(specs, ctx); + parse_format_specs(s, h); + return specs; +} + +TEST(FormatTest, ConstexprDynamicSpecsHandler) { + static_assert(parse_dynamic_specs("<").align() == fmt::ALIGN_LEFT, ""); + static_assert(parse_dynamic_specs("*^").fill() == '*', ""); + static_assert(parse_dynamic_specs("+").flag(fmt::PLUS_FLAG), ""); + static_assert(parse_dynamic_specs("-").flag(fmt::MINUS_FLAG), ""); + static_assert(parse_dynamic_specs(" ").flag(fmt::SIGN_FLAG), ""); + static_assert(parse_dynamic_specs("#").flag(fmt::HASH_FLAG), ""); + static_assert(parse_dynamic_specs("0").align() == fmt::ALIGN_NUMERIC, ""); + static_assert(parse_dynamic_specs("42").width() == 42, ""); + static_assert(parse_dynamic_specs("{}").width_ref.index == 33, ""); + static_assert(parse_dynamic_specs("{42}").width_ref.index == 42, ""); + static_assert(parse_dynamic_specs(".42").precision() == 42, ""); + static_assert(parse_dynamic_specs(".{}").precision_ref.index == 33, ""); + static_assert(parse_dynamic_specs(".{42}").precision_ref.index == 42, ""); + static_assert(parse_dynamic_specs("d").type() == 'd', ""); +}