Подтвердить что ты не робот

Хэш-функция для пользовательского класса. Как подружиться?:)

У меня есть класс C, у которого есть частный элемент данных string* ps.
Теперь я хотел бы иметь unordered_map<C, int>, для которого мне нужна пользовательская хеш-функция.

В соответствии с ссылкой на С++, я могу сделать это как

namespace std {
  template<>
  class hash<C> {
  public:
    size_t operator()(const C &c) const
    {
      return std::hash<std::string>()(*c.ps);
    }
  };
}

Проблема в том, что я не могу заставить друзей operator() и C так, чтобы я мог получить доступ к ps.

Я пробовал это:

class C;
template<>
class std::hash<C>;
class C{
  //...
  friend std::hash<C>::operator ()(const C&) const; // error: Incomplete type 
};
// define hash<C> here.

но он говорит, что неполный тип... в вложенном спецификаторе имен...

Я тоже не могу обойти определения, потому что, если класс C определяется позже, hash<C> не имеет возможности узнать о ps.

Что я здесь делаю неправильно? Как можно зафиксировать эту ситуацию, не делая ps public?

4b9b3361

Ответ 1

Попробуйте следующее:

class C;
namespace std {
  template<>
  class hash<C> {
  public:
    size_t operator()(const C &c) const; // don't define yet
  };
}
class C{
  //...
  friend std::hash<C>::operator ()(const C&) const;
};
namespace std {
  template<>
  size_t hash<C>::operator()(const C &c) const {
    return std::hash<std::string>()(*c.ps);
  }
}

Или это:

class C;
template<>
class std::hash<C>;
class C{
  friend class std::hash<C>; // friend the class, not the member function
};

(я не скомпилирован, поэтому может возникнуть синтаксическая ошибка)

Ответ 2

Я бы предложил добавить метод, например, следующий

class C
{
....
public:  const string* get_ps() const { return ps; }
....
};

и использовать его в своей хэш-специализации.