devil0150
devil0150

Reputation: 1469

Syntax to pass argument to unordered_set hash function in c++

I have created a hasher class for a custom type I'm using, but it has a constructor that takes an argument. I can't figure out the syntax to use this in an unordered_set.

class Hasher {
    unsigned arg;
public:
    Hasher(unsigned a) : arg(a) {}
    size_t operator()(const MyType& t) const {
        return calculate_hash(arg, t);
    }
}

int main() {
    unordered_set<MyType, Hasher(2)> myset; // compilation error
}

The error message:

In file included from Tetrahedron.cc:5:
./Triangulation.h:52:29: error: template argument for template type parameter must be a type
       unordered_set<TetraFace,FaceHasher(2)> faces2;
                               ^~~~~~~~~~~~~
/bin/../lib/gcc/x86_64-redhat-linux/6.3.1/../../../../include/c++/6.3.1/bits/unordered_set.h:90:11: note: template parameter is declared here
       class _Hash = hash<_Value>,
             ^

I also tried

unordered_set<MyType, Hasher> myset(Hasher(2));

but I still get an error:

In file included from Tetrahedron.cc:5:
./Triangulation.h:52:59: error: expected ')'
    unordered_set<TetraFace,FaceHasher> faces2(FaceHasher(2));
                                                          ^
./Triangulation.h:52:58: note: to match this '('
unordered_set<TetraFace,FaceHasher> faces2(FaceHasher(2));
                                                     ^

Upvotes: 2

Views: 2076

Answers (2)

NathanOliver
NathanOliver

Reputation: 180585

Unfortunately it is not possible to construct a std::unorderd_set with just the hash object. All of the constructors that take the hash object have a parameter before it for bucket_count. You would need to specify the value for it like

unordered_set<MyType, Hasher> myset(some_bucket_count_value, Hasher(2));

If you do not want to do that then you have to make Hasher default constructable.

Also not that

return calculate_hash(arg);

Is not going to work as you will always hash arg no matter what MyType you pass. You need to be hashing the MyType object for the std::unordered_set to really work.

Upvotes: 0

CakePlusPlus
CakePlusPlus

Reputation: 993

You're getting a compile error there because you're trying to pass an object (i.e. instance) of type Hasher as a template argument.

Like your error describes: template argument for template type parameter must be a type

It's expecting a type, and you're passing in a value.

Parameterize the arg at the type level.

template<unsigned A>
class Hasher {
    unsigned arg = A;
public:
    size_t operator()(const int& t) const {
        std::cout << arg << std::endl;
        return 0;
    }
};

int main() {
    std::unordered_set<int, Hasher<2>> myset;
    myset.insert(5); // prints 2

    std::unordered_set<int, Hasher<3>> myset2;
    myset2.insert(3); // prints 3
}

Upvotes: 4

Related Questions