Title
std::print should permit an efficient implementation
Status
lewg
Section
[print.fun]
Submitter
Victor Zverovich

Created on 2024-01-20.00:00:00 last changed 9 months ago

Messages

Date: 2024-03-12.01:17:28

Proposed resolution:

This wording is relative to N4971.

  1. Modify [print.fun] as indicated:

    void vprint_unicode(FILE* stream, string_view fmt, format_args args);
    

    -6- Preconditions: stream is a valid pointer to an output C stream.

    -7- Effects: The function initializes an automatic variable via

    string out = vformat(fmt, args);
    

    If stream refers to a terminal capable of displaying Unicode, writes out to the terminal using the native Unicode API; if out contains invalid code units, the behavior is undefined and implementations are encouraged to diagnose it. Otherwise writes out to stream unchanged. If the native Unicode API is used, the function flushes stream before writing out.

    If writing to the terminal or stream fails, some arguments in args may not be formatted.

    […]

    […]
    void vprint_nonunicode(FILE* stream, string_view fmt, format_args args);
    

    -11- Preconditions: stream is a valid pointer to an output C stream.

    -12- Effects: Writes the result of vformat(fmt, args) to stream. If writing to stream fails, some arguments in args may not be formatted.

    -13- Throws: […].

Date: 2024-03-15.00:00:00

[ 2024-03-12; Reflector poll ]

Set priority to 3 and status to LEWG after reflector poll in January 2024.

"This loses the guarantee that if the formatting throws then there's no output."

Date: 2024-02-15.00:00:00

[ 2024-02-19; Feb 2024 mailing ]

This would be resolved by P3107.

Date: 2024-01-20.00:00:00

std::print/std::vprint* is currently defined in terms of formatting into a temporary string, e.g. [print.fun]:

void vprint_nonunicode(FILE* stream, string_view fmt, format_args args);

Preconditions: stream is a valid pointer to an output C stream.

Effects: Writes the result of vformat(fmt, args) to stream.

Throws: Any exception thrown by the call to vformat ([format.err.report]). system_error if writing to stream fails. May throw bad_alloc.

This is done to make it clear that noninterleaved output is desired while keeping specification simple and portable.

Unfortunately, the current specification seems to prohibit a more efficient implementation that performs formatting directly into a stream buffer under a lock (flockfile/funlockfile in POSIX) like printf does. The difference can be observable in case of an I/O error that occurs before a custom formatter is called. In the (double buffered) implementation that directly follows the spec all formatters will be called, while in a more efficient (locking) implementation subsequent formatters may not be called.

The easiest fix, given in the current proposed resolution, is to say that some arguments may not be formatted in case of a write error. It might be a bit weird considering that the spec says that we construct a string first so an alternative resolution is to replace vformat with vformat_to info some unspecified buffer iterator and state noninterleaving requirement separately.

History
Date User Action Args
2024-03-12 01:17:28adminsetmessages: + msg14000
2024-03-12 01:17:28adminsetstatus: new -> lewg
2024-02-19 12:29:05adminsetmessages: + msg13951
2024-01-21 07:57:35adminsetmessages: + msg13927
2024-01-20 00:00:00admincreate