std::filesystem::path::lexically_normal, std::filesystem::path::lexically_relative, std::filesystem::path::lexically_proximate

  1. Returns *this converted to normal form in its generic format.

# Declarations

path lexically_normal() const;

(since C++17)

path lexically_relative( const path& base ) const;

(since C++17)

path lexically_proximate( const path& base ) const;

(since C++17)

# Notes

These conversions are purely lexical. They do not check that the paths exist, do not follow symlinks, and do not access the filesystem at all. For symlink-following counterparts of lexically_relative and lexically_proximate, see relative and proximate.

On Windows, the returned path has backslashes (the preferred separators).

On POSIX, no filename in a relative path is acceptable as a root-name.

# Example

#include <cassert>
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
 
int main()
{
    assert(fs::path("a/./b/..").lexically_normal() == "a/");
    assert(fs::path("a/.///b/../").lexically_normal() == "a/");
    assert(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
    assert(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
    assert(fs::path("a/b/c").lexically_relative("a") == "b/c");
    assert(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
    assert(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
    assert(fs::path("a/b").lexically_relative("c/d") == "../../a/b");
    assert(fs::path("a/b").lexically_relative("/a/b") == "");
    assert(fs::path("a/b").lexically_proximate("/a/b") == "a/b");
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
LWG 3070C++17a filename that can also be a root-name may cause surprising resulttreated as error case
LWG 3096C++17trailing “/” and “/.” are handled incorrectlycorrected

# See also