c++ - Clang 错误:不支持友元类声明的从属嵌套名称说明符
问题描述
我正在尝试为我的自定义类编写一个哈希函数,并使我的代码与 gcc 11.1 和 clang 12.0.0 兼容,但是 clang 给出了警告/错误:
<source>:30:25: warning: dependent nested name specifier 'std::hash<Base<U>>::' for friend class declaration is not supported; turning off access control for 'Base' [-Wunsupported-friend]
std::hash<Base<U>>::operator()(const Base<U>& b) const noexcept;
<source>:38:26: error: 'data_' is a private member of 'ns::Base<int>'
std::size_t seed = b.data_.size();
对于下面的代码(也在https://godbolt.org/z/8Wsnqr5cb)。如何修复它以与两者兼容?
#include <set>
#include <utility>
#include <iostream>
// Forward declaration
namespace ns
{
template<typename T>
class Base;
}
/// Hash specialization declaration
template<typename T>
struct std::hash<ns::Base<T>>
{
std::size_t operator()(const ns::Base<T>& b) const noexcept;
};
namespace ns
{
template<typename T>
class Base {
std::set<T> data_;
public:
Base(const std::set<T>& data): data_{data} {}
template<typename U>
friend std::size_t
std::hash<Base<U>>::operator()(const Base<U>& b) const noexcept;
};
}
// In implementation file:
template<typename T>
std::size_t std::hash<ns::Base<T>>::operator()(const ns::Base<T>& b) const noexcept
{
std::size_t seed = b.data_.size();
for(const auto & x : b.data_)
seed ^= x;
return seed;
}
using namespace ns;
int main()
{
std::set<int> data({1,2,3,4,5});
Base<int> a(data);
std::cout << std::hash<Base<int>>{}(a) << std::endl;
}
解决方案
您可以更改friend
仅对Base
当前模板参数有效的声明T
,即当前实例化。
template<typename T>
class Base {
std::set<int> data_;
public:
Base(const std::set<int>& data): data_{data} {}
friend std::size_t
std::hash<Base<T>>::operator()(const Base<T>& b) const noexcept;
//or just
//friend std::size_t
//std::hash<Base>::operator()(const Base& b) const noexcept;
};
请注意,效果与您的不同。使用上面的friend
声明,例如,给定的Base<int>
,只有. 在您的代码中使用模板声明,给定所有可能的实例化,如, , ... 都是s。std::hash<Base<int>>::operator()
friend
friend
Base<int>
std::hash<Base<int>>::operator()
std::hash<Base<char>>::operator()
friend
推荐阅读
- r - glmnet多项逻辑回归预测结果
- visual-studio - 对 SSRS 中的参数使用 DateAdd 时出错
- node.js - 如何修复此错误 -npm
- php - 在 Node.js 中解码用 PHP 编码的 base64 编码密码
- sql - 计算表中的列数和联合表中的列数
- r - 如何处理不需要的幅度?
- intellij-idea - 如何在 IntelliJ IDEA Java 项目中禁用大括号鼠标悬停的不同背景颜色?
- python - 使用 setup.cfg 在 PyScaffold 3.0.x 中包含数据文件
- html - 使用python 3提取html标签之间的文本
- visual-studio - 如何从 VisualStudio.com 将 PowerShell 脚本发布到内部文件共享