Anton Pevtsov wrote:
Martin, I am working on the test for lib.string.io and there are several
questions:

I'm not surprised ;-) The area of iostreams and locales are in
general less cleanly specified than the rest of the library.


1. Shall we implement an our own locale class to exercise the >> and <<
operators using it?

There is only one locale class and it cannot be replaced by
a user-defined one. You can customize the behavior of the class
by installing your own facets as replacements for the standard
ones in it. The only facet that affects the behavior of the string
I/O functions is ctype. It's fairly easy to replace the standard
ctype facet with your own:

    struct MyCtype: std::ctype<char> { /* ... */ };
    const std::locale myloc =
        std::locale (std::locale (), new MyCtype);
    std::istream strm;
    strm.imbue (myloc);

In the user-defined ctype facet it's important to override all
the virtual member functions that share the same behavior (in
our case both overloads of do_is(), do_scan_is(), as well as
do_scan_not()).

There are a number of iostream and locale tests with examples
of to do this.


2. Small question about 21.3.7.9, paragraph 4:

"
Effects: Begins by constructing a sentry object k as if k were
constructed by typename basic_ostream<chart, thraits>::sentry k(os). If bool(k) is true, inserts characters as if by calling
os.rdbuf()->sputn(str.data(), n), padding as described in stage 3 of
22.2.2.2.2, where n is the larger of os.width() and str.size(); then
calls os.width(0). If the call to sputn fails, calls
os.setstate(iosbase::failbit).
"

As I understand os.width(0) should be called if bool(k) is true only. I
not sure, but Dinkumware STL from MSVC and STLPort does that while
stdcxx calls os.with(0) in any case:
[...]
Is this correct?

I believe your reading is correct: our behavior is wrong. Could you
open an issue please? (In your test case, please use the assert macro
to verify the postconditions.)

The attached small test (iocheck.cpp) to illustrate this situation.
3. Another small question about 21.3.7.9 paragraph 4:

The stdcxx calls os.setstate(ios_base::badbit).

Hmmm, that would also be wrong. Badbit is typically set in response
to "bad" (i.e., unrecoverable) streambuf errors such as exceptions,
and failbit in response to the recoverable ones. Although I note
that the majority of implementations (including g++, IBM XLC++,
and MSVC) do set badbit as well.

OTOH, it's not clear that the behavior of your test case is wrong,
either. The string overload of operator<<) is required to set failbit
when the call to xsputn() fails but there doesn't seem to be any way
for the function to indicate failure (except by throwing an exception).
So strictly speaking the standard allows implementations to choose
whether to set failbit or leave it clear (depending on how they
interpret the value returned from xsputn).

That said, I think it makes sense to consider xsputn(s, n) as having
failed when it returns any value other than n (I sent an email to the
committee's reflector proposing this change -- see the attachment),
and for the inserter to set failbit in response to it.

Thanks
Martin
--- Begin Message ---
To: C++ libraries mailing list
Message c++std-lib-17241

The function doesn't specify a return value to indicate a failure.
This is a problem for inserters such as the one overloaded for
basic_string which are supposed to set failbit when sputn() fails.
How can the inserter tell that the call failed?

From what I've seen implementations treat a return value that's
different from the second argument of the call as an indication
of failure. I suggest to change the Returns clause to make that
clear.

Here's my proposed wording: Change 27.5.2.4.5, p2 to read:

  -2- Returns: The number of characters writter. A value other
      than n to indicate a failure.

Martin

--- End Message ---

Reply via email to