On Thu, 28 Sep 2017 13:38:06 +0100
Jonathan Wakely<jwakely@redhat.com> wrote:
On 28/09/17 15:06 +0300, Petr Ovtchenkov wrote:
On Thu, 28 Sep 2017 11:34:25 +0100
Jonathan Wakely<jwakely@redhat.com> wrote:
+ VERIFY(i == std::istreambuf_iterator<char>());
+
+ VERIFY(memcmp(b, r, 36) == 0);
+
+ s << q;
+ VERIFY(!s.fail());
+
+ copy_n(i, 36, r);
This is undefined behaviour. The end-of-stream iterator value cannot
be dereferenced.
Within this test istreambuf_iterator in eof state never dereferenced.
That is quite implementation dependent.
The libc++ and VC++ implementations fail this test, because once an
istreambuf_iterator has been detected to reach end-of-stream it
doesn't get "reset" by changes to the streambuf.
If we will keep even "unspecified" behaviour same, then bug fix/drawback
removing become extremely hard: it should be identified as drawback
in all libs almost simultaneously.
The libc++ implementation crashes, because operator== on an
end-of-stream iterator sets its streambuf* to null, and any further
increment or dereference will segfault.
So this is testing something that other implementations don't support,
and isn't justifiable from the standard.
I will use N4687 as reference.
27.2.3 par.2 Table 95:
++r
Requires: r is dereferenceable. Postconditions: r is dereferenceable or r is
past-the-end; any copies of the previous value of r are no longer required
either to be dereferenceable or to be in the domain of ==.
(void)r++ equivalent to (void)++r
*r++
{ T tmp = *r;
++r;
return tmp; }
[BTW, you see that r++ without dereference has no sense, and even more,
copies of the previous
value of r are no longer
required either to be
dereferenceable or to be in
the domain of ==.
From this follow, that postfix increment operator shouldn't return
istreambuf_iterator.
]
The test itself simulate "stop and go" istream usage.
stringstream is convenient for behaviuor illustration, but in "real life"
I can assume socket or tty on this place.
At the very minimum we should have a comment in the test explaining
how it relies on non-standard, non-portable behaviour.
But I'd prefer to avoid introducing more divergence from other
implementations.
Standard itself say nothting about "stop and go" scenario.
At least I don't see any words pro or contra.
But current implementation block usage of istreambuf_iterator
with underlying streams like socket or tty, so istreambuf_iterator become
almost useless structure for practice.