Вы должны определить специализацию 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 { ... }
}