From b43de126b92b3a280f8d4aaa04d0cf40d0c888ea Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 22 Mar 2021 12:27:40 +0100 Subject: [PATCH] Retain source compatibility of numberToString()/stringToNumber() IntegralType and BaseType need to be kept different types, otherwise one runs into deduction errors if both arguments have different types (which is quite likely in practise). Since the base is always a small positive integer the cast should always be safe. --- conversion/stringconversion.h | 61 ++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/conversion/stringconversion.h b/conversion/stringconversion.h index e04905d..568e409 100644 --- a/conversion/stringconversion.h +++ b/conversion/stringconversion.h @@ -397,18 +397,18 @@ template constexpr CharType digitToChar(CharType digit) * \tparam StringType The string type (should be an instantiation of the basic_string class template). * \sa stringToNumber() */ -template , std::is_unsigned> * = nullptr> -StringType numberToString(IntegralType number, IntegralType base = 10) +StringType numberToString(IntegralType number, BaseType base = 10) { std::size_t resSize = 0; - for (auto n = number; n; n /= base, ++resSize) + for (auto n = number; n; n /= static_cast(base), ++resSize) ; StringType res; res.reserve(resSize); do { res.insert(res.begin(), digitToChar(static_cast(number % base))); - number /= base; + number /= static_cast(base); } while (number); return res; } @@ -419,9 +419,9 @@ StringType numberToString(IntegralType number, IntegralType base = 10) * \tparam StringType The string type (should be an instantiation of the basic_string class template). * \sa stringToNumber() */ -template , std::is_signed> * = nullptr> -StringType numberToString(IntegralType number, IntegralType base = 10) +StringType numberToString(IntegralType number, BaseType base = 10) { const bool negative = number < 0; std::size_t resSize; @@ -430,13 +430,14 @@ StringType numberToString(IntegralType number, IntegralType base = 10) } else { resSize = 0; } - for (auto n = number; n; n /= base, ++resSize) + for (auto n = number; n; n /= static_cast(base), ++resSize) ; StringType res; res.reserve(resSize); do { - res.insert(res.begin(), digitToChar(static_cast(number % base))); - number /= base; + res.insert(res.begin(), + digitToChar(static_cast(number % static_cast(base)))); + number /= static_cast(base); } while (number); if (negative) { res.insert(res.begin(), '-'); @@ -492,15 +493,17 @@ template CharType charToDigit(CharType character, CharType b * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), bufferToNumber() */ -template , std::is_unsigned, Traits::Not>>> * = nullptr> -IntegralType stringToNumber(const StringType &string, IntegralType base = 10) +template , std::is_unsigned, Traits::Not>>> + * = nullptr> +IntegralType stringToNumber(const StringType &string, BaseType base = 10) { IntegralType result = 0; for (const auto &c : string) { if (c == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(c, static_cast(base))); } return result; @@ -513,7 +516,8 @@ IntegralType stringToNumber(const StringType &string, IntegralType base = 10) * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), bufferToNumber() */ -template , std::is_signed, Traits::Not>>> * = nullptr> +template , std::is_signed, Traits::Not>>> * = nullptr> IntegralType stringToNumber(const StringType &string, IntegralType base = 10) { auto i = string.begin(); @@ -532,7 +536,7 @@ IntegralType stringToNumber(const StringType &string, IntegralType base = 10) if (*i == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(*i, static_cast(base))); } return negative ? -result : result; @@ -547,7 +551,8 @@ IntegralType stringToNumber(const StringType &string, IntegralType base = 10) * \a base and types). * \sa numberToString(), bufferToNumber() */ -template , Traits::Not>>> * = nullptr> +template , Traits::Not>>> * = nullptr> FloatingType stringToNumber(const StringType &string, int base = 10) { std::basic_stringstream ss; @@ -571,15 +576,16 @@ FloatingType stringToNumber(const StringType &string, int base = 10) * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), bufferToNumber() */ -template , std::is_unsigned> * = nullptr> -IntegralType stringToNumber(const CharType *string, IntegralType base = 10) +template , std::is_unsigned> * = nullptr> +IntegralType stringToNumber(const CharType *string, BaseType base = 10) { IntegralType result = 0; for (; *string; ++string) { if (*string == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(*string, static_cast(base))); } return result; @@ -618,15 +624,16 @@ FloatingType stringToNumber(const CharType *string, int base = 10) * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), stringToNumber() */ -template , std::is_unsigned> * = nullptr> -IntegralType bufferToNumber(const CharType *string, std::size_t size, IntegralType base = 10) +template , std::is_unsigned> * = nullptr> +IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10) { IntegralType result = 0; for (const CharType *end = string + size; string != end; ++string) { if (*string == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(*string, static_cast(base))); } return result; @@ -639,7 +646,8 @@ IntegralType bufferToNumber(const CharType *string, std::size_t size, IntegralTy * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), bufferToNumber() */ -template , std::is_signed> * = nullptr> +template , std::is_signed> * = nullptr> IntegralType stringToNumber(const CharType *string, IntegralType base = 10) { if (!*string) { @@ -659,7 +667,7 @@ IntegralType stringToNumber(const CharType *string, IntegralType base = 10) if (*string == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(*string, static_cast(base))); } return negative ? -result : result; @@ -672,8 +680,9 @@ IntegralType stringToNumber(const CharType *string, IntegralType base = 10) * \throws A ConversionException will be thrown if the provided \a string is not a valid number. * \sa numberToString(), stringToNumber() */ -template , std::is_signed> * = nullptr> -IntegralType bufferToNumber(const CharType *string, std::size_t size, IntegralType base = 10) +template , std::is_signed> * = nullptr> +IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10) { if (!size) { return 0; @@ -693,7 +702,7 @@ IntegralType bufferToNumber(const CharType *string, std::size_t size, IntegralTy if (*string == ' ') { continue; } - result *= base; + result *= static_cast(base); result += static_cast(charToDigit(*string, static_cast(base))); } return negative ? -result : result;