From 16cac46a094aa1b182494f1935c2267189262827 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 12 Jul 2020 08:26:35 -0700 Subject: [PATCH] Improve handling of streamable and convertible to bool types (#1766) --- include/fmt/ostream.h | 24 +++++++++++++++++------- test/ostream-test.cc | 13 ++++++++++++- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 1b809eb4caea..1361ac297c88 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -49,17 +49,27 @@ template class formatbuf : public std::basic_streambuf { } }; +struct converter { + template ::value)> converter(T); +}; + template struct test_stream : std::basic_ostream { private: - // Hide all operator<< from std::basic_ostream. - void_t<> operator<<(null<>); - void_t<> operator<<(const Char*); - - template ::value && - !std::is_enum::value)> - void_t<> operator<<(T); + void_t<> operator<<(converter); }; +// Hide insertion operators for built-in types. +template +void_t<> operator<<(std::basic_ostream&, Char); +template +void_t<> operator<<(std::basic_ostream&, char); +template +void_t<> operator<<(std::basic_ostream&, char); +template +void_t<> operator<<(std::basic_ostream&, signed char); +template +void_t<> operator<<(std::basic_ostream&, unsigned char); + // Checks if T has a user-defined operator<< (e.g. not a member of // std::ostream). template class is_streamable { diff --git a/test/ostream-test.cc b/test/ostream-test.cc index bd98f6439a33..ce36b4cd69fc 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -290,9 +290,20 @@ std::ostream& operator<<(std::ostream& os, TEST(OStreamTest, FormatExplicitlyConvertibleToStdStringView) { EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like())); } - #endif // FMT_USE_STRING_VIEW +struct streamable_and_convertible_to_bool { + operator bool() const { return true; } +}; + +std::ostream& operator<<(std::ostream& os, streamable_and_convertible_to_bool) { + return os << "foo"; +} + +TEST(OStreamTest, FormatConvertibleToBool) { + EXPECT_EQ("foo", fmt::format("{}", streamable_and_convertible_to_bool())); +} + struct copyfmt_test {}; std::ostream& operator<<(std::ostream& os, copyfmt_test) {