Revert "Replace a bunch of craft with type_traits"

This reverts commit e79588d6c1.
This commit is contained in:
Victor Zverovich 2018-01-21 18:53:38 -08:00
parent 0473c48f88
commit 21429c8646
3 changed files with 54 additions and 10 deletions

View File

@ -338,13 +338,47 @@ inline void require_wchar() {
"formatting of wide characters into a narrow output is disallowed");
}
template <typename T, bool ENABLE = true>
struct convert_to_int {
using yes = char[1];
using no = char[2];
yes &convert(unsigned long long);
no &convert(...);
template<typename T, bool ENABLE_CONVERSION>
struct convert_to_int_impl {
enum { value = ENABLE_CONVERSION };
};
template<typename T, bool ENABLE_CONVERSION>
struct convert_to_int_impl2 {
enum { value = false };
};
template<typename T>
struct convert_to_int_impl2<T, true> {
enum {
value = !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value
// Don't convert arithmetic types.
value = convert_to_int_impl<T, !std::is_arithmetic<T>::value>::value
};
};
template<typename T>
struct convert_to_int {
enum {
enable_conversion = sizeof(convert(std::declval<T>())) == sizeof(yes)
};
enum { value = convert_to_int_impl2<T, enable_conversion>::value };
};
#define FMT_DISABLE_CONVERSION_TO_INT(Type) \
template <> \
struct convert_to_int<Type> { 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 <typename Char>
struct named_arg_base;

View File

@ -47,12 +47,22 @@ class FormatBuf : public std::basic_streambuf<Char> {
}
};
template <typename T>
struct convert_to_int<T,
sizeof(std::declval<std::ostream>() << std::declval<T>()) != 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<typename T>
struct convert_to_int_impl<T, true> {
// Convert to int only if T doesn't have an overloaded operator<<.
enum {
value = false
value = sizeof(convert(std::declval<DummyStream&>() << std::declval<T>()))
== sizeof(no)
};
};

View File

@ -827,15 +827,15 @@ TEST(UtilTest, ReportWindowsError) {
enum TestEnum2 {};
TEST(UtilTest, ConvertToInt) {
EXPECT_FALSE(fmt::internal::convert_to_int<char>::value);
EXPECT_FALSE(fmt::internal::convert_to_int<const char *>::value);
EXPECT_TRUE(fmt::internal::convert_to_int<char>::enable_conversion);
EXPECT_FALSE(fmt::internal::convert_to_int<const char *>::enable_conversion);
EXPECT_TRUE(fmt::internal::convert_to_int<TestEnum2>::value);
}
#if FMT_USE_ENUM_BASE
enum TestEnum : char {TestValue};
TEST(UtilTest, IsEnumConvertibleToInt) {
EXPECT_TRUE(fmt::internal::convert_to_int<TestEnum>::value);
EXPECT_TRUE(fmt::internal::convert_to_int<TestEnum>::enable_conversion);
}
#endif