I can find surprisingly little useful information about how an overridden std::streambuf::overflow function should look like to simply get each character that's written to the stream. So I asked ChatGPT for some pointers. It keeps coming back to this concept:
int overflow(int c)
{
if (c == EOF)
{
// Flush the buffer here
return !EOF;
}
// Put c in the buffer here
if (c == '\n')
{
// Flush the buffer here
}
return c;
}
It's super weird that it returns !EOF
when c is EOF
.
The docs don't elaborate what "success" means.
This page says it should return EOF
(not !EOF
) when called with EOF
as the argument (or when signalling "a failure").
So: Is my suspicion correct that returning !EOF
here is wrong and that I should return EOF
instead?
Cookie points if you can tell me where ChatGPT got that idea from. I can't find return !EOF;
anywhere else on the internet.
This is what the C++ standard has to say about the return value:
[streambuf.virt.put]
int_type overflow(int_type c = traits::eof());
6 Returns:
traits::eof()
or throws an exception if the function fails.
Otherwise, returns some value other thantraits::eof()
to indicate success.(304)(Footnote 304) Typically,
overflow
returnsc
to indicate success, except whentraits::eq_int_type(c, traits::eof())
returnstrue
, in which case it returnstraits::not_eof(c)
.
Thus, the specific return value doesn't much matter, just whether it's traits::eof()
or not. There's a (non-normative) convention you may want to follow.
Re: what "success" means:
[streambuf.virt.put]/5 Requires: Every overriding definition of this virtual function shall obey the following constraints:
...
- Let
r
be the number of characters in the pending sequence not consumed. Ifr
is nonzero thenpbase()
andpptr()
shall be set so that:pptr() - pbase() == r
and ther
characters starting atpbase()
are the associated output stream. In caser
is zero (all characters of the pending sequence have been consumed) then eitherpbase()
is set tonullptr
, orpbase()
andpptr()
are both set to the same non-null value.- The function may fail if either appending some character to the associated output stream fails or if it is unable to establish
pbase()
andpptr()
according to the above rules.
Thus, the function fails if it is unable to actually write to the underlying medium, or unable to restore the invariants. It succeeds if it managed both.