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

< cpp‎ | filesystem‎ | path

path lexically_normal() const; | (1) | (C++17 起)
path lexically_relative(const path& base) const; | (2) | (C++17 起)
path lexically_proximate(const path& base) const; | (3) | (C++17 起)

1) 返回以其通用格式转换成正规形式的 `*this`
2) 返回设为相对 `base` 的 `*this` 。

  - 首先，若 root_name() != base.root_name() 为 true 或 is_absolute() != base.is_absolute() 为 true 或 (!has_root_directory() && base.has_root_directory()) 为 true 或 relative_path() 或 base.relative_path() 中的任何文件名能转译为 根名, ，则返回默认构造的 `path` 。
  - 否则，首先确定 `*this` 和 `base` 的首个不匹配元素，如同以 auto [a, b] = mismatch(begin(), end(), base.begin(), base.end()) ，然后
    - 若 a == end() 且 b == base.end() ，则返回 path(".") ；
    - 否则，定义 N 为 [b, base.end()) 中既非 dot 亦非 dot-dot 的非空文件名元素数减去 dot-dot 文件名元素数。若 N < 0 则返回默认构造的 `path` 。
    - 否则，若 N = 0 且 a == end() || a->empty() ，则返回 path(".") 。
    - 否则返回由以下方式合成的对象
      - 默认构造 path() 后
      - 应用 N 次 operator/=(path("..")) ，之后
      - 对半开范围 `[a, end())` 中的每个元素应用一次 operator/=

3) 若 lexically_relative(base) 的值不是空路径，则返回它。否则返回 `*this` 。

### 参数

（无）

### 返回值

1) 路径的正规形式
2) 路径的相对形式
3) 路径的近似形式

### 异常

可能抛出实现定义的异常。

### 注解

这些转换是纯文字的。它们不检查路径是否存在，不跟随符号链接，且完全不访问文件系统。关于 `lexically_relative` 与 `lexically_proximate` 跟随符号链接的对应版本，见 `relative` 与 `proximate` 。

Windows 上返回路径拥有反斜杠（偏好分隔符）。

POSIX 上相对路径中的文件名均不可接受为 根名 。

### 示例

    #include <iostream>
    #include <filesystem>
    #include <cassert>
    namespace fs = std::filesystem;

    int main()
    {
        assert(fs::path("foo/./bar/..").lexically_normal() == "foo/");
        assert(fs::path("foo/.///bar/../").lexically_normal() == "foo/");

        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");
    }

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3070 | C++17 | 亦能为根名的文件名可能导致诧异的结果 | 当作错误情况
LWG 3096 | C++17 | 错误地处理了尾随 "/" 和 "/." | 已更正

### 参阅

relative proximate (C++17) | 组成一个相对路径 (函数)