stringstream operator>>作为函数失败,但作为实例工作?

时间:2009-11-30 23:16:10

标签: c++ stringstream

我正在编写简单的代码,它将从文件中提取一堆名称,int对。我正在修改刚刚使用的现有代码:

string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
    //  save values
}

但我想使用另一个(类似的)输入文件,它具有相同的前两列,但后跟其他数据(将被忽略)。 所以我写道:

string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}

但这无法编译,给出了典型的淫秽std lib模板:

 error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]

右。 line不是std :: string,而是std :: basic_string等的一些变体。 但是,显式实例化stringstream有效。

string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
    stringstream ss(line);
    if ( ss >> chrom >> size ) {
       // save values
    }
    // Discard remainder of line
}

为什么呢?第一种情况有什么问题?始终有用的cplusplus.com example basic_io有效,为什么我的代码不行?

更新: 另一个参考点:当提取的第一个值是int而不是字符串时,临时字符串流工作:

unsigned int chrom;  // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}

4 个答案:

答案 0 :(得分:2)

C和C ++中的某些运算符要求运算符左侧的值为左值,即它们可以被修改。

Here是一个更完整的解释。

答案 1 :(得分:2)

为了扩展John Weldon的答案,外设运算符“&gt;&gt;”做两件事:

  1. 提取下一个值并将其放入运算符右侧的变量中。
  2. 增加左侧流的当前位置。
  3. 因此,它会修改左右操作数。在您的情况下,左侧操作数是临时值,编译器在修改它时会皱眉。

答案 2 :(得分:2)

三组成员函数和一组全局函数重载此“提取运算符”(&gt;&gt;),请参阅http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

  • 字符串流(线); - 创建一个临时对象
  • stringstream ss(line); - 一个普通对象。

当“chrom”为int时,运算符&gt;&gt;被重载为算术提取器,它是成员函数。普通对象或临时对象都可以正常工作。

当“chrom”是字符串时,运算符&gt;&gt;应该重载为istream& operator>> (istream& is, char* str),这是一个全局函数,应该将对象引用作为参数。但是,给定临时对象,我们不允许在标准C ++中通过非const引用传递临时对象。除非将重载函数定义为istream& operator>> (const istream& is, char* str),否则重载函数无法获取临时对象的引用。不幸的是,这不是事实。函数不能在临时对象的情况下重载,因此给出错误,如error: no match for function...

答案 3 :(得分:1)

因为从stringstream提取的第一个值是std :: string。如果它是一个int,那么stringstream(line)版本就可以工作。

没有成员函数运算符&gt;&gt;在stringstream中为std :: string。因此,临时流不能作为左值。

并非我完全理解上述内容......但也许这是一个更好答案的起点。