Reputation: 733
I've created a template for casting strings do different data types, and it's having issues when the data type is an unsigned char.
template<class TYPE>
bool TryParse(const std::string value, TYPE &out)
{
std::istringstream iss(value);
iss >> out;
if (iss.fail())
{
return false;
}
return true;
}
The problem is the istringstream
will treat the first character it sees as a char, instead of treating it as a numeric string. So if I pass a value of "255", the value returned will be '2'.
Would the best solution be casting the out
variable as an unsigned int, perform the operation, then cast back again?
Upvotes: 1
Views: 325
Reputation: 169221
I would suggest having an overload that applies specifically to unsigned char
cases since you need to use an intermediate type.
bool TryParse(const std::string & value, unsigned char & out)
{
std::istringstream iss(value);
unsigned int i;
iss >> i;
if (iss.fail()) { return false; }
// The less-than-min check is technically redundant because both i and out
// are unsigned, but it makes me feel better having it there. It will become
// necessary for the "signed char" overload, anyway.
if (i > std::numeric_limits<unsigned char>::max() ||
i < std::numeric_limits<unsigned char>::min()) {
throw std::overflow_error();
// Or you could "return false" instead, if that makes more sense.
}
out = static_cast<unsigned char>(i);
return true;
}
You can use a nearly identical function for signed char
. (Just replace every unsigned
with signed
.)
I would not suggest using an intermediate type in your template, because you would need to use the widest possible type, and there isn't any one type that would work. unsigned long long int
wouldn't be compatible with signed long long int
, for example, and vice-versa -- and neither of those types would be compatible with float
or double
. Having a base template that uses the requested type directly, with overloads for problematic types (char
, for example) is the right approach.
Note that I have changed the value
parameter to be a reference to const string, as this means that the caller is not required to copy the string for no reason. I would suggest changing your template function as well.
Upvotes: 3