[英]Clang error: Dependent nested name specifier for friend class declaration not supported
I am trying to write a hash function for my custom class, and make my code compatible with both gcc 11.1 and clang 12.0.0, but clang gives the warning/error: I am trying to write a hash function for my custom class, and make my code compatible with both gcc 11.1 and clang 12.0.0, but clang gives the warning/error:
<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();
for the code below (also at https://godbolt.org/z/8Wsnqr5cb ).对于下面的代码(也在https://godbolt.org/z/8Wsnqr5cb )。 How can I fix it to be compatible with both?如何修复它以与两者兼容?
#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;
}
You can change the friend
declaration only valid for the Base
of current template parameter T
, ie current instantiation.您可以更改仅对当前模板参数T
的Base
有效的friend
声明,即当前实例化。
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;
};
Note that the effect is different with yours.请注意,效果与您的不同。 With the above friend
declaration, for example, given Base<int>
, only std::hash<Base<int>>::operator()
is the friend
.例如,对于上面的friend
声明,给定Base<int>
,只有std::hash<Base<int>>::operator()
是friend
。 With template friend
declaration in your code, given Base<int>
, all the possible instantiations like std::hash<Base<int>>::operator()
, std::hash<Base<char>>::operator()
, ... are friend
s.在代码中使用模板friend
元声明,给定Base<int>
,所有可能的实例化,如std::hash<Base<int>>::operator()
, std::hash<Base<char>>::operator()
, ... 是friend
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.