std::filesystem 根路径如何将自己作为父路径?

How can a std::filesystem root path have itself as a parent?

这个程序:

#include <iostream>
#include <filesystem>

int main()
{
    std::filesystem::path p1("c:\");
    std::filesystem::path p2("c:/");
    if (p1.has_parent_path())
        std::cout << "Parent path of " << p1 << " is " << p1.parent_path() << std::endl;
    if (p2.has_parent_path())
        std::cout << "Parent path of " << p2 << " is " << p2.parent_path() << std::endl;
}

产生这个输出:

Parent path of "c:\" is "c:\"
Parent path of "c:/" is "c:/"

(EDIT:我对正斜杠的使用感到困惑所以我更新了这段代码以显示无论您使用哪种路径分隔符都会发生同样的事情在 Windows)

这对我来说毫无意义。目录如何成为其自身的父目录?如果永远不会 return false,那么即使 "has_parent" 函数有什么意义?

最重要的是:如果我正在编写递归搜索目录树以查找文件的代码,best/most 检测我已经访问根文件夹并应该停止的可靠方法是什么?

(我在 C++17 语言模式下使用 Visual Studio 2019,如果这很重要的话)

函数 bool has_parent_path() const; 检查从 path parent_path() const; 函数 return 编辑的路径是否为空。

此外,对于 path parent_path() const; 函数,standard 表示:

Returns the root directory of the generic-format path. If the path (in generic format) does not include root directory, returns path().

在 Linux 系统上,根路径为 /,在 Windows 系统上,根路径为 C:\parent_path() 函数将 return 为空字符串,因此 has_parent_path() 函数将 return false.

检查来自 here 的代码:

#include <iostream>
#include <experimental/filesystem>

namespace fs = std::experimental::filesystem;

int main() {
    for (fs::path p : {"/var/tmp/example.txt", "/", "C:\", "/var/tmp/."}) {
        std::cout << "The parent path of " << p
                  << " is " << p.parent_path() << '\n';
        std::cout << "Has parent path: " << p.has_parent_path() << '\n';
    }

    return 0;
}

注意Windows根目录的拼写。不是 c:/ 而是 C:\.

其实在godbolt例子中是没有输出的,因为测试是运行在GCC上posix环境下,其中"C:\"不是根目录,所以是被视为一个奇怪的 directory/file 名称并且它的父级是空的,但是使用 correct posix root path "/" 它会给出输出,正如 OP 所观察的那样。 所以不,根目录("/""C:\")的 parent_path() 不是空的,所以 has_parent_path() 在 [=40= 的所有实现上都是真的] 我知道的。

实际标准说:"Returns: *this if has_relative_path() is false, otherwise a path whose generic format pathname is the longest prefix of the generic format pathname of *this that produces one fewer element in its iteration."relative_path()root_path() 之后的所有内容,所以没有 relative_path()在这种情况下,所以 parent_path() returns *thishas_parent_path() returns 为真,如 OP 的示例所示。

我对为什么标准选择这种行为的问题的猜测是,这就是 cd .. 对每个 OS 所做的,如果你已经在根目录,你就保持不变根.

确实,检测结束的一种可能方法是:(!p.has_parent_path() || !p.has_relative_path()) 或者甚至 !p.has_relative_path(),这取决于如果它是无根的,您是否想以空路径结束。