diff --git a/README.md b/README.md index 0c2f5d5..82725ee 100644 --- a/README.md +++ b/README.md @@ -482,7 +482,7 @@ float: 12345678 * 10^23 = 1.23456782e+30 (==expected) ``` Overloads of `fast_float::integer_times_pow10()` are provided for -signed and unsigned integer types: `int64_t`, `uint64_t`, etc. +signed and unsigned integer types up to 64 bits: `int64_t`, `uint64_t`, etc. ## Users and Related Work diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index d12a442..2058330 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -535,38 +535,42 @@ integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept { // the following overloads are here to avoid surprising ambiguity for int, // unsigned, etc. template -FASTFLOAT_CONSTEXPR20 - typename std::enable_if::value && - std::is_integral::value && - !std::is_signed::value, - T>::type - integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { +FASTFLOAT_CONSTEXPR20 typename std::enable_if< + is_supported_float_type::value && std::is_integral::value && + sizeof(Int) <= sizeof(uint64_t) && !std::is_signed::value, + T>::type +integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template -FASTFLOAT_CONSTEXPR20 - typename std::enable_if::value && - std::is_integral::value && - std::is_signed::value, - T>::type - integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { +FASTFLOAT_CONSTEXPR20 typename std::enable_if< + is_supported_float_type::value && std::is_integral::value && + sizeof(Int) <= sizeof(int64_t) && std::is_signed::value, + T>::type +integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template -FASTFLOAT_CONSTEXPR20 typename std::enable_if< - std::is_integral::value && !std::is_signed::value, double>::type -integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value && + sizeof(Int) <= sizeof(uint64_t) && + !std::is_signed::value, + double>::type + integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template -FASTFLOAT_CONSTEXPR20 typename std::enable_if< - std::is_integral::value && std::is_signed::value, double>::type -integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value && + sizeof(Int) <= sizeof(int64_t) && + std::is_signed::value, + double>::type + integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); } diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 8ae74fc..44c1e30 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -2283,6 +2283,38 @@ void verify_integer_times_pow10(Int mantissa, int decimal_exponent) { } } // namespace all_supported_types +#if defined(__SIZEOF_INT128__) +template +struct has_integer_times_pow10 : std::false_type {}; + +template +struct has_integer_times_pow10< + Int, std::void_t> + : std::true_type {}; + +template +struct has_typed_integer_times_pow10 : std::false_type {}; + +template +struct has_typed_integer_times_pow10< + Float, Int, + std::void_t(Int{}, 0))>> + : std::true_type {}; + +TEST_CASE("integer_times_pow10 rejects integers wider than 64 bits") { + CHECK(has_integer_times_pow10::value); + CHECK(has_integer_times_pow10::value); + CHECK(has_typed_integer_times_pow10::value); + CHECK(has_typed_integer_times_pow10::value); + CHECK_FALSE(has_integer_times_pow10<__int128_t>::value); + CHECK_FALSE(has_integer_times_pow10<__uint128_t>::value); + CHECK_FALSE(has_typed_integer_times_pow10::value); + CHECK_FALSE(has_typed_integer_times_pow10::value); + CHECK_FALSE(has_typed_integer_times_pow10::value); + CHECK_FALSE(has_typed_integer_times_pow10::value); +} +#endif + TEST_CASE("integer_times_pow10") { /* explicitly verifying API with different types of integers */ // double (the "default" overload)