Skip to content

Commit

Permalink
Improve handling of streamable and convertible to bool types (#1766)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Jul 12, 2020
1 parent 415cd51 commit 16cac46
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
24 changes: 17 additions & 7 deletions include/fmt/ostream.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,27 @@ template <class Char> class formatbuf : public std::basic_streambuf<Char> {
}
};

struct converter {
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> converter(T);
};

template <typename Char> struct test_stream : std::basic_ostream<Char> {
private:
// Hide all operator<< from std::basic_ostream<Char>.
void_t<> operator<<(null<>);
void_t<> operator<<(const Char*);

template <typename T, FMT_ENABLE_IF(std::is_convertible<T, int>::value &&
!std::is_enum<T>::value)>
void_t<> operator<<(T);
void_t<> operator<<(converter);
};

// Hide insertion operators for built-in types.
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char);
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char);

// Checks if T has a user-defined operator<< (e.g. not a member of
// std::ostream).
template <typename T, typename Char> class is_streamable {
Expand Down
13 changes: 12 additions & 1 deletion test/ostream-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 16cac46

Please sign in to comment.