c++ - `std::filesystem::path` 没有标准哈希值吗?

标签 c++ hash c++17

我有一个简单的程序,旨在存储一组 C++17 std::filesystem::path对象。因为有一个 std::filesystem::hash_value 那是标准的一部分,为什么我不必提供自己的 std::hash 就无法编译这段代码? ?

当我使用 gcc 8.1.1 作为 g++ -std=c++17 -NO_HASH=1 hashtest.cpp -o hashtest -lstdc++fs 编译和链接时包括我的哈希函数,一切都运行完美。但是,如果我将其更改为 -NO_HASH=0 ,我收到一长串错误消息,其中最关键的一条是:

usr/include/c++/8/bits/hashtable.h:195:21: error: static assertion failed: hash function must be invocable with an argument of key type
       static_assert(__is_invocable<const _H1&, const _Key&>{},

这是一个 live Coliru version如果你想玩。

真的没有定义std::hash<std::filesystem::path>吗? ?我错过了什么?

对于那些对我为什么想要这样的东西感兴趣的人来说,是这样的:https://codereview.stackexchange.com/questions/124307/from-new-q-to-compiler-in-30-seconds

哈希测试.cpp

#include <optional>
#include <unordered_set>
#include <filesystem>
#include <string>
#include <iostream>

namespace fs = std::filesystem;

#if NO_HASH
namespace std {
    template <>
    struct hash<fs::path> {
        std::size_t operator()(const fs::path &path) const {
            return hash_value(path);            }
    };
}
#endif
int main()
{
    using namespace std::literals;
    std::unordered_set< std::optional<fs::path> >  paths = {
            "/usr/bin"s, std::nullopt, "/usr//bin"s, "/var/log"s
    };

    for(const auto& p : paths)
        std::cout << p.value_or("(no path)") << ' ';
}

最佳答案

Since there is a std::filesystem::hash_value that's part of the standard, why doesn't this code compile without me having to supply my own std::hash?

对了,有一个fs::hash_value()但没有std::hash<fs::path>的特化,这就是您所需要的。这就是它无法编译的原因。至于为什么图书馆提供前者的功能而不提供后者,我将引用自Billy O'Neal。 (MSVC 标准库的实现者):

Looks like a defect.

However, putting paths as keys in a hash table is almost certainly incorrect; you need to test for path equivalence in most such scenarios. That is, "/foo/bar/../baz" and "/foo/baz" are the same target but are not the same path. Similarly, "./bar" and "./bar" may be different paths, depending on the value of current_path in the first context vs. in the second.

如果您想要的是规范唯一的路径,那么只需 std::unordered_set<fs::path>无论如何都不会做你想做的事。所以也许编译失败不是一件坏事?我对文件系统的了解还不够多,无法用一种或另一种方式来表达。


请注意,您自己提供了 std::hash 的特化对于 fs::path不允许 - 您只能将特化添加到 std对于您控制的类型。将称为“程序定义类型”的类型。 fs::path不是你控制的类型,所以你不能专门化 std::hash

关于c++ - `std::filesystem::path` 没有标准哈希值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51065244/

相关文章:

c++ - 在 Allegro 5 的运行时更改基元的颜色

arrays - 通过 Perl 中的哈希引用数组获取切片

c# - 哈希值是否全局唯一

c++ - 如何检查类型是否可显式/隐式构造?

c++ - 如何使用折叠表达式实例化可变参数模板函数中的每种类型?

c++ - C26486 与 string_view

c++ - 如果 operator<< 重载,VSCode 表示 std::chrono 不明确

c++ - 如何在 Qt 中使用 QDataStream 将自定义结构保存/加载到二进制文件中?

c++ - Qt 信号可以是公共(public)的、 protected 还是私有(private)的?

hash - 如何在 presto 中将字符串散列到 bigint?