0

I have multiple classes which overloads std::hash operator(). Let's say:

A.h

class A
{
...
}

namespace std
{
  template<typename T>
  struct hash;
}

A.cpp

template<> struct std::hash<A>
{
  public:
  virtual std::size_t operator()(const A& joint) const noexcept
  {
..

}

And similar classes let's say class B and class C

Now class B uses A's hash like:

boost::hash_combine(h, std::hash<A>{}(b.getA())

Problem: error: use of deleted function std::hash<A>::hash()

I tried: A.h

namespace std
{
  template<typename T>
  struct hash;
}

B.h

class B 
{
   friend struct std::hash<A>;
}
code muncher
  • 1,592
  • 2
  • 27
  • 46

1 Answers1

3

You have to define the std::hash<A> specialization in A.h, so that B and C will be able to see that the specialization exists and that it has an operator() member.

If B and C can't "see" the std::hash<A> specialization, then they will instantiate the primary std::hash template, which is disabled because the standard library doesn't know how to hash your user-defined type A.

If you declare the std::hash<A> specialization in A.h, but you do not define it, then B and C will see it as an incomplete class, which means the operator() cannot be called.

So you must define std::hash<A> in A.h. You can do so like this:

// A.h
namespace std {
template <> struct hash<A> {
    std::size_t operator()(const A&) const noexcept { ... }
};
}

You could also move the definition of operator() to the A.cpp file:

// A.h
namespace std {
template <> struct hash<A> {
    std::size_t operator()(const A&) const noexcept;
};
}

// A.cpp
namespace std {
std::size_t hash<A>::operator()(const A&) const noexcept { ... }
}
Brian Bi
  • 111,498
  • 10
  • 176
  • 312