samedi 26 décembre 2020

How to use std::unordered_multiset with a custom class?

I am trying to declare an unordered_multiset which is going to contain objects of a custom class, but I can't find any examples out there for this. Following the documentation, it seems that I need to declare an operator== in the class, alongside the hashing function(operator() const) which, as per the documentation:

  1. Accepts a single parameter of type Key.
  2. Returns a value of type std::size_t that represents the hash value of the parameter.
  3. Does not throw exceptions when called.
  4. For two parameters k1 and k2 that are equal, std::hash<Key>()(k1) == std::hash<Key>()(k2).
  5. For two different parameters k1 and k2 that are not equal, the probability that
    std::hash<Key>()(k1) == std::hash<Key>()(k2) should be very small, approaching 1.0/std::numeric_limits<std::size_t>::max().

The code looks like this in a very simplistic way:

Class MyClass:

// comparator
bool MyClass::operator ==(const MyClass b) const {                                                                          
    return (string == b.getString()); // compares two strings
}

// hash operation
size_t MyClass::operator()() const {                                                                         
    return hash<string>()(string); // bases the hash on the string
}

main.cpp:

unordered_multiset<MyClass> s1;
// Also tried: unordered_multiset<MyClass, std::hash<MyClass>, std::equal_to<MyClass>> s1;

However, in the instatiation of the unordered_multiset the compiler (GCC) will complain about the hash functions (Tupla is the name of MyClass, and there are 1000+ lines, I included a few of them):

 error: use of deleted function ‘std::unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset() [with _Value = Tupla; _Hash = std::hash<Tupla>; _Pred = std::equal_to<Tupla>; _Alloc = std::allocator<Tupla>]’
   78 |     unordered_multiset<Tupla> s1;
      |                               ^~


/usr/include/c++/10/bits/unordered_set.h:949:7: note: ‘std::unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset() [with _Value = Tupla; _Hash = std::hash<Tupla>; _Pred = std::equal_to<Tupla>; _Alloc = std::allocator<Tupla>]’ is implicitly deleted because the default definition would be ill-formed:
  949 |       unordered_multiset() = default;


/usr/include/c++/10/bits/unordered_set.h:949:7: error: use of deleted function ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Hashtable() [with _Key = Tupla; _Value = Tupla; _Alloc = std::allocator<Tupla>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<Tupla>; _H1 = std::hash<Tupla>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, false>]’
In file included from /usr/include/c++/10/unordered_set:46,


/usr/include/c++/10/bits/hashtable.h:451:7: note: ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Hashtable() [with _Key = Tupla; _Value = Tupla; _Alloc = std::allocator<Tupla>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<Tupla>; _H1 = std::hash<Tupla>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, false>]’ is implicitly deleted because the default definition would be ill-formed:
  451 |       _Hashtable() = default;

An allocator is also mentioned as a pre-requisite for the unordered_multiset, but I neither understand it not I am sure whether that should be included (or how).

What did I miss?

Aucun commentaire:

Enregistrer un commentaire