std :: unordered_set <Foo>как член класса Foo - PullRequest
5 голосов
/ 09 января 2012

Я пишу класс, который имеет unordered_set своего собственного типа в качестве члена. Поэтому мне нужно написать специализацию для hash<Foo>. Эта специализация должна быть определена после объявления Foo. Но мне кажется, что мне уже нужна специализация для hash<Foo> до определения члена unordered_set<Foo>. По крайней мере, он не компилируется и не работает там. Я попробовал предварительное объявление шаблона хэша, но не смог заставить его работать.

Соответствующий фрагмент кода:

class Foo {
public:
    int i;
    std::unordered_set<Foo> dummy;
    Peer(std::unordered_set<Foo>);
};

namespace std {
    template<> struct hash<Foo>
    {
        size_t operator()(const Foo& f) const
        {
            return hash<int>()(f.i);
        }
    };
}

Заранее спасибо

Ответы [ 2 ]

8 голосов
/ 09 января 2012

Foo не может иметь переменную-член типа std::unordered_set<Foo>.

Вы не можете создать экземпляр контейнера стандартной библиотеки с неполным типом. По сути, за некоторыми исключениями, не относящимися к делу, тип класса не завершен до тех пор, пока } не завершит его определение.

Вам нужно будет либо сохранить в контейнере какой-то другой тип (возможно, std::unique_ptr<Foo>), либо использовать библиотеку контейнеров, которая предоставляет контейнеры, экземпляры которых могут быть неполными (например, в Boost есть такая библиотека контейнеров).

1 голос
/ 09 января 2012

Вы можете немного переместить объявление, чтобы оно скомпилировалось:

class Foo;

namespace std {
  template<> struct hash<Foo> {
    size_t operator()(const Foo& f) const;
  };
}

class Foo {
public:
  int i;
  std::unordered_set<Foo> dummy;
  Foo(std::unordered_set<Foo>);
};

namespace std {
  size_t hash<Foo>::operator()(const Foo& f) const {
    return hash<int>()(f.i);
  }
}

Однако, как говорит Джеймс, объявление dummy является неопределенным поведением.

Вы будететакже необходимо сравнение на равенство;проще всего добавить operator== к Foo.

Я также рекомендовал бы заставить конструктор Foo принимать аргумент по const-reference.

...