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

### 3070. `path::lexically_relative` causes surprising results if a filename can also be a root-name

Section: 29.12.6.5.11 [fs.path.gen] Status: C++20 Submitter: Billy O'Neal III Opened: 2018-02-23 Last modified: 2021-02-25

Priority: 2

View all other issues in [fs.path.gen].

View all issues with C++20 status.

Discussion:

`path::lexically_relative` constructs the resulting path with `operator/=`. If any of the filename elements from `*this` are themselves acceptable root-names, `operator/=` will destroy any previous value, and take that `root_name()`. For example:

>     path("/a:/b:").lexically_relative("/a:/c:")

On a POSIX implementation, this would return `path("../b:")`, but on a Windows implementation, the `"b:"` element is interpreted as a root-name, and clobbers the entire result `path`, giving `path("b:")`. We should detect this problematic condition and fail (by returning `path()`).

[2019-01-20 Reflector prioritization]

Set Priority to 2

[2019 Cologne Wednesday night]

Status to Ready

Proposed resolution:

This wording is relative to N4727.

1. Change 29.12.6.5.11 [fs.path.gen] as indicated:

   >     path lexically_relative(const path& base) const;

   > > -3- […]

   > > -4- Effects: If `root_name() != base.root_name()` is `true` or `is_absolute() != base.is_absolute()` is `true` or `!has_root_directory() && base.has_root_directory()` is `true` or if any filename in `relative_path()` or `base.relative_path()` can be interpreted as a root-name, returns `path()`. [Note: On a POSIX implementation, no filename in a relative-path is acceptable as a root-name — end note] Determines the first mismatched element of `*this` and `base` as if by:

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

   > > Then,

   > > 1. (4.1) — if `a == end()` and `b == base.end()`, returns `path(".")`; otherwise

   > > 2. (4.2) — let `n` be the number of filename elements in `[b, base.end())` that are not dot or dot-dot minus the number that are dot-dot. If `n < 0`, returns `path()`; otherwise

   > > 3. (4.3) — returns an object of class `path` that is default-constructed, followed by

   > >    1. (4.3.1) — application of `operator/=(path(".."))` `n` times, and then

   > >    2. (4.3.2) — application of `operator/=` for each element in `[a, end())`.