I have written a class that acts like an iterator to parse CSV formatted files. I have also written other classes to read specific csv files to fill directly a MyObject structure. Thus the class can be used like that (I removed the error handling part of the code):
std::ifstream in(filename);
MyObjectParser parser(in);
MyObjectParser::Iterator it;
for (it = parser.begin(); it != parser.end(); it++)
{
MyObject b = *it;
// do some stuff here ...
}
The program works well and I'm happy with it but I realized that the implicit meaning (only for myself?) of an iterator is that it will iterate over a collection. In this case there is no collection but a stream.
Should I prefer a form that explicitly suggest i'm using a stream by overloading >> operator and thus having something like that :
std::ifstream in(filename);
MyObjectReader reader(in);
MyObject obj;
while(reader >> obj)
{
// do the same "some stuff" here...
}
Is it only a matter of taste? I don't see clearly what are the differences (except that in the second form the object is just filled and not copied) and what are the consequences of choosing the first or the second form.
I would be happy to get some other opinions in order to know exactly why i'm using a solution rather than another.
An iterator can be used to iterate over the container elements. It can also provide access to those elements to modify their values. Iterators follow a generic approach for STL container classes. This way, the programmers don't need to learn about different iterators for different containers.
An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualised as something similar to a pointer pointing to some location and we can access content at that particular location using them.
The most obvious form of an iterator is a pointer. A pointer can point to elements in an array and can iterate through them using the increment operator (++).
You can treat a stream as a collection if you want.
I'd note, however, that by overloading operator>>
, you can have both -- you can explicitly read data from the stream using operator>>
directly, or you can treat the stream as a collection by using std::istream_iterator<whatever>
to treat it as a collection.
That being the case, it seems to me that overloading operator>>
is the obvious choice, since then you can treat things either way with essentially no extra work. In addition, using std::istream_iterator<x>
is a fairly recognizable idiom, since it's included in the standard library.
The concept of iteration is not dependent on that of containers. Iterators iterate over a sequence of values. Different iterator designs define the sequence in different ways, but there is always the ideas of current value, advance and reaching the end. About the only problem with input iterators is that they only terminate at the end of file; you cannot say, for example, that the next 10 lines contain doubles, and then we go on to something else. (But of course, you can insert a filtering streambuf in the stream to detect the end.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With