diff --git a/include/fmt/core.h b/include/fmt/core.h index a73fa829..561c1b86 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -338,36 +338,11 @@ inline void require_wchar() { "formatting of wide characters into a narrow output is disallowed"); } -using yes = char[1]; -using no = char[2]; - -yes &convert(unsigned long long); -no &convert(...); - -template -struct convert_to_int_impl { - enum { value = ENABLE_CONVERSION }; -}; - -template -struct convert_to_int_impl2 { - enum { value = false }; -}; - -template -struct convert_to_int_impl2 { - enum { - // Don't convert arithmetic types. - value = convert_to_int_impl::value>::value - }; -}; - -template +template struct convert_to_int { enum { - enable_conversion = sizeof(convert(std::declval())) == sizeof(yes) + value = !std::is_arithmetic::value && std::is_convertible::value }; - enum { value = convert_to_int_impl2::value }; }; #define FMT_DISABLE_CONVERSION_TO_INT(Type) \ diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 09b85608..b24d026d 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -47,23 +47,28 @@ class FormatBuf : public std::basic_streambuf { } }; -yes &convert(std::ostream &); - -struct DummyStream : std::ostream { - DummyStream(); // Suppress a bogus warning in MSVC. - // Hide all operator<< overloads from std::ostream. - void operator<<(null<>); +struct test_stream : std::ostream { + private: + struct null; + // Hide all operator<< from std::ostream. + void operator<<(null); }; -no &operator<<(std::ostream &, int); +// Disable conversion to int if T has an overloaded operator<< which is a free +// function (not a member of std::ostream). +template +class convert_to_int { + private: + template + static decltype( + std::declval() << std::declval(), std::true_type()) + test(int); -template -struct convert_to_int_impl { - // Convert to int only if T doesn't have an overloaded operator<<. - enum { - value = sizeof(convert(std::declval() << std::declval())) - == sizeof(no) - }; + template + static std::false_type test(...); + + public: + static const bool value = !decltype(test(0))::value; }; // Write the content of buf to os. diff --git a/test/util-test.cc b/test/util-test.cc index 65d8e5f8..4f4f04c7 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -827,15 +827,15 @@ TEST(UtilTest, ReportWindowsError) { enum TestEnum2 {}; TEST(UtilTest, ConvertToInt) { - EXPECT_TRUE(fmt::internal::convert_to_int::enable_conversion); - EXPECT_FALSE(fmt::internal::convert_to_int::enable_conversion); + EXPECT_FALSE(fmt::internal::convert_to_int::value); + EXPECT_FALSE(fmt::internal::convert_to_int::value); EXPECT_TRUE(fmt::internal::convert_to_int::value); } #if FMT_USE_ENUM_BASE enum TestEnum : char {TestValue}; TEST(UtilTest, IsEnumConvertibleToInt) { - EXPECT_TRUE(fmt::internal::convert_to_int::enable_conversion); + EXPECT_TRUE(fmt::internal::convert_to_int::value); } #endif