Fix handling of types convertible to int

This commit is contained in:
Victor Zverovich
2017-09-02 07:08:19 -07:00
parent 89654cd127
commit 3e75d3e001
3 changed files with 27 additions and 10 deletions

View File

@ -1171,17 +1171,17 @@ T &get();
Yes &convert(fmt::ULongLong); Yes &convert(fmt::ULongLong);
No &convert(...); No &convert(...);
template<typename T, bool ENABLE_CONVERSION> template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl { struct ConvertToIntImpl {
enum { value = ENABLE_CONVERSION }; enum { value = ENABLE_CONVERSION };
}; };
template<typename T, bool ENABLE_CONVERSION> template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl2 { struct ConvertToIntImpl2 {
enum { value = false }; enum { value = false };
}; };
template<typename T> template <typename T>
struct ConvertToIntImpl2<T, true> { struct ConvertToIntImpl2<T, true> {
enum { enum {
// Don't convert numeric types. // Don't convert numeric types.
@ -1189,7 +1189,7 @@ struct ConvertToIntImpl2<T, true> {
}; };
}; };
template<typename T> template <typename T>
struct ConvertToInt { struct ConvertToInt {
enum { enum {
enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes) enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
@ -1206,16 +1206,16 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
FMT_DISABLE_CONVERSION_TO_INT(double); FMT_DISABLE_CONVERSION_TO_INT(double);
FMT_DISABLE_CONVERSION_TO_INT(long double); FMT_DISABLE_CONVERSION_TO_INT(long double);
template<bool B, class T = void> template <bool B, class T = void>
struct EnableIf {}; struct EnableIf {};
template<class T> template <class T>
struct EnableIf<true, T> { typedef T type; }; struct EnableIf<true, T> { typedef T type; };
template<bool B, class T, class F> template <bool B, class T, class F>
struct Conditional { typedef T type; }; struct Conditional { typedef T type; };
template<class T, class F> template <class T, class F>
struct Conditional<false, T, F> { typedef F type; }; struct Conditional<false, T, F> { typedef F type; };
// For bcc32 which doesn't understand ! in template arguments. // For bcc32 which doesn't understand ! in template arguments.

View File

@ -52,13 +52,15 @@ Yes &convert(std::ostream &);
struct DummyStream : std::ostream { struct DummyStream : std::ostream {
DummyStream(); // Suppress a bogus warning in MSVC. DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream. // Hide all operator<< overloads from std::ostream.
void operator<<(Null<>); template <typename T>
typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
}; };
No &operator<<(std::ostream &, int); No &operator<<(std::ostream &, int);
template<typename T> template <typename T>
struct ConvertToIntImpl<T, true> { struct ConvertToIntImpl<T, true> {
// Convert to int only if T doesn't have an overloaded operator<<. // Convert to int only if T doesn't have an overloaded operator<<.
enum { enum {

View File

@ -172,3 +172,18 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
} while (size != 0); } while (size != 0);
fmt::internal::write(os, w); fmt::internal::write(os, w);
} }
struct ConvertibleToInt {
template <typename ValueType>
operator ValueType() const {
return 0;
}
friend std::ostream &operator<<(std::ostream &o, ConvertibleToInt) {
return o << "foo";
}
};
TEST(FormatTest, FormatConvertibleToInt) {
EXPECT_EQ("foo", fmt::format("{}", ConvertibleToInt()));
}