1

I am making a GUI for images edition and I need to display and handle RGB values from the user. Hence I use uint8_t to store those values and stringstream to get/set the value from/to a string. My problem is that uint8_t is considered as a char so the cast returns only the first character of the string.

Example: Let say I set the input string "123", my returned value will be 49 (the ASCII code of '1')

As I use templated functions to make the casts, I'd like to make as few changes to the code as possible (of course). Here is the cast function I use:

template<typename T>
T Cast(const std::string &str) {
    std::stringstream stream;
    T value;
    stream << str;
    stream >> value;
    if (stream.fail()) {
        Log(LOG_LEVEL::LERROR, "XMLCast failed to cast ", str, " to ", typeid(value).name());
    }
    return value;
}

So when I do

uint8_t myInt = Cast<uint8_t>("123");

I get 49 rather than 123, any idea ?

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
CdS
  • 13
  • 4

2 Answers2

1

It seems like a cast is not the right tool for the job here. A cast is to reinterpret one value as a given type or convert similar types to each other (think, double to int and vice versa or base class pointer to derived class pointer). The types string and integer are not closely related in this way. I think what you want to do is explicitly convert the string to an integer which suggests std::stoi() is what you want.

void Foo( const std::string& str ) 
{
    const auto i = std::stoi( str );
    std::cout << i << '\n';
    // ...
}

int main()
{
    Foo( "123" );
}

Prints: 123. See it live on Coliru.

metal
  • 6,202
  • 1
  • 34
  • 49
  • *"A cast is to reinterpret one value as a given type."* Not quite. Most casts actually convert, they don't reinterpret. Except for `reinterpret_cast` which is used to reinterpret memory representation (for the very few cases where it's allowed). – François Andrieux Apr 22 '19 at 19:27
  • @FrançoisAndrieux Fair point. I have attempted to clarify. – metal Apr 22 '19 at 19:39
0

You need to read the value as an unsigned (short) int first (or uint(16|32)_t, if you like), then you can truncate it to uint8_t. Since your function is templated, you can simply provide a specialization for uint8_t to handle it differently from other types:

template<>
uint8_t Cast<uint8_t>(const std::string &str) {
    std::istringstream stream(str);
    uint16_t value;
    if ((!(stream >> value)) || (value > 0x00FF)) {
        Log(LOG_LEVEL::LERROR, "XMLCast failed to cast ", str, " to ", typeid(uint8_t).name());
    }
    return static_cast<uint8_t>(value);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770