Zasadniczo moje pytanie brzmi, dlaczego ten kompilacyjny nie będzie?

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


}

Ale jeśli zmieniam to linię UnorderDed_set

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

To będzie. Dlaczego potrzebuje początkowej liczenia wiadra? Po prostu wydaje się dziwaczne, że używając lambda zmusza mnie do dodania początkowej liczenia wiadra, ale za pomocą funkcji nie będzie. Patrz przykład tutaj: C ++ UnorderDed_set vectors Dowód Wersja Funkcjonalna nie potrzebuje początkowa liczba wiader.

3
user3586940 11 marzec 2020, 06:12

2 odpowiedzi

Najlepsza odpowiedź

To po prostu dlatego, że nie ma takiego konstruktora.

tylko konstruktor UnorderDed_set, który bierze jeden parametr to ten, który bierze Instancja niestandardowego alokatora, a nie niestandardowej funkcji Hash.

Str.s. Nie zainicjujesz hash do 0, w funkcji niestandardowej Hash. Niesie to podwyższone ryzyko Demonów nosowych. Powinieneś to naprawić.

3
Sam Varshavchik 11 marzec 2020, 03:30

Tak jak sidenote, jeśli masz dostęp do C ++ 20, możesz zrobić decltype dla Lambda bez konstruowania jednego, pozwalając domyślnym konstruowaniu std::unordered_set.

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();
4
MaLarsson 11 marzec 2020, 05:15