我有一个简单的程序,旨在存储一组 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 ownstd::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 ofcurrent_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/