2943. Problematic specification of the wide version of basic_filebuf::open

Section: 31.10.3.4 [filebuf.members] Status: C++20 Submitter: Tim Song Opened: 2017-03-09 Last modified: 2021-02-25

Priority: 2

View all other issues in [filebuf.members].

View all issues with C++20 status.

Discussion:

LWG 2676 specified basic_filebuf::open(const std::filesystem::path::value_type* s, ios_base::openmode mode) by simply reusing the specification for the const char* overload, but that specification is incorrect for the wide overload: it says that s is an NTBS — a null-terminated byte string — which it isn't. Moreover, it specifies that the file is opened as if by calling fopen(s, modstr), but that call is ill-formed if s isn't a const char*.

[2017-07 Toronto Wed Issue Prioritization]

Priority 2

[2017-11 Albuquerque Wednesday issue processing]

Status to Open; Jonathan to provide wording.

[2018-01-16; Jonathan and Tim Song provide wording]

We'll have to ask the Microsoft guys if "as by a call to fopen" is OK for them. There are paths that can be represented as a wide character string that can't reliably be converted to narrow characters (because they become dependent on the current codepage, or some other Windows nonsense) so they definitely won't use fopen. But as long as they call something that behaves like it (which should allow _fwopen), I think they'll still meet the spirit of the wording.

[2018-08-14; Marshall corrects a grammar nit in the P/R]

The Microsoft guys note that "as by a call to fopen" is OK by them.

Previous resolution [SUPERSEDED]:

This wording is relative to N4713.

  1. Edit 31.10.3.4 [filebuf.members] as indicated:

    basic_filebuf* open(const char* s, ios_base::openmode mode);
    basic_filebuf* open(const filesystem::path::value_type* s,
                        ios_base::openmode mode); // wide systems only; see 31.10.1 [fstream.syn]
    

    -?- Requires: s shall point to a NTCTS (3.35 [defns.ntcts]).

    -2- Effects: If is_open() != false, returns a null pointer. Otherwise, initializes the filebuf as required. It then opens the file to which s resolves, if possible, as if by a call to fopen with the second argumenta file, if possible, whose name is the ntbs s (as if by calling fopen(s, modstr)). The ntbs modstr is determined from mode & ~ios_base::ate as indicated in Table 117. If mode is not some combination of flags shown in the table then the open fails.

    -3- If the open operation succeeds and (mode & ios_base::ate) != 0, positions the file to the end (as if by calling fseek(file, 0, SEEK_END), where file is the pointer returned by calling fopen).(footnote 330)

    -4- If the repositioning operation fails, calls close() and returns a null pointer to indicate failure.

    -5- Returns: this if successful, a null pointer otherwise.

[2018-08-23 Batavia Issues processing]

Adopted after changing 'Requires' -> 'Expects' in the P/R.

[2018-11, Adopted in San Diego]

Proposed resolution:

This wording is relative to N4713.

  1. Edit 31.10.3.4 [filebuf.members] as indicated:

    basic_filebuf* open(const char* s, ios_base::openmode mode);
    basic_filebuf* open(const filesystem::path::value_type* s,
                        ios_base::openmode mode); // wide systems only; see 31.10.1 [fstream.syn]
    

    -?- Expects: s shall point to a NTCTS (3.35 [defns.ntcts]).

    -2- Effects: If is_open() != false, returns a null pointer. Otherwise, initializes the filebuf as required. It then opens the file to which s resolves, if possible, as if by a call to fopen with the second argumenta file, if possible, whose name is the ntbs s (as if by calling fopen(s, modstr)). The ntbs modstr is determined from mode & ~ios_base::ate as indicated in Table 117. If mode is not some combination of flags shown in the table then the open fails.

    -3- If the open operation succeeds and (mode & ios_base::ate) != 0, positions the file to the end (as if by calling fseek(file, 0, SEEK_END), where file is the pointer returned by calling fopen).(footnote 330)

    -4- If the repositioning operation fails, calls close() and returns a null pointer to indicate failure.

    -5- Returns: this if successful, a null pointer otherwise.