Reputation: 2321
The error is
in file included from /usr/include/c++/8/unordered_map:46,
from main.cpp:3:
/usr/include/c++/8/bits/hashtable.h: In instantiation of ‘class std::_Hashtable<MyClass*, std::pair<MyClass* const, double>, std::allocator<std::pair<MyClass* const, double> >, std::__detail::_Select1st, MyClassEquality, MyClassHash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’:
/usr/include/c++/8/bits/unordered_map.h:105:18: required from ‘class std::unordered_map<MyClass*, double, MyClassHash, MyClassEquality>’
main.cpp:35:68: required from here
/usr/include/c++/8/bits/hashtable.h:195:21: error: static assertion failed: hash function must be invocable with an argument of key type
static_assert(__is_invocable<const _H1&, const _Key&>{},
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/8/bits/hashtable.h:197:21: error: static assertion failed: key equality predicate must be invocable with two arguments of key type
static_assert(__is_invocable<const _Equal&, const _Key&, const _Key&>{},
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
the code is
#include <iostream>
#include <functional>
#include <unordered_map>
using namespace std;
class MyClass {
public:
long my_id;
MyClass() {
my_id = lrand48();
}
size_t id() const {
hash<long> long_hash;
return long_hash(my_id);
}
};
struct MyClassHash {
public:
size_t operator() (const MyClass * &c) const {
return c->id();
}
};
struct MyClassEquality {
public:
bool operator() (const MyClass * &a, const MyClass * &b) const {
return a->id() == b->id();
}
};
class TestClass {
public:
unordered_map<MyClass *, double, MyClassHash, MyClassEquality> my_map;;
/* makes no difference
* TestClass() {
* my_map = unordered_map<MyClass *, double, MyClassHash, MyClassEquality>(42, MyClassHash(), MyClassEquality());
* }
*/
void test() {
for (auto p : my_map) {
cout << p.first << "," << p.second << endl;
}
}
};
int main(int argc, char * argv[]) {
auto * a = new TestClass();
a->test();
return 0;
}
The reason the map has pointers as keys is that the program needs to leverage polymorphism when it interacts with the contents of the map; is there a relatively simple oversight in the code or is there a more appropriate design pattern?
I've tried variations such as changing the struct
s to class
es, not declaring the hash / equality operators public
, etcetera; similarly the commented constructor.
Upvotes: 0
Views: 2387
Reputation: 2321
In view of the fact that it looked as though there were limited specifically helpful results for the general design pattern of using polymorphic pointers as map keys, I'll just post the modified code as rafix07 rightly and very quickly suggested
struct MyClassHash {
public:
size_t operator() (const MyClass * c) const {
return c->id();
}
};
struct MyClassEquality {
public:
bool operator() (const MyClass * a, const MyClass * b) const {
return a->id() == b->id();
}
};
Upvotes: 1