c ++ 11 статическое утверждение ключей полиморфной карты не выполнено: хеш-функция должна вызываться с аргументом типа ключа - PullRequest
0 голосов
/ 13 марта 2019

Ошибка:

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&>{},
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

код:

#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;
}

Причина, по которой на карте есть указатели в качестве ключей, заключается в том, что программе необходимо использовать полиморфизм при взаимодействии с содержимымкарта;Есть ли относительно простой надзор в коде или есть более подходящий шаблон проектирования?

Я пробовал варианты, такие как изменение struct s на class es, а не объявление операторов хеширования / равенстваpublic и т. Д .;аналогично прокомментированный конструктор.

1 Ответ

1 голос
/ 13 марта 2019

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

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();
    }
};
...