1

I am reading C++ Practical Programming by Example by Andrew Koenig (Author) and in the chapter 4.1.3 Reading homework grades, there is this snippet:

istream& read_hw(istream& in, vector<double>& hw){
    //if(in){      /* HOW can be istream be used as bool in condition? -> commented out, this is not needed */     
        //hw.clear();     /*WHY to clear vector, when every instance is used only once? -> commented out, not needed*/

        double x;
        while(cin >> x)
            hw.push_back(x);

        //in.clear();      /* why to clear istream from error state, when if wrong value is passed, it is ignored anyway -> commented out*/ 
    //}      /* this is connected with the if-block */
    return in;    /*how is now in(istream) modified? where is binding between `std::cout` and `in`?? */
}

I have several question:

  1. return value : Why does the function have istream type as return value? Why is not the function void? It does not have to return any value, when the only purpose of that function is to populate the vector. (this question is connected with the last one, about how is istream in modified)

  2. if(in) : as in comments, I know it could have true value if std::basic_ios::good according to documentation, however, the istream in parameter is fresh instance, and therefor should not have any error state before it is called, therefor the if clause is redundant.

  3. hw.clear() : again, there is no need to clear the vector. It is a fresh instance, it was nowhere populated before in the program, so why to do this?

  4. in.clear() : this one is really bother me. Is this even essential to do in non-parallel process? I can think of one case when to clear buffer and that is when fatal error occure, otherwise, I see no point to clear buffer, when the buffer itself take care of error -> wrong value was passed (that is other value then double in this case) => buffer simply ignore it, or EOF was invoked => buffer will end reading. the buffer takes care of it all.

  5. The last one - how is std::cout connected with in? quotation from the book:

We don't know the details of how cin works, but presumably the library defines it as a data structure that stores everything the library needs to know about the state of our input file. Reading input from the standard input file changes the state of the file, so it should logically change the value of cin as well.

I can imagine the std::cin buffer is indeed modified from input from keyboard words (separated by whitespace), however where is the connection between the std::cout and in, there is only while(cin >> x) which modifies the cin, but how does cin know to copy those data in another buffer in? Or what is even the purpose of in when the only purpose of that function is to populate the vector? I guess it is somehow connected with returning the somehow now "modified" in at the end, but I cannot really see the connection between those two buffers.

I know this is related to the book above, so if you have not read it, you probably do not have context, but some questions do not need the context.

// comments mean part of original code that I commented out thinking it is not needed, and if compiled, it still works, so It indeed is not needed.

/**/ explains why I think it is not needed

Anyway sorry for these beginner questions, my background is only c.

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • The code you show doesn't actually use `in` for reading. And there's no apparent "binding" between the stream referenced by in` and `std::cout` (unless `in` references `std::cin`, which we don't know). – Some programmer dude Jul 03 '20 at 19:00
  • 1
    Regarding point two, how would the `read_hw` function even know what stream is actually passed for `in`? How does it know that the stream is "fresh"? The answer is: It *doesn't*. – Some programmer dude Jul 03 '20 at 19:01
  • Regarding point five, it allows you to "chain" function calls or operators. This is especially useful (and required) if you want to create manipulators (which your `read_hw` function could be used for, once you fix some of your problems). – Some programmer dude Jul 03 '20 at 19:05
  • @Someprogrammerdude how does manipulators differ from functions/ – milanHrabos Jul 03 '20 at 19:13
  • Any callable object (function, function object, lambda) with the right set of arguments and return type could be used as a stream manipulator. See e.g. [here](https://accu.org/index.php/journals/1769) for some examples. – Some programmer dude Jul 04 '20 at 05:09

1 Answers1

1
  1. return value : Why does the function have istream type as return value? Why is not the function void?

The function type certainly could be void, you are correct. However, returning an istream& allows chaining, like the following:

std::string name;
read_hw(cin, gradevec) >> name; 

This would place the first non-double value received from cin into the name variable. Admittedly this is kind of a contrived example and not the most readable, but it does show how it can work.

  1. if(in) : as in comments, I know it could have true value if std::basic_ios::good according to documentation, however, the istream in parameter is fresh instance

No, it is not a fresh instance, it is a reference (signified by ampersand & in istream& in) that has already been defined outside of the function.

  1. hw.clear() : again, there is no need to clear the vector. It is a fresh instance, it was nowhere populated before in the program, so why to do this?

Again, in fact it is not a fresh instance, it is a reference to a pre-existing vector (vector<double>&). C does not have references like this, it only has pointers, so this answer may help you understand better what's going on.

  1. in.clear() : this one is really bother me. Is this even essential to do in non-parallel process? I can think of one case when to clear buffer and that is when fatal error occur.

in.clear() somewhat confusingly does not clear the entire buffer, it only clears the various state flags like a failbit or badbit that you wouldn't want to stick around and cause future I/O operations to fail.

  1. The last one - how is std::cout connected with in?

For this one I can only guess the author made a mistake and meant to write while(in >> x). Otherwise there is no point to working with in at all.

jdaz
  • 5,964
  • 2
  • 22
  • 34