3

Following up https://stackoverflow.com/a/1120224/390066.

Why can't I use

getline(stringstream(line),cell,','){}

instead of

stringstream lineStream(line); 
getline(lineStream,cell,','){}

?

update

I should have clarified that I want to use getline within a loop.

Furthermore, I should have also noted that my initial intention was to read a file line-by-line using getline and use the line from that in the new getline that would divide on ',', which is more intuitive imo.

From what I understood so far, getline is not designed for that because it takes a non-const input and gives const token; therefore, getline cannot be blindly recursed.

Community
  • 1
  • 1
kirill_igum
  • 3,953
  • 5
  • 47
  • 73
  • getline would change some temp object which would be always the same unchanged one. – NaCl Nov 17 '14 at 18:09
  • Would it be of any significance to store value in a temporary variable... – ravi Nov 17 '14 at 18:11
  • 1
    Define `template T & stay(T && x) { return x; }` and try: `std::getline(stay(std::istringstream(line)), cell, ',')`. – Kerrek SB Nov 17 '14 at 18:11
  • @KerrekSB Neat, except for the name:-), which suggests that it somehow extends the lifetime of the temporary. (The use of `flush()` is the consecrated idiom, although I wouldn't say that it's particularly transparent either. But it does work with pre-C++11.) – James Kanze Nov 17 '14 at 18:50
  • @JamesKanze: `stay` is the opposite of `move`. Neither actually changes the location of things :-) Maybe they should be renamed to `std::value_category_cast`! – Kerrek SB Nov 17 '14 at 20:02
  • @KerrekSB I hadn't thought of it like that. Seen that way, it's a good name. – James Kanze Nov 18 '14 at 09:36
  • @JamesKanze: I'm just parroting this from [an earlier post](http://stackoverflow.com/a/8116843/596781) (second code block). – Kerrek SB Nov 18 '14 at 09:54

2 Answers2

3

As show by @James Kanze you can.

The question is do you really want to?
The stream is destroyed at the end of the expression so you are only reading one cell from it.

If we look at this in the context of the original question:
i.e. You can not use that in a loop:

std::string       line = /* Init */;
std::stringstream lineStream(line); 

std::string cell;
while(std::getline(lineStream, cell, ','))
{
    // Do stuff with cell.
}

If you place your code into this context it will not work as expected:

std::string cell;
while(std::getline(std::istringstream(line).flush(), cell, ','))
{
    // Do stuff with cell.
}

As the expression inside the while() will be fully evaluated each time. So you go into an infinte loop reading the first cell continuously.

Community
  • 1
  • 1
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • He might want to. If he's using `getline`, there are more efficient and more natural ways of doing this using `std::find` or `std::find_if`; it might be useful for picking off an initial numerical value, however. (On the whole, like you, I'm skeptical. Normally, you'd want to check the status after extraction. But I'm sure there are cases.) – James Kanze Nov 18 '14 at 09:39
  • @JamesKanze: There are more efficient ways. But this is very natural to me. Using `std::find()` is more C like and requires more auxiliary code to get to the same point. So this technique is easy to teach with as all the details are handled for you while you can concentrate on the results. – Martin York Nov 18 '14 at 16:25
1

You can, but it's ugly:

std::getline( std::istringstream( line ).flush(), cell, ',' );

The problem is that std::getline takes a non-const reference (which is logical, since it is going to modify the stream), and you cannot initialize a non-const reference with a temporary. You can, however, call member functions on it. std::istream::flush is a member function, which returns a non-const reference to the stream on which it was called (and if that stream is an std::istringstream, doesn't do anything else).

FWIW: you'd probably find:

cell = std::string( line.cbegin(), std::find( line.cbegin(), line.cend(), ',' ) );

a bit more efficient. And, at least in my opinion, easier to read and maintain.

James Kanze
  • 150,581
  • 18
  • 184
  • 329