diff --git a/include/fmt/format.h b/include/fmt/format.h index e884d01a..bbc6fb42 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -286,17 +286,6 @@ template struct function { template struct result { typedef Result type; }; }; -struct dummy_int { - int data[2]; - operator int() const { return 0; } -}; -typedef std::numeric_limits fputil; - -// Dummy implementations of system functions called if the latter are not -// available. -inline dummy_int isinf(...) { return dummy_int(); } -inline dummy_int _finite(...) { return dummy_int(); } - template typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) { #if __cplusplus >= 201103L || FMT_MSC_VER >= 1700 @@ -305,34 +294,9 @@ typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) { return alloc.allocate(n); #endif } - -// A helper function to suppress bogus "conditional expression is constant" -// warnings. -template inline T const_check(T value) { return value; } } // namespace internal FMT_END_NAMESPACE -namespace std { -// Standard permits specialization of std::numeric_limits. This specialization -// is used to resolve ambiguity between isinf and std::isinf in glibc: -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891 -// and the same for isnan. -template <> -class numeric_limits - : public std::numeric_limits { - public: - // Portable version of isinf. - template static bool isinfinity(T x) { - using namespace fmt::internal; - // The resolution "priority" is: - // isinf macro > std::isinf > ::isinf > fmt::internal::isinf - if (const_check(sizeof(isinf(x)) != sizeof(fmt::internal::dummy_int))) - return isinf(x) != 0; - return !_finite(static_cast(x)); - } -}; -} // namespace std - FMT_BEGIN_NAMESPACE template class basic_writer; @@ -2841,9 +2805,8 @@ void basic_writer::write_double(T value, const format_specs& spec) { if (!std::isfinite(value)) { // Format infinity and NaN ourselves because sprintf's output is not // consistent across platforms. - const char* str = internal::fputil::isinfinity(value) - ? (handler.upper ? "INF" : "inf") - : (handler.upper ? "NAN" : "nan"); + const char* str = std::isinf(value) ? (handler.upper ? "INF" : "inf") + : (handler.upper ? "NAN" : "nan"); return write_padded(spec, inf_or_nan_writer{sign, handler.as_percentage, str}); } diff --git a/include/fmt/printf.h b/include/fmt/printf.h index c3d8b556..e540a55b 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -16,6 +16,10 @@ FMT_BEGIN_NAMESPACE namespace internal { +// A helper function to suppress bogus "conditional expression is constant" +// warnings. +template inline T const_check(T value) { return value; } + // Checks if a value fits in int - used to avoid warnings about comparing // signed and unsigned integers. template struct int_checker { diff --git a/test/format-test.cc b/test/format-test.cc index b03b8af1..2e0ff199 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1107,6 +1107,7 @@ TEST(FormatterTest, Width) { EXPECT_EQ("x ", format("{0:11}", 'x')); EXPECT_EQ("str ", format("{0:12}", "str")); } +template inline T const_check(T value) { return value; } TEST(FormatterTest, RuntimeWidth) { char format_str[BUFFER_SIZE]; @@ -1135,7 +1136,7 @@ TEST(FormatterTest, RuntimeWidth) { EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)), format_error, "number is too big"); EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l), format_error, "negative width"); - if (fmt::internal::const_check(sizeof(long) > sizeof(int))) { + if (const_check(sizeof(long) > sizeof(int))) { long value = INT_MAX; EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)), format_error, "number is too big"); @@ -1257,7 +1258,7 @@ TEST(FormatterTest, RuntimePrecision) { "number is too big"); EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l), format_error, "negative precision"); - if (fmt::internal::const_check(sizeof(long) > sizeof(int))) { + if (const_check(sizeof(long) > sizeof(int))) { long value = INT_MAX; EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)), format_error, "number is too big");