I'm writing a class that has an unordered_set of its own type as a member.
Therefore I need to write a specialization for hash<Foo>
. This specialization needs to be defined after Foo is declared. But it seems to me as if I already need the specialization for hash<Foo>
before defining the member unordered_set<Foo>
. At least it doesn't compile and fails there. I tried a forward declaration of the hash template but couldn't get it working thereby either.
The relevant code snippet is:
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);
}
};
}
Thanks in advance
Foo
cannot have a member variable of type std::unordered_set<Foo>
.
You cannot instantiate a Standard Library container with an incomplete type. Basically, with several exceptions not relevant here, a class type is not complete until the }
that terminates its definition.
You'll either need to store some other type in the container (perhaps std::unique_ptr<Foo>
), or use a containers library that provides containers instantiable with an incomplete type (e.g., Boost has such a containers library).
You can move the declaration around a bit to make it compile:
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);
}
}
As James says, though, the declaration of dummy
is is undefined behaviour.
You will also need an equality comparison; easiest to add an operator==
to Foo
.
I would also recommend making the constructor of Foo
take the argument by const-reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With