0

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.

Niko O
  • 406
  • 3
  • 15
  • @Someprogrammerdude Is calling it with EOF as an argument considered "successful"? Also, `Traits::eof()` is a constant value, so I'm not sure what you mean by "And if the stream has reached the end of the file Treats::eof() returns true". `!EOF` becomes `false`, which becomes 0. – Niko O Jan 27 '23 at 07:52
  • It's probably have to do with the function needing to return a value different from `Traits::eof()` on success. And apparently the code considers `EOF` to be a successful case. – Some programmer dude Jan 27 '23 at 07:55
  • With that said, ChatGPT is really unreliable for actual and factual information. It can generate text and code that seems good and real, but at closer inspection often isn't. There's a reason ChatGPT-generated answers have been forbidden here. I wouldn't trust any code it generates. – Some programmer dude Jan 27 '23 at 07:56
  • `!EOF` doesn't make any sense (it is just a funny way to spell the constant `false`). – n. m. could be an AI Jan 27 '23 at 08:19
  • There is also a `Traits::not_eof()` function. Perhaps that's what confuses the AI? Of course `not_eof()` is very different from `!EOF`. – BoP Jan 27 '23 at 08:50
  • @Someprogrammerdude Did you delete your comment I was replying to? Yes, ChatGPT isn't a reliable source and one needs to verify its output. That's... why I'm here. I wasn't blindly copying its output, but using it as a stepping stone. – Niko O Jan 27 '23 at 09:34

1 Answers1

1

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 than traits::eof() to indicate success.(304)

(Footnote 304) Typically, overflow returns c to indicate success, except when traits::eq_int_type(c, traits::eof()) returns true, in which case it returns traits::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:
...

  1. Let r be the number of characters in the pending sequence not consumed. If r is nonzero then pbase() and pptr() shall be set so that: pptr() - pbase() == r and the r characters starting at pbase() are the associated output stream. In case r is zero (all characters of the pending sequence have been consumed) then either pbase() is set to nullptr, or pbase() and pptr() are both set to the same non-null value.
  2. The function may fail if either appending some character to the associated output stream fails or if it is unable to establish pbase() and pptr() 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.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • So it's just one of those boneheaded C++-isms to use an int for what should have been a bool. Thank you for the explanation. – Niko O Jan 28 '23 at 18:42
  • @NikoO I suppose. Streams library was designed a very long time ago, by [one person](https://en.wikipedia.org/wiki/Alexander_Stepanov), and well predates the standardization effort. I suspect that if it were designed now, it would look very differently. My guess is, in the original design the return value was more than just a boolean; but that is lost to the mists of time. – Igor Tandetnik Jan 28 '23 at 19:09