From 502f2b89497fb6ffcfec0786f206f82582cab5e1 Mon Sep 17 00:00:00 2001 From: Giel van Schijndel <giel@mortis.eu> Date: Fri, 29 Sep 2023 14:50:23 +0200 Subject: [PATCH 1/2] fix: make std::bitset formattable again It used to be formattable via operator<<(ostream&) implicitly. Make it formattable again, but this time via formatter specialization. --- include/fmt/std.h | 26 ++++++++++++++++++++++++++ test/std-test.cc | 8 ++++++++ 2 files changed, 34 insertions(+) diff --git a/include/fmt/std.h b/include/fmt/std.h index b4e055c28d41..262ad4d209c0 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -145,6 +145,32 @@ FMT_END_NAMESPACE #endif FMT_BEGIN_NAMESPACE +FMT_EXPORT +template <std::size_t N, typename Char> +struct formatter<std::bitset<N>, Char> : nested_formatter<string_view> { + private: + // Functor because C++11 doesn't support generic lambdas. + struct writer { + const std::bitset<N>& bs; + + template <typename OutputIt> + FMT_CONSTEXPR OutputIt operator()(OutputIt out) { + for (auto pos = N; pos > 0; --pos) { + out = detail::write<Char>(out, bs[pos - 1] ? Char('1') : Char('0')); + } + + return out; + } + }; + + public: + template <typename FormatContext> + auto format(const std::bitset<N>& bs, FormatContext& ctx) const + -> decltype(ctx.out()) { + return write_padded(ctx, writer{bs}); + } +}; + FMT_EXPORT template <typename Char> struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {}; diff --git a/test/std-test.cc b/test/std-test.cc index 56904cc9889d..4279fec10b0f 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -237,6 +237,14 @@ TEST(std_test, format_const_bit_reference) { EXPECT_EQ(fmt::format("{} {}", v[0], v[1]), "true false"); } +TEST(std_test, format_bitset) { + const std::bitset<6> bs(42); + EXPECT_EQ(fmt::format("{}", bs), "101010"); + EXPECT_EQ(fmt::format("{:.4}", bs), "101010"); + EXPECT_EQ(fmt::format("{:0>8}", bs), "00101010"); + EXPECT_EQ(fmt::format("{:-^12}", bs), "---101010---"); +} + TEST(std_test, format_atomic) { std::atomic<bool> b(false); EXPECT_EQ(fmt::format("{}", b), "false"); From 40524a3595924bba11af685a87e071b2a524e64b Mon Sep 17 00:00:00 2001 From: Giel van Schijndel <giel@mortis.eu> Date: Sat, 30 Sep 2023 20:34:42 +0200 Subject: [PATCH 2/2] fix: make nested_formatter constexpr default constructible --- include/fmt/format.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/fmt/format.h b/include/fmt/format.h index 30addcb7f335..433339614ff7 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -4224,6 +4224,8 @@ struct nested_formatter { formatter<T> formatter_; public: + constexpr nested_formatter() : width_(0), align_(align_t::none) {} + FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> const char* { auto specs = detail::dynamic_format_specs<char>(); auto it = parse_format_specs(