'Concatenation of multiple absolute std::filesystem::path instances

Why is the result of concatenating the following paths /c/d?

std::filesystem::path{"/a"} / std::filesystem::path{"b"} / std::filesystem::path{"/c/d"}

My mental model so far had the resulting path set to /a/b/c/d. To my surprise, it was simply /c/d. Curious to know where I went wrong here. (And what the right mental model is)



Solution 1:[1]

/a is an absolute path, and b is a relative path, so concatenating them will produce /a/b.

But /c/d is also an absolute path, so concatenating it with anything in front of it is basically a no-op, the absolute path will take priority, so the final result is just /c/d.

This is discussed in more detail on cppreference.com:

std::filesystem::operator/(std::filesystem::path)

Concatenates two path components using the preferred directory separator if appropriate (see operator/= for details).

Effectively returns path(lhs) /= rhs.

std::filesystem::path::operator/=

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

If p.is_absolute() || (p.has_root_name() && p.root_name() != root_name()), then replaces the current path with p as if by operator=(p) and finishes.

To get the result you want, drop the leading / from /c/d to make it a relative path:

std::filesystem::path{"/a"} / std::filesystem::path{"b"} / std::filesystem::path{"c/d"}

Solution 2:[2]

what the right mental model is

a / b means "if b is not absolute, then it's relative to a".

This lets you have a "default" base directory, where the rhs is assumed to be located, if the path is not absolute.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 HolyBlackCat