2

我继承了一个将字符串转换为数值的模板,并希望将其应用于转换为boolean。我对 stringstream 和 locale 类不是很有经验。我似乎确实有一些奇怪的行为,我想知道是否有人可以向我解释一下?

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

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

return num;  
}  

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

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

我花了一些时间来追踪问题。我已确认语言环境的 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_

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

4

2 回答 2

7

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

导致您出现问题的原因是默认情况下流仅识别值0并且1在处理布尔值时。要让他们识别名称true和,您需要使用操纵器false将其明确告知流。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;  
}  

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

编辑:修改代码以处理数字和 alpha 布尔值。

于 2010-10-07T11:30:51.750 回答
1

这是因为从 'true' 的字符串流转换失败 - 您的函数模板应该SStream.fail()在它返回之前进行检查,这样您就可以更容易地发现类似的失败。

当你初始化 bool 时,它的值为 false。当您不初始化它时(在删除 = 0 之后),它是随机垃圾(通常非零)并返回 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;  
} 
于 2010-10-07T11:36:06.760 回答