首页 > 解决方案 > 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;
}

标签: c++templateshashfriend

解决方案


您可以更改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()friendfriendBase<int>std::hash<Base<int>>::operator()std::hash<Base<char>>::operator()friend


推荐阅读