We have a file filled with integers, as an example we can think to a file created in this way:
const char* const filename = "someStuff.dat";
for(int i = 0; i < 10; ++i)
ofs << i << ' ';
To read it, we can think to loop on a ifstream open on that file, getting one single integer at time and pushing it in our container:
ifs >> value;
We know that is better to use range member methods, so we rewrite our solution using istream_iterator:
std::list<int> data(dataBegin, dataEnd);
Notice that we create the "begin" istream_iterator specifying the type we are expecting in the file, and an ifstream to the file itself.
The "end" istream_iterator requires just the data type.
Do we really need to give names to the iterators? Actually not. They are used only in the list ctor, so we could create them there on the fly. The issue in doing this, is that we have to pay attention in writing it right:
std::list<int> data((std::istream_iterator<int>(ifs)), std::istream_iterator<int>());
The parentheses around the first iterator in the list ctor are mandatory. If you don't put them, for the compiler we are declaring a function, and not defining a list object.
I love the Effective C++ books by Scott Meyers. Currently, I'm reading the STL instalment. This post is written in connection to its Item 6.