不完整成员类型的哈希函数

时间:2015-10-12 17:39:08

标签: c++ hash dependencies

我有一个类secondaryTest,它有一个无序容器,其中包含类A的实例,B依赖于B,因为它有一个指向其A的指针 - 作为一个领域的实例。我可以在A的实现之前转发声明B,但这是不够的,因为A中的无序容器需要A的定义,之前无法定义悬停std::hash<B>,因为它取决于它。

A

有没有办法解决这个问题?

template <typename X> class B; namespace std { template <typename V> struct hash<B<V>> // <- requires full definition { size_t operator()(const B<V>& b) const { return (b.mem /*do hashing stuff with it*/ ); } }; } template <typename T> class A { typedef A<T> THIS; void func() { } std::unordered_set<B<THIS>> set;// <- requires std::hash<B> }; template <typename A> class B { B(A* a) { A_ptr = a; } void otherfunc() { A_ptr->func(); } public: int mem; A* A_ptr; }; 要求B完成。 A不需要A完整,但需要B,这需要std::hash<B>完成。

编辑:

我试图将Richard Hodges的提案纳入我的实际计划中,但我无法让它发挥作用。这是代码在我的文件中编译的顺序:

B

但我得到了

namespace E
{

    template<typename G>
    class R;

    template <typename V, typename P>
    class G;

}

namespace std
{
    template <typename G> std::size_t hash_code(const E::R<G>&);


    template <typename G>
    struct hash<E::R<G>>
    {
        size_t operator()(const E::R<G>& r) const
        {
            return hash_code(r);
        }
    };
}

namespace E
{

    template <typename V, typename P>
    class G
    {
        // code
    }

    template <typename G>
    class R
    {
        // code
    }

}


namespace std
{
    template<typename G>
    size_t hash_code(const E::R<G>& r)
    {
        size_t hash = 0x9e3779b9;

        typename E::R<G>::Rside v = r[0];

        for(auto t = v.begin(); t != v.end(); ++t)
        {
            hash += (((*t + (hash << 6)) ^ (hash >> 16)) - hash);
        }
        v = r[1];

        for(auto t = v.begin(); t != v.end(); ++t)
        {
            hash += (((*t + (hash << 6)) ^ (hash << 16)) - hash);
        }
        return hash;

    }
}

implicit instantiation of undefined template
      'std::__1::hash<std::__1::vector<std::__1::vector<int, std::__1::allocator<int>
      >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > > >'
    : public integral_constant<bool, __is_empty(_Tp)> {};

1 个答案:

答案 0 :(得分:1)

代码中有太多错误提供了一个工作示例,但这可以帮助您入门。

有很多方法可以做到这一点,但在我看来,最干净的是通过ADL找到的名为hash_code的免费函数。

类似的东西:

// forward declarations
template <typename X> class B;
template <typename X> std::size_t hash_code(const B<X>&);

// specialisation of std::hash, uses only references so forward declarations are fine.    
template <typename V>
struct std::hash<B<V>>  // <- no longer requires full definition
{
    size_t operator()(const B<V>& b) const {
        return hash_code(b);
    }
};

...
... later on ...
...

// provide the definition of hash_code once B has been defined.
template<typename A>
std::size_t hash_code(const B<A>& b) {
    return b.mem;
}