Batzorig Zorigoo
Batzorig Zorigoo

Reputation: 35

Hashing a template type

Here, I tried to make a map that its vertex can be user-defined class. But when I try to add template type element to the unordered_set it gives error. The code is:

#include <iostream>
#include <unordered_set>
#include <string>
#include <vector>
#include <functional>

template<class T> class Edge;

template<class T> class Vertex{          // Made it a class just for its constructor.
    public:
        template<class A> Vertex(A vert){
            A vertex = vert;
            std::unordered_set<Edge<A>> adjlist; 
        }
};

template<class T> class Edge{       // Made it a class just for its constructor.
    public:
        template<class A> Edge(Vertex<A> vert1, Vertex<A> vert2, int w){    
            Vertex<A> *origin = &vert1;
            Vertex<A> *target = &vert2;
        }
    };


template<class T> 
class WUG{
    private:
        std::unordered_set<Vertex<T>> vertices;
        std::unordered_set<Edge<T>> edges;
        int num_of_edges;
        int num_of_vertices;
    public:
        WUG() {
            num_of_edges = 0;
            num_of_vertices = 0;
        } 
        void addVertex(T newVert) {
            Vertex<T> temp = Vertex<T>(newVert);             
            vertices.emplace(temp);                 //Problem is here
        }
int main(int argc, char** argv) {
    WUG<char> g1 = WUG<char>();
    g1.addVertex('A');
    g1.addVertex('B');
    g1.addVertex('C');

    return 0;
}

Error: it opens hashtable_policy.h and gives error at

    template <typename _Key, typename _Hash>
         struct __is_noexcept_hash : std::integral_constant<bool,
         noexcept(declval<const _Hash&>()(declval<const _Key&>()))> //Here
    { };
    [Error] no match for call to '(const std::hash<Vertex<char> >) (const Vertex<char>&)'

How do you emplace a template type object to unordered_set? How about pair of 2 template?

Upvotes: 1

Views: 1378

Answers (1)

rutofproblems
rutofproblems

Reputation: 51

I believe you need to provide special hashing and comparison functions to make the hash set (or in my example's case, hash map) work. Here is a minimal example. Tested with C++11.

#include <unordered_map>
#include <iostream>
#include <algorithm>

template<typename T>
struct foo {
  typedef T value_type;
  foo(T x) : x(x) {}
  T x;
};

template<typename T>
struct foo_hasher {
  int operator()(const T &val) const {
    return std::hash<typename T::value_type>()(val.x);
  }
};

template<typename T>
struct foo_equality {
  bool operator()(const T &left, const T& right) const {
    return left.x == right.x;
  }
};

int main() {
  typedef std::unordered_map<foo<int>, int, foo_hasher<foo<int>>, foo_equality<foo<int>>> Map;
  Map mp;
  foo<int> x(5);
  mp[x] = 10;
  mp[foo<int>(10)] = 22;

  std::for_each(mp.begin(), mp.end(), [](const Map::value_type &val) {
    std::cout << val.first.x << ", " << val.second << "\n";
  });
}

Note that both my hashing and equality function are not at all restrictive - they are wrt T rather than foo, but the principal should be the same.

Upvotes: 2

Related Questions