3

我对以下标记字符串的代码有疑问(用空格分隔标记)。

#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string s="And I feel fine ...";
    istringstream ss(s);
    vector<string> tokens{istream_iterator<string>(ss),{}};
    for(auto& elem: tokens)
        cout << elem << endl;
}

这工作得很好。另一方面,如果我尝试将临时istringstream对象传递给 istream_iterator(3-rd line inside main),例如

vector<string> tokens{istream_iterator<string>(istringstream(s)),{}};

我收到编译时错误 error: no matching conversion for functional-style cast from 'istringstream' (aka 'basic_istringstream<char>') to 'istream_iterator<string>'

我相信这是因为我不能将临时右值绑定到非常量左值引用,并且构造函数istream_iterator将引用作为参数。有没有办法istream_iterator<string>从临时构建一个?我也不能std::ref在临时对象上使用...

谢谢!

4

1 回答 1

3

使用std::skipw技巧:

std::vector<std::string> tokens{
    std::istream_iterator<std::string>(std::istringstream(s) >> std::skipws), {}
};

这是有效的,因为提取器返回一个对流的左值引用,并且设置std::skipw不会有任何影响,因为它默认在所有流上启用。要在一般情况下使用它,您可能希望有一个接受通用引用的函数,然后返回对该对象的引用:

template<typename T>
T& lvalue(T&& x)
{
    return x;
}

// ...
std::istream_iterator<std::string>(lvalue(std::istringstream(s)));

确保引用没有在完整表达式之后使用,否则您将有一个悬空引用,因为临时引用已经被破坏。

于 2014-05-17T18:03:15.273 回答