This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.

### 2676. Provide `filesystem::path` overloads for File-based streams

Section: 29.10 [file.streams] Status: C++17 Submitter: Beman Dawes Opened: 2016-03-16 Last modified: 2017-07-30

Priority: 2

View all other issues in [file.streams].

View all issues with C++17 status.

Discussion:

The constructor and `open` functions for File-based streams in 27.9 [file.streams] currently provide overloads for `const char*` and `const string&` arguments that specify the path for the file to be opened. With the addition of the File System TS to the standard library, these constructors and `open` functions need to be overloaded for `const filesystem::path&` so that file-based streams can take advantage of class `filesystem::path` features such as support for strings of character types `wchar_t`, `char16_t`, and `char32_t`.

The `const filesystem::path& p` overload for these functions is like the existing `const string&` overload; it simply calls the overload of the same function that takes a C-style string.

For operating systems like POSIX that traffic in `char` strings for filenames, nothing more is required. For operating systems like Windows that traffic in `wchar_t` strings for filenames, an additional C-style string overload is required. The overload's character type needs to be specified as `std::filesystem::path::value_type` to also support possible future operating systems that traffic in `char16_t` or `char32_t` characters.

Not recommended:

Given the proposed constructor and `open` signatures taking `const filesystem::path&`, it would in theory be possible to remove some of the other signatures. This is not proposed because it would break ABI's, break user code depending on user-defined automatic conversions to the existing argument types, and invalidate existing documentation, books, and tutorials.

Implementation experience:

The Boost Filesystem library has provided header `<boost/filesystem/fstream.hpp>` implementing the proposed resolution for over a decade.

The Microsoft/Dinkumware implementation of standard library header `<fstream>` has provided the `const wchar_t*` overloads for many years.

[2016-08-03 Chicago]

Fri PM: Move to Review

Proposed resolution:

At the end of 27.9.1 File streams [fstreams] add a paragraph:

In this subclause, member functions taking arguments of `const std::filesystem::path::value_type*` shall only be provided on systems where `std::filesystem::path::value_type` ([fs.class.path]) is not `char`. [Note: These functions enable class `path` support for systems with a wide native path character type, such as `wchar_t`. — end note]

Change 27.9.1.1 Class template basic_filebuf [filebuf] as indicated:

    basic_filebuf<charT,traits>* open(const char* s,
        ios_base::openmode mode);
    basic_filebuf<charT,traits>* open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode);  // wide systems only; see [fstreams]
    basic_filebuf<charT,traits>* open(const string& s,
       ios_base::openmode mode);
    basic_filebuf<charT,traits>* open(const filesystem::path& p,
       ios_base::openmode mode);

Change 27.9.1.4 Member functions [filebuf.members] as indicated:

    basic_filebuf<charT,traits>* open(const char* s,
       ios_base::openmode mode);
    basic_filebuf<charT,traits>* open(const std::filesystem::path::value_type* s,
       ios_base::openmode mode);  // wide systems only; see [fstreams]

To 27.9.1.4 Member functions [filebuf.members] add:

    basic_filebuf<charT,traits>* open(const filesystem::path& p,
       ios_base::openmode mode);

> Returns: `open(p.c_str(), mode);`

Change 27.9.1.6 Class template basic_ifstream [ifstream] as indicated:

    explicit basic_ifstream(const char* s,
        ios_base::openmode mode = ios_base::in);
    explicit basic_ifstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]
    explicit basic_ifstream(const string& s,
        ios_base::openmode mode = ios_base::in);
    explicit basic_ifstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in);
    ...
    void open(const char* s,
        ios_base::openmode mode = ios_base::in);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]
    void open(const string& s,
        ios_base::openmode mode = ios_base::in);
    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in);

Change 27.9.1.7 basic_ifstream constructors [ifstream.cons] as indicated:

    explicit basic_ifstream(const char* s,
        ios_base::openmode mode = ios_base::in);
    explicit basic_ifstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]

To 27.9.1.7 basic_ifstream constructors [ifstream.cons] add:

    explicit basic_ifstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in);

> Effects: the same as `basic_ifstream(p.c_str(), mode)`.

Change 27.9.1.9 Member functions [ifstream.members] as indicated:

    void open(const char* s,
        ios_base::openmode mode = ios_base::in);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]

To 27.9.1.9 Member functions [ifstream.members] add:

    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in);

> Effects: calls `open(p.c_str(), mode)`.

Change 27.9.1.10 Class template basic_ofstream [ofstream] as indicated:

    explicit basic_ofstream(const char* s,
        ios_base::openmode mode = ios_base::out);
    explicit basic_ofstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]
    explicit basic_ofstream(const string& s,
        ios_base::openmode mode = ios_base::out);
    explicit basic_ofstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::out);
    ...
    void open(const char* s,
        ios_base::openmode mode = ios_base::out);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]
    void open(const string& s,
        ios_base::openmode mode = ios_base::out);
    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::out);

Change 27.9.1.11 basic_ofstream constructors [ofstream.cons] as indicated:

    explicit basic_ofstream(const char* s,
        ios_base::openmode mode = ios_base::out);
    explicit basic_ofstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]

To 27.9.1.11 basic_ofstream constructors [ofstream.cons] add:

    explicit basic_ofstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::out);

> Effects: the same as `basic_ofstream(p.c_str(), mode)`.

Change 27.9.1.13 Member functions [ofstream.members] as indicated:

    void open(const char* s,
        ios_base::openmode mode = ios_base::out);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]

To 27.9.1.13 Member functions [ofstream.members] add:

    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::out);

> Effects: calls `open(p.c_str(), mode)`.

Change 27.9.1.14 Class template basic_fstream [fstream] as indicated:

    explicit basic_fstream(const char* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    explicit basic_fstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]
    explicit basic_fstream(const string& s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    explicit basic_fstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    ...
    void open(const char* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]
    void open(const string& s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in|ios_base::out);

Change 27.9.1.15 basic_fstream constructors [fstream.cons] as indicated:

    explicit basic_fstream(const char* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    explicit basic_fstream(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]

To 27.9.1.15 basic_fstream constructors [fstream.cons] add:

    explicit basic_fstream(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in|ios_base::out);

> Effects: the same as `basic_fstream(p.c_str(), mode)`.

Change 27.9.1.17 Member functions [fstream.members] as indicated:

    void open(const char* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);
    void open(const std::filesystem::path::value_type* s,
        ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]

To 27.9.1.17 Member functions [fstream.members] add:

    void open(const filesystem::path& p,
        ios_base::openmode mode = ios_base::in|ios_base::out);

> Effects: calls `open(p.c_str(), mode)`.