diff --git a/include/fmt/std.h b/include/fmt/std.h index 3af4d61c..2684c10b 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -232,6 +232,19 @@ struct is_bit_reference_like> { }; #endif +template +struct has_format_as : std::false_type {}; +template +struct has_format_as()))>> + : std::true_type {}; + +template +struct has_format_as_member : std::false_type {}; +template +struct has_format_as_member< + T, void_t::format_as(std::declval()))>> + : std::true_type {}; + } // namespace detail template @@ -678,25 +691,10 @@ template struct formatter, Char> { } }; -namespace detail { -template -struct has_format_as : std::false_type {}; -template -struct has_format_as()))>> - : std::true_type {}; - -template -struct has_format_as_member : std::false_type {}; -template -struct has_format_as_member< - T, void_t::format_as(std::declval()))>> - : std::true_type {}; -} // namespace detail - -// Guard against format_as because reference_wrappers are implicitly convertible -// to T& template struct formatter, Char, + // Guard against format_as because reference_wrapper is + // implicitly convertible to T&. enable_if_t, Char>::value && !detail::has_format_as::value && !detail::has_format_as_member::value>> diff --git a/test/std-test.cc b/test/std-test.cc index 2f7f7d7c..f5b4e7e8 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -413,37 +413,31 @@ TEST(std_test, format_shared_ptr) { TEST(std_test, format_reference_wrapper) { int num = 35; - EXPECT_EQ("35", fmt::to_string(std::cref(num))); - EXPECT_EQ("35", fmt::to_string(std::ref(num))); - EXPECT_EQ("35", fmt::format("{}", std::cref(num))); - EXPECT_EQ("35", fmt::format("{}", std::ref(num))); + EXPECT_EQ(fmt::to_string(std::cref(num)), "35"); + EXPECT_EQ(fmt::to_string(std::ref(num)), "35"); + EXPECT_EQ(fmt::format("{}", std::cref(num)), "35"); + EXPECT_EQ(fmt::format("{}", std::ref(num)), "35"); } -// Regression test for https://github.com/fmtlib/fmt/issues/4424 -struct type_with_format_as { - int x; -}; - -int format_as(const type_with_format_as& t) { return t.x; } +// Regression test for https://github.com/fmtlib/fmt/issues/4424. +struct type_with_format_as {}; +int format_as(type_with_format_as) { return 20; } TEST(std_test, format_reference_wrapper_with_format_as) { - type_with_format_as t{20}; - EXPECT_EQ("20", fmt::to_string(std::cref(t))); - EXPECT_EQ("20", fmt::to_string(std::ref(t))); - EXPECT_EQ("20", fmt::format("{}", std::cref(t))); - EXPECT_EQ("20", fmt::format("{}", std::ref(t))); + type_with_format_as t; + EXPECT_EQ(fmt::to_string(std::cref(t)), "20"); + EXPECT_EQ(fmt::to_string(std::ref(t)), "20"); + EXPECT_EQ(fmt::format("{}", std::cref(t)), "20"); + EXPECT_EQ(fmt::format("{}", std::ref(t)), "20"); } -struct type_with_format_as_string { - std::string str; -}; - -std::string format_as(const type_with_format_as_string& t) { return t.str; } +struct type_with_format_as_string {}; +std::string format_as(type_with_format_as_string) { return "foo"; } TEST(std_test, format_reference_wrapper_with_format_as_string) { - type_with_format_as_string t{"foo"}; - EXPECT_EQ("foo", fmt::to_string(std::cref(t))); - EXPECT_EQ("foo", fmt::to_string(std::ref(t))); - EXPECT_EQ("foo", fmt::format("{}", std::cref(t))); - EXPECT_EQ("foo", fmt::format("{}", std::ref(t))); + type_with_format_as_string t; + EXPECT_EQ(fmt::to_string(std::cref(t)), "foo"); + EXPECT_EQ(fmt::to_string(std::ref(t)), "foo"); + EXPECT_EQ(fmt::format("{}", std::cref(t)), "foo"); + EXPECT_EQ(fmt::format("{}", std::ref(t)), "foo"); }