diff --git a/include/fmt/std.h b/include/fmt/std.h index 12e15d3e..b6301805 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -585,5 +586,31 @@ struct formatter : formatter { }; #endif // __cpp_lib_atomic_flag_test +FMT_EXPORT +template +struct formatter, Char> : nested_formatter { + private: + // Functor because C++11 doesn't support generic lambdas. + struct writer { + const formatter, Char>* f; + const std::complex& c; + + template + FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt { + auto format = + detail::string_literal{}; + return fmt::format_to(out, basic_string_view(format), + f->nested(c.real()), f->nested(c.imag())); + } + }; + + public: + template + auto format(const std::complex& c, FormatContext& ctx) const + -> decltype(ctx.out()) { + return this->write_padded(ctx, writer{this, c}); + } +}; + FMT_END_NAMESPACE #endif // FMT_STD_H_ diff --git a/test/std-test.cc b/test/std-test.cc index 0cdd3abb..52053234 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -65,6 +65,12 @@ TEST(std_test, thread_id) { EXPECT_FALSE(fmt::format("{}", std::this_thread::get_id()).empty()); } +TEST(std_test, complex) { + EXPECT_EQ(fmt::format("{}", std::complex(1, 2.2)), "(1,2.2)"); + EXPECT_EQ(fmt::format("{:>20.2f}", std::complex(1, 2.2)), + " (1.00,2.20)"); +} + #ifdef __cpp_lib_source_location TEST(std_test, source_location) { std::source_location loc = std::source_location::current(); diff --git a/test/xchar-test.cc b/test/xchar-test.cc index c1683468..b552f85b 100644 --- a/test/xchar-test.cc +++ b/test/xchar-test.cc @@ -562,49 +562,6 @@ TEST(locale_test, int_formatter) { EXPECT_EQ(fmt::to_string(buf), "12,345"); } -FMT_BEGIN_NAMESPACE -template struct formatter, charT> { - private: - detail::dynamic_format_specs specs_; - - public: - FMT_CONSTEXPR typename basic_format_parse_context::iterator parse( - basic_format_parse_context& ctx) { - auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, - detail::type::float_type); - detail::parse_float_type_spec(specs_); - return end; - } - - template - typename FormatContext::iterator format(const std::complex& c, - FormatContext& ctx) const { - auto specs = specs_; - detail::handle_dynamic_spec( - specs.precision, specs.precision_ref, ctx); - auto fspecs = std::string(); - if (specs.precision > 0) fspecs = fmt::format(".{}", specs.precision); - if (specs.type == presentation_type::fixed) fspecs += 'f'; - auto real = fmt::format(ctx.locale().template get(), - fmt::runtime("{:" + fspecs + "}"), c.real()); - auto imag = fmt::format(ctx.locale().template get(), - fmt::runtime("{:" + fspecs + "}"), c.imag()); - auto fill_align_width = std::string(); - if (specs.width > 0) fill_align_width = fmt::format(">{}", specs.width); - return fmt::format_to(ctx.out(), runtime("{:" + fill_align_width + "}"), - c.real() != 0 ? fmt::format("({}+{}i)", real, imag) - : fmt::format("{}i", imag)); - } -}; -FMT_END_NAMESPACE - -TEST(locale_test, complex) { - std::string s = fmt::format("{}", std::complex(1, 2)); - EXPECT_EQ(s, "(1+2i)"); - EXPECT_EQ(fmt::format("{:.2f}", std::complex(1, 2)), "(1.00+2.00i)"); - EXPECT_EQ(fmt::format("{:8}", std::complex(1, 2)), " (1+2i)"); -} - TEST(locale_test, chrono_weekday) { auto loc = get_locale("es_ES.UTF-8", "Spanish_Spain.1252"); auto loc_old = std::locale::global(loc); @@ -625,6 +582,13 @@ TEST(locale_test, sign) { EXPECT_EQ(fmt::format(std::locale(), L"{:L}", -50), L"-50"); } +TEST(std_test_xchar, complex) { + auto s = fmt::format(L"{}", std::complex(1, 2)); + EXPECT_EQ(s, L"(1,2)"); + EXPECT_EQ(fmt::format(L"{:.2f}", std::complex(1, 2)), L"(1.00,2.00)"); + EXPECT_EQ(fmt::format(L"{:8}", std::complex(1, 2)), L"(1,2) "); +} + TEST(std_test_xchar, optional) { # ifdef __cpp_lib_optional EXPECT_EQ(fmt::format(L"{}", std::optional{L'C'}), L"optional(\'C\')");