CS Student
CS Student

Reputation: 1633

istream_iterator invalid when using std::copy

I'm trying to copy some ints from stdin into a vector. I have the code working but I'm unsure why I need the () after the second argument of copy. By this I mean the istream_iterator<int>() argument in the copy call.

Code here...

#include <iterator>
#include <vector>
#include <iostream>

using std::vector;
using std::copy;
using std::cin;
using std::istream_iterator;

int main()
{   
     vector<int> nums;
     copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(nums)); // why do I need the empty brackets after the 2nd argument?

     return 0;
}   

If I remove the brackets I get an error from the compiler, however if I slightly modify my code to code below my program works fine.

int main()
{   
     vector<int> nums;
     istream_iterator<int> end; // no brackets used here
     copy(istream_iterator<int>(cin), end, back_inserter(nums)); 

     return 0;
}  

I'm coming from a Java background so empty brackets simply means you have used an empty constructor. The first code snippet goes against what I thought I understood, from my understanding in C++ if you want to use an empty constructor you simply miss off the () however this isn't the case here

help!

Upvotes: 2

Views: 175

Answers (3)

NathanOliver
NathanOliver

Reputation: 180595

The line

copy(istream_iterator<int>(cin), istream_iterator<int>, back_inserter(nums));

is meaningless. istream_iterator<int> is a type not an object. You need to use () to create an unnamed, temporary, default-constructed object of the type istream_iterator<int>.

Using

istream_iterator<int> end;

You declare an object of the type istream_iterator<int>, and you do not need the parentheses, as it is default-constructed without them. In fact, if you had used parentheses, like:

istream_iterator<int> end();

Then you would have run into a most vexing parse issue and end would now be a function taking nothing and returning a istream_iterator<int>.

Upvotes: 3

songyuanyao
songyuanyao

Reputation: 172924

It might be confusing but both cases creating an object by default constructor. And for the 1st case you must use (), for the 2nd case you must not use ().

istream_iterator<int>() creates a temporary object by default constructor. Without (), istream_iterator<int> is just a type name, which doesn't make sense because an instance of the type expected.

istream_iterator<int> end; creates a named object by default constructor too. You can't use () here, otherwise it will become a declaration of function, which takes no parameter and returns istream_iterator<int>. See Most vexing parse.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

I have the code working but I'm unsure why I need the () after the second argument of copy

You need them to construct an iterator in place, instead of declaring a separate variable representing one-past-the-end of an input stream. If you write

istream_iterator<int>

without parentheses, that would be a type name. With parentheses that's an invocation of a default constructor:

istream_iterator<int>()

An istream_iterator<int> object is constructed in place, and passed to std::copy as its second argument. By convention, the default constructor of istream_iterator<T> gives you an instance of the iterator that signals one-past-the-end of a stream.

Upvotes: 1

Related Questions