std::unordered_set<std::filesystem::p ath>:v.12 以下的 clang 和 g++ 上的编译错误。错误或用户错误?



我在项目中添加了以下函数模板,一位用户抱怨它无法在他们的系统上编译:

template<typename T>
std::size_t removeDuplicates(std::vector<T>& vec)
{
std::unordered_set<T> seen;
auto newEnd = std::remove_if(
vec.begin(), vec.end(), [&seen](const T& value)
{
if (seen.find(value) != std::end(seen))
return true;
seen.insert(value);
return false;
}
);
vec.erase(newEnd, vec.end());
return vec.size();
}

g++ 9.4的错误消息大约为

error: use of deleted function
'std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() 
[with
_Value = std::filesystem::__cxx11::path; 
_Hash = std::hash<std::filesystem::__cxx11::path>; 
_Pred = std::equal_to<std::filesystem::__cxx11::path>; 
_Alloc = std::allocator<std::filesystem::__cxx11::path>]'
12 |  std::unordered_set<T> seen;

因此,在用T = std::filesystem::path实例化上述函数模板时出现了错误。我进行了一些调查,发现用其他类型实例化它时没有问题,例如基本类型或std::string,但仅用std::filesystem::path

使用编译器资源管理器,我查看了不同的编译器版本如何处理代码,发现只有g++ v.12可以使用std::filesystem::path编译实例化。任何低于12的g++版本都会出现上述错误而失败。即使在最新版本(14(上,clang也会产生类似的错误(call to implicitly deleted default constructor(。我没有测试其他编译器。

我使用的解决方法是用std::set代替std::unordered_set。然后在CCD_ 12和CCD_。

所以我想这个错误是std::filesystem::path的哈希函数丢失了吗?还是我有错?

std::filesystem::pathstd::hash专业化最近才作为LWG问题3657的解决方案添加到标准草案中。在已发布的C++17和C++20标准中还没有出现这种情况。

然而,一直有一个函数std::filesystem::hash_value,您可以从中轻松创建一个函数对象,作为散列函数传递给std::unordered_set:

struct PathHash {
auto operator()(const std::filesystem::path& p) const noexcept {
return std::filesystem::hash_value(p);
}
};
//...
std::unordered_set<std::filesystem::path, PathHash> seen;

如果您提供该模板时没有任何保证它适用于定义了std::hash专门化的类型以外的类型,那么我认为您没有问题。

但是,如果您要求类型是可散列的,那么最好让用户以std::unordered_set的方式重写散列函数。这同样适用于所使用的等式函子。

相关内容

  • 没有找到相关文章

最新更新