Value-initialization of an input iterator

403 views Asked by At

I am reading chapter 8 of the "Accelerated C++" book. Section 8.3 is about input and output iterators:

vector<int> v; // read ints from the standard input and append them to v
copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v));

[...]

The second argument to copy creates a default (empty) istream_iterator, which is not bound to any file. The istream_iterator type has a default value with the property that any istream_iterator that has reached end-of-file or is in an error state will appear to be equal to the default value. Therefore, we can use the default value to indicate the "one-past-the-end" convention for copy.

This is what I understand: istream_iterator is a template class, and istream_iterator< int> is an instance of the template. Writing istream_iterator< int>() triggers value-initialization of the istream_iterator< int> object, which means zero-initialization + call to implicit default constructor (http://en.cppreference.com/w/cpp/language/value_initialization). I thought that default-initialization of the istream_iterator< int> object would work as well (triggers call to default constructor), so I tried this:

vector<int> v; // read ints from the standard input and append them to v
copy(istream_iterator<int>(cin), istream_iterator<int>, back_inserter(v));

But this does not compile:

error: expected primary-expression before ‘,’ token

I don't understand what is going on. Any explanation is welcome.

4

There are 4 answers

0
Mike Seymour On BEST ANSWER

There's no way to default-initialise, rather than value-initialise, a temporary. While the expression type() creates a value-initialised temporary, a type name alone is not a valid expression.

However, for any type (like this one) that declares a default constructor, default-initialisation and value-initialisation are equivalent; there is no zero-initialisation before a non-implicit constructor is called.

0
P0W On

istream_iterator is a "templated" class Provides two constructor :

  basic_istream<charT,traits>* in_stream;
  istream_iterator() : in_stream(0) {}
  istream_iterator(istream_type& s) : in_stream(&s) { ++*this; }

Default constructor initializes in_stream to 0 used for end-of-stream

So,

istream_iterator<int> need () for EOF

Fix:- copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v));

0
juanchopanza On

In this context:

copy(istream_iterator<int>(cin), istream_iterator<int>, back_inserter(v));
//                               ^^^^^^^^^^^^^^^^^^^^^

the second argument, istream_iterator<int> is parsed as a type. You need an instance, so you need the (), with or without arguments. By the same token, the following wouldn't work:

void foo(int); // function declaration

int main()
{
  foo(int);
}
0
Pete Becker On

Don't get distracted by the template. The same problem will occur with any type name:

struct S {};

void f(int, S);

f(1, S);   // error: S is not an object
f(1, S()); // okay: S() constructs an object