Прямое объявление std :: ha sh<MyClass> - PullRequest
0 голосов
/ 08 мая 2020

У меня есть несколько классов, которые перегружают std :: ha sh operator (). Скажем:

Ah

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
  {
..

}

И аналогичные классы, скажем, class B и class C

Теперь class B использует ha sh как:

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

Проблема: error: use of deleted function std::hash<A>::hash()

Я пробовал: Ah

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

Bh

class B 
{
   friend struct std::hash<A>;
}

1 Ответ

3 голосов
/ 08 мая 2020

Вы должны определить специализацию std::hash<A> в A.h, чтобы B и C могли видеть, что специализация существует и что у нее есть член operator().

Если B и C не могут «увидеть» специализацию std::hash<A>, они создадут экземпляр основного шаблона std::hash, который отключен, поскольку стандартная библиотека не знает, как sh получить ваш определяемый пользователем тип A.

Если вы объявляете специализацию std::hash<A> в A.h, но не определяете ее, то B и C будут рассматривать его как неполный класс, что означает, что operator() не может быть вызван.

Таким образом, вы должны определить std::hash<A> в A.h. Вы можете сделать это следующим образом:

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

Вы также можете переместить определение operator() в файл A.cpp:

// 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 { ... }
}
...