27 Input/output library [input.output]

27.10 File systems [filesystems]

27.10.8 Class path [class.path]

27.10.8.4 path members [path.member]

27.10.8.4.1 path constructors [path.construct]

path() noexcept;

Effects: Constructs an object of class path.

Postconditions: empty() == true.

path(const path& p); path(path&& p) noexcept;

Effects: Constructs an object of class path with pathstring having the original value of p.pathstring. In the second form, p is left in a valid but unspecified state.

path(string_type&& source);

Effects: Constructs an object of class path with pathstring having the original value of source. source is left in a valid but unspecified state.

template <class Source> path(const Source& source); template <class InputIterator> path(InputIterator first, InputIterator last);

Effects: Constructs an object of class path, storing the effective range of source ([path.req]) or the range [first, last) in pathstring, converting format and encoding if required ([path.cvt]).

template <class Source> path(const Source& source, const locale& loc); template <class InputIterator> path(InputIterator first, InputIterator last, const locale& loc);

Requires: The value type of Source and InputIterator is char.

Effects: Constructs an object of class path, storing the effective range of source or the range [first, last) in pathstring, after converting format if required and after converting the encoding as follows:

  • If value_type is wchar_t, converts to the native wide encoding ([fs.def.native.encode]) using the codecvt<wchar_t, char, mbstate_t> facet of loc.

  • Otherwise a conversion is performed using the codecvt<wchar_t, char, mbstate_t> facet of loc, and then a second conversion to the current narrow encoding.

Example: A string is to be read from a database that is encoded in ISO/IEC 8859-1, and used to create a directory:

namespace fs = std::filesystem;
std::string latin1_string = read_latin1_data();
codecvt_8859_1<wchar_t> latin1_facet;
std::locale latin1_locale(std::locale(), latin1_facet);
fs::create_directory(fs::path(latin1_string, latin1_locale));

For POSIX-based operating systems, the path is constructed by first using latin1_facet to convert ISO/IEC 8859-1 encoded latin1_string to a wide character string in the native wide encoding ([fs.def.native.encode]). The resulting wide string is then converted to a narrow character pathstring string in the current native narrow encoding. If the native wide encoding is UTF-16 or UTF-32, and the current native narrow encoding is UTF-8, all of the characters in the ISO/IEC 8859-1 character set will be converted to their Unicode representation, but for other native narrow encodings some characters may have no representation.

For Windows-based operating systems, the path is constructed by using latin1_facet to convert ISO/IEC 8859-1 encoded latin1_string to a UTF-16 encoded wide character pathstring string. All of the characters in the ISO/IEC 8859-1 character set will be converted to their Unicode representation.  — end example ]

27.10.8.4.2 path assignments [path.assign]

path& operator=(const path& p);

Effects: If *this and p are the same object, has no effect. Otherwise, modifies pathstring to have the original value of p.pathstring.

Returns: *this.

path& operator=(path&& p) noexcept;

Effects: If *this and p are the same object, has no effect. Otherwise, modifies pathstring to have the original value of p.pathstring. p is left in a valid but unspecified state. [ Note: A valid implementation is swap(p).  — end note ]

Returns: *this.

path& operator=(string_type&& source); path& assign(string_type&& source);

Effects: Modifies pathstring to have the original value of source. source is left in a valid but unspecified state.

Returns: *this.

template <class Source> path& operator=(const Source& source); template <class Source> path& assign(const Source& source); template <class InputIterator> path& assign(InputIterator first, InputIterator last);

Effects: Stores the effective range of source ([path.req]) or the range [first, last) in pathstring, converting format and encoding if required ([path.cvt]).

Returns: *this.

27.10.8.4.3 path appends [path.append]

The append operations use operator/= to denote their semantic effect of appending preferred-separator when needed.

path& operator/=(const path& p);

Requires: !p.has_root_name().

Effects: Appends path::preferred_separator to pathstring unless:

Then appends p.native() to pathstring.

Returns: *this.

template <class Source> path& operator/=(const Source& source); template <class Source> path& append(const Source& source);

Effects: Equivalent to: return operator/=(path(source));

template <class InputIterator> path& append(InputIterator first, InputIterator last);

Effects: Equivalent to: return operator/=(path(first, last));

27.10.8.4.4 path concatenation [path.concat]

path& operator+=(const path& x); path& operator+=(const string_type& x); path& operator+=(basic_string_view<value_type> x); path& operator+=(const value_type* x); path& operator+=(value_type x); template <class Source> path& operator+=(const Source& x); template <class EcharT> path& operator+=(EcharT x); template <class Source> path& concat(const Source& x); template <class InputIterator> path& concat(InputIterator first, InputIterator last);

Postconditions: native() == prior_native + effective-argument, where prior_native is native() prior to the call to operator+=, and effective-argument is:

  • if x is present and is const path&, x.native(); otherwise,

  • if source is present, the effective range of source ([path.req]); otherwise,

  • if first and last are present, the range [first, last); otherwise,

  • x.

If the value type of effective-argument would not be path::value_type, the actual argument or argument range is first converted ([path.type.cvt]) so that effective-argument has value type path::value_type.

Returns: *this.

27.10.8.4.5 path modifiers [path.modifiers]

void clear() noexcept;

Postconditions: empty() == true.

path& make_preferred();

Effects: Each directory-separator is converted to preferred-separator.

Returns: *this.

Example:

path p("foo/bar");
std::cout << p << '\n';
p.make_preferred();
std::cout << p << '\n';

On an operating system where preferred-separator is the same as directory-separator, the output is:

"foo/bar"
"foo/bar"

On an operating system where preferred-separator is a backslash, the output is:

"foo/bar"
"foo\bar"

 — end example ]

path& remove_filename();

Postconditions: !has_filename().

Returns: *this.

Example:

std::cout << path("/foo").remove_filename();  // outputs "/"
std::cout << path("/").remove_filename();     // outputs ""

 — end example ]

path& replace_filename(const path& replacement);

Effects: Equivalent to:

remove_filename();
operator/=(replacement);

Returns: *this.

Example:

std::cout << path("/").replace_filename("bar");     // outputs "bar"

 — end example ]

path& replace_extension(const path& replacement = path());

Effects: pathstring (the stored path) is modified as follows:

  • Any existing extension()([path.decompose]) is removed from the stored path, then

  • If replacement is not empty and does not begin with a dot character, a dot character is appended to the stored path, then

  • replacement is concatenated to the stored path.

Returns: *this.

void swap(path& rhs) noexcept;

Effects: Swaps the contents of the two paths pathstring and rhs.pathstring.

Complexity: Constant time.

27.10.8.4.6 path native format observers [path.native.obs]

The string returned by all native format observers is in the native pathname format ([fs.def.native]).

const string_type& native() const noexcept;

Returns: pathstring.

const value_type* c_str() const noexcept;

Returns: pathstring.c_str().

operator string_type() const;

Returns: pathstring.

Note: Conversion to string_type is provided so that an object of class path can be given as an argument to existing standard library file stream constructors and open functions.  — end note ]

template <class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;

Returns: pathstring.

Remarks: All memory allocation, including for the return value, shall be performed by a. Conversion, if any, is specified by [path.cvt].

std::string string() const; std::wstring wstring() const; std::string u8string() const; std::u16string u16string() const; std::u32string u32string() const;

Returns: pathstring.

Remarks: Conversion, if any, is performed as specified by [path.cvt]. The encoding of the string returned by u8string() is always UTF-8.

27.10.8.4.7 path generic format observers [path.generic.obs]

Generic format observer functions return strings formatted according to the generic pathname format ([path.generic]). The forward slash ('/') character is used as the directory-separator character.

Example: On an operating system that uses backslash as its preferred-separator, path("foo\\bar").generic_string() returns "foo/bar".  — end example ]

template <class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;

Returns: pathstring, reformatted according to the generic pathname format ([path.generic]).

Remarks: All memory allocation, including for the return value, shall be performed by a. Conversion, if any, is specified by [path.cvt].

std::string generic_string() const; std::wstring generic_wstring() const; std::string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const;

Returns: pathstring, reformatted according to the generic pathname format ([path.generic]).

Remarks: Conversion, if any, is specified by [path.cvt]. The encoding of the string returned by generic_u8string() is always UTF-8.

27.10.8.4.8 path compare [path.compare]

int compare(const path& p) const noexcept;

Returns:

  • A value less than 0, if native() for the elements of *this are lexicographically less than native() for the elements of p; otherwise,

  • a value greater than 0, if native() for the elements of *this are lexicographically greater than native() for the elements of p; otherwise,

  • 0.

Remarks: The elements are determined as if by iteration over the half-open range [begin(), end()) for *this and p.

int compare(const string_type& s) const int compare(basic_string_view<value_type> s) const;

Returns: compare(path(s)).

int compare(const value_type* s) const

Returns: compare(path(s)).

27.10.8.4.9 path decomposition [path.decompose]

path root_name() const;

Returns: root-name, if pathstring includes root-name, otherwise path().

path root_directory() const;

Returns: root-directory, if pathstring includes root-directory, otherwise path().

path root_path() const;

Returns: root_name() / root_directory().

path relative_path() const;

Returns: A path composed from pathstring, if !empty(), beginning with the first filename after root-path. Otherwise, path().

path parent_path() const;

Returns: (empty() || begin() == --end()) ? path() : pp, where pp is constructed as if by starting with an empty path and successively applying operator/= for each element in the range [begin(), --end()).

path filename() const;

Returns: empty() ? path() : *--end().

Example:

std::cout << path("/foo/bar.txt").filename(); // outputs "bar.txt"
std::cout << path("/").filename();            // outputs "/"
std::cout << path(".").filename();            // outputs "."
std::cout << path("..").filename();           // outputs ".."

 — end example ]

path stem() const;

Returns: if filename() contains a period but does not consist solely of one or two periods, returns the substring of filename() starting at its beginning and ending with the character before the last period. Otherwise, returns filename().

Example:

std::cout << path("/foo/bar.txt").stem(); // outputs "bar"
path p = "foo.bar.baz.tar";
for (; !p.extension().empty(); p = p.stem())
  std::cout << p.extension() << '\n';
  // outputs: .tar
  //          .baz
  //          .bar

 — end example ]

path extension() const;

Returns: if filename() contains a period but does not consist solely of one or two periods, returns the substring of filename() starting at the rightmost period and for the remainder of the path. Otherwise, returns an empty path object.

Remarks: Implementations are permitted to define additional behavior for file systems which append additional elements to extensions, such as alternate data streams or partitioned dataset names.

Example:

std::cout << path("/foo/bar.txt").extension(); // outputs ".txt"

 — end example ]

Note: The period is included in the return value so that it is possible to distinguish between no extension and an empty extension. Also note that for a path p, p.stem()+p.extension() == p.filename().  — end note ]

27.10.8.4.10 path query [path.query]

bool empty() const noexcept;

Returns: pathstring.empty().

bool has_root_path() const;

Returns: !root_path().empty().

bool has_root_name() const;

Returns: !root_name().empty().

bool has_root_directory() const;

Returns: !root_directory().empty().

bool has_relative_path() const;

Returns: !relative_path().empty().

bool has_parent_path() const;

Returns: !parent_path().empty().

bool has_filename() const;

Returns: !filename().empty().

bool has_stem() const;

Returns: !stem().empty().

bool has_extension() const;

Returns: !extension().empty().

bool is_absolute() const;

Returns: true if pathstring contains an absolute path ([fs.def.absolute.path]), else false.

Example: path("/").is_absolute() is true for POSIX-based operating systems, and false for Windows-based operating systems.  — end example ]

bool is_relative() const;

Returns: !is_absolute().

27.10.8.4.11 path generation [path.gen]

path lexically_normal() const;

Returns: *this in normal form ([fs.def.normal.form]).

Example:

assert(path("foo/./bar/..").lexically_normal() == "foo");
assert(path("foo/.///bar/../").lexically_normal() == "foo/.");

The above assertions will succeed. The second example ends with a current directory (dot) element appended to support operating systems that use different syntax for directory names and regular file names.

On Windows, the returned path's directory-separator characters will be backslashes rather than slashes, but that does not affect path equality.  — end example ]

path lexically_relative(const path& base) const;

Returns: *this made relative to base. Does not resolve ([fs.def.pathres]) symlinks. Does not first normalize ([fs.def.normal.form]) *this or base.

Effects: Determines the first mismatched element of *this and base as if by:

auto [a, b] = mismatch(begin(), end(), base.begin(), base.end());

Then,

  • if a == begin() and b == base.begin(), returns path(); otherwise

  • if a == end() and b == base.end(), returns path("."); otherwise

  • returns an object of class path that is default-constructed, followed by

    • application of operator/=(path("..")) for each element in [b, base.end()), and then

    • application of operator/= for each element in [a, end()).

Example:

assert(path("/a/d").lexically_relative("/a/b/c") == "../../d");
assert(path("/a/b/c").lexically_relative("/a/d") == "../b/c");
assert(path("a/b/c").lexically_relative("a") == "b/c");
assert(path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
assert(path("a/b/c").lexically_relative("a/b/c") == ".");
assert(path("a/b").lexically_relative("c/d") == "");

The above assertions will succeed. On Windows, the returned path's directory-separator characters will be backslashes rather than forward slashes, but that does not affect path equality.  — end example ]

Note: If symlink following semantics are desired, use the operational function relative().  — end note ]

Note: If normalization ([fs.def.normal.form]) is needed to ensure consistent matching of elements, apply lexically_normal() to *this, base, or both.  — end note ]

path lexically_proximate(const path& base) const;

Returns: If the value of lexically_relative(base) is not an empty path, return it. Otherwise return *this.

Note: If symlink following semantics are desired, use the operational function proximate().  — end note ]

Note: If normalization ([fs.def.normal.form]) is needed to ensure consistent matching of elements, apply lexically_normal() to *this, base, or both.  — end note ]