This is an Minimal, Complete, Verifiable Example I understand that this is not copacetic. Anyway, given the struct:
struct Foo {
int even;
int odd;
};
istream& operator>>(istream& lhs, Foo& rhs) {
int input;
lhs >> input;
(input % 2 == 0 ? rhs.even : rhs.odd) = input;
return lhs;
}
I can do the following:
stringstream bar("1 2 3 4 5 6 7 8 9 0");
for (const auto& i : vector<Foo>{istream_iterator<Foo>(bar), istream_iterator<Foo>()}) {
cout << i.even << ' ' << i.odd << endl;
}
However this gives me the results:
-1215720516 1
2 1
2 3
4 3
4 5
6 5
6 7
8 7
8 9
0 9
To zero-initialize the Foo
I can write the code:
for(Foo i{}; bar >> i; i = Foo{}) {
cout << i.even << ' ' << i.odd << endl;
}
This gives m my expected result:
0 1
2 0
0 3
4 0
0 5
6 0
0 7
8 0
0 9
0 0
I understand that having an extraction operator that does not fully overwrite the variable is sketchy. This is initially stemming from my answer here and my question here which in my mind had a more natural expectation of zero-initializing the variable in-between reads. In any case, is it possible to use an istream_iterator
such that the variable is zero-initialized between reads, or must I use the for
-loop?
in my mind had a more natural expectation of zero-initializing the variable in-between reads
That is an incorrect expectation. operator>>
should completely and solely responsible for initializing the object. You cannot assume that the object will have been previously default/value-initialized. A pretty standard use-case is reading in all the objects in a while loop:
Foo foo;
while (std::cin >> foo) { ... }
The 2nd time through, foo
will have whatever the old values were - there is no zeroing anywhere here. So you need to make sure that when your operator returns, the new object is completely set by you.
The simplest thing is to value-initialize it first:
istream& operator>>(istream& lhs, Foo& rhs) {
int input;
lhs >> input;
rhs = Foo{}; // <== add this
input % 2 == 0 ? rhs.even : rhs.odd) = input;
return lhs;
}
Alternatively you could manually write both:
if (input % 2 == 0) {
rhs.odd = 0;
rhs.even = input;
}
else {
rhs.odd = input;
rhs.even = 0;
}
or aggregate-initialize each case:
rhs = input % 2 == 0 ? Foo{input, 0} : Foo{0, input};
Regardless, operator>>
is responsible for zeroing out values that you want zeroed out.