num_get facet and stringstream conversion to boolean - fails with initialised boolean?

早过忘川 提交于 2019-12-12 09:09:50

问题


I have inherited a template to convert a string to a numerical value, and want to apply it to convert to boolean. I am not very experienced with the stringstream and locale classes. I do seem to be getting some odd behaviour, and I am wondering if someone could please explain it to me?

template<typename T> T convertFromString( const string& str ) const {

std::stringstream SStream( str );  
T num = 0; 
SStream >> num;

return num;  
}  

This works fine until I try the boolean conversion

string str1("1");
int val1 = convertFromString<int>(str1); // ok
string str2("true");
bool val2 = convertFromString<bool>(str2); // val2 is _false_

I spent some time tracking down the problem. I have confirmed that the locale's truename() returns "true".

The problem seems to be with the initialisation of the variable num. I can change the template to this and it works:

template<typename T> T convertFromString( const string& str ) const {

std::stringstream SStream( str );  
T num;  // <----------------------- Changed here
SStream >> num;

return num;  
}  
string str2("true");
bool val2 = convertFromString<bool>(str2); // val2 is _true_

Why does it work? I accept that initialising a bool with '0' is wrong, but why would this cause the SStream>>numconversion to fail?


回答1:


Initialising a bool with 0 will reliably set it to false, and this has no effect on the stream extraction.

What is causing your problem is that streams by default only recognize the values 0 and 1 when dealing with booleans. To have them recognize the names true and false, you need to tell that explicitly to the stream with the boolalpha manipulator.

The best way to solve your problems is to specialize the template for bool:

template<> bool convertFromString<bool>( const string& str ) const {
  std::stringstream SStream( str );  
  bool val = false;
  SStream >> val;
  if( SStream.fail() )
  {
    SStream.clear(); 
    SStream >> boolalpha >> val; 
  }    
  return val;  
}  

Note that your change did not make the code work. It just appeared to do so for the single testcase you used. With your change, the function failed to read from the stream and returned an uninitialised value. As any non-zero value will be interpreted as true, the function appears to work, but as soon as you try to extract "false", you will see it fail (the function still returns true).

Edit: Adapted the code to handle both numeric and alpha bools.




回答2:


This is because the stringstream conversion from 'true' fails - your function template should check SStream.fail() before it returns, so you can discover similar failures more easily.

When you init the bool its value is false. When you don't init it (after you remove the = 0), it is random garbage (usually non-zero) and returns true.

template<typename T> T convertFromString( const string& str ) {

std::stringstream SStream( str );  
T num = 0; 
SStream >> num;

if (SStream.fail())
{
    // conversion failure - handle error
    bool error = true;
}

return num;  
} 


来源:https://stackoverflow.com/questions/3880927/num-get-facet-and-stringstream-conversion-to-boolean-fails-with-initialised-bo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!