From 21429c864648341b7ef7d7c20e96df84ba16bae2 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 21 Jan 2018 18:53:38 -0800 Subject: [PATCH] Revert "Replace a bunch of craft with type_traits" This reverts commit e79588d6c1e654cb2833d496042b14807c8cd818. --- include/fmt/core.h | 40 +++++++++++++++++++++++++++++++++++++--- include/fmt/ostream.h | 18 ++++++++++++++---- test/util-test.cc | 6 +++--- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index 024a7912..a73fa829 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -338,13 +338,47 @@ inline void require_wchar() { "formatting of wide characters into a narrow output is disallowed"); } -template -struct convert_to_int { +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 { - value = !std::is_arithmetic::value && std::is_convertible::value + // Don't convert arithmetic types. + value = convert_to_int_impl::value>::value }; }; +template +struct convert_to_int { + enum { + enable_conversion = sizeof(convert(std::declval())) == sizeof(yes) + }; + enum { value = convert_to_int_impl2::value }; +}; + +#define FMT_DISABLE_CONVERSION_TO_INT(Type) \ + template <> \ + struct convert_to_int { enum { value = 0 }; } + +// Silence warnings about convering float to int. +FMT_DISABLE_CONVERSION_TO_INT(float); +FMT_DISABLE_CONVERSION_TO_INT(double); +FMT_DISABLE_CONVERSION_TO_INT(long double); + template struct named_arg_base; diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 6e26817f..09b85608 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -47,12 +47,22 @@ class FormatBuf : public std::basic_streambuf { } }; -template -struct convert_to_int() << std::declval()) != 0> { +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<>); +}; + +no &operator<<(std::ostream &, int); + +template +struct convert_to_int_impl { // Convert to int only if T doesn't have an overloaded operator<<. enum { - value = false + value = sizeof(convert(std::declval() << std::declval())) + == sizeof(no) }; }; diff --git a/test/util-test.cc b/test/util-test.cc index 4f4f04c7..65d8e5f8 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -827,15 +827,15 @@ TEST(UtilTest, ReportWindowsError) { enum TestEnum2 {}; TEST(UtilTest, ConvertToInt) { - EXPECT_FALSE(fmt::internal::convert_to_int::value); - EXPECT_FALSE(fmt::internal::convert_to_int::value); + EXPECT_TRUE(fmt::internal::convert_to_int::enable_conversion); + EXPECT_FALSE(fmt::internal::convert_to_int::enable_conversion); 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::value); + EXPECT_TRUE(fmt::internal::convert_to_int::enable_conversion); } #endif