Hisham Hijjawi
Hisham Hijjawi

Reputation: 2425

Why does a unordered_set with a custom hash function and custom class need an initial number of buckets?

Basically my question is, why won't this compile?

#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;


int main() {
    vector<int> v{1,2,3};
    auto hash_function=[](const vector<int>& v){
        size_t hash;
        for (int i = 0; i < v.size(); ++i) {
            hash+=v[i]+31*hash;
        }
        return hash;
        };

unordered_set<vector<int>, decltype(hash_function)> s(hash_function);
std::cout<<s.bucket_count();
std::cout<<"here";


}

but if I change the unordered_set line to this

unordered_set<vector<int>, decltype(hash_function)> s(10,hash_function);

It will. Why does it need an initial bucket count? It just seems bizarre that using a lambda forces me to add an initial bucket count, but using a functor it won't. See example here: C++ unordered_set of vectors for proof the functor version doesn't need an initial number of buckets.

Upvotes: 5

Views: 977

Answers (2)

MaLarsson
MaLarsson

Reputation: 260

Just as a sidenote, if you have access to C++20 you can do the decltype for the lambda without constructing one, letting the std::unordered_set default construct it.

using hash_function = decltype([](const std::vector<int>& v) {
    size_t hash = 0;
    for (int i = 0; i < v.size(); ++i) {
        hash += v[i] + 31 * hash;
    }
    return hash;
});

std::unordered_set<std::vector<int>, hash_function> s();

Upvotes: 4

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

That's simply because there is no such constructor.

The only unordered_set constructor that takes one parameter is the one that takes an instance of a custom allocator, and not a custom hash function.

P.S. You fail to initialize hash to 0, in your custom hash function. This carries an elevated risk of nasal demons. You should fix that.

Upvotes: 3

Related Questions