num_get facet和stringstream转换为boolean - 失败并初始化布尔值?

you*_*ing 2 c++ templates initialization std stringstream

我继承了一个模板来将字符串转换为数值,并希望将其应用于转换为布尔值.我对stringstream和locale类不太熟悉.我似乎得到了一些奇怪的行为,我想知道是否有人可以向我解释一下?

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

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

return num;  
}  
Run Code Online (Sandbox Code Playgroud)

这工作正常,直到我尝试布尔转换

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

我花了一些时间来追查问题.我已经确认locale的truename()返回"true".

问题似乎是变量num的初始化.我可以将模板更改为此,它可以工作:

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_
Run Code Online (Sandbox Code Playgroud)

它为什么有效?我接受用'0'初始化一个bool是错误的,但为什么这会导致SStream>>num转换失败?

Bar*_*nau 7

使用0初始化bool将可靠地将其设置为false,这对流提取没有影响.

造成问题的原因是默认情况下,流只识别值01处理布尔值.让他们认识的名字truefalse,你需要明确地告诉与流boolalpha操纵.

解决问题的最佳方法是专门为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;  
}  
Run Code Online (Sandbox Code Playgroud)

请注意,你的变化并没有使代码工作.它似乎只适用于您使用的单个测试用例.通过更改,该函数无法从流中读取并返回未初始化的值.由于任何非零值都将被解释为true,因此该函数似乎可以正常工作,但是一旦您尝试提取"false",您将看到它失败(该函数仍然返回true).

编辑:修改代码以处理数字和alpha bool.