Pytanie Jak korzystać z funkcji is_transparent na literał łańcuchowy z unordered_map z std :: string?


Rozglądając się wokół cppreferencji, znalazłem to std::unordered_map  uzyskuje sprawne wyszukiwanie funkcje z "odpowiedników kluczy".

Rozumiem, że równoważny klucz musi mieć tę samą wartość skrótu. W jaki sposób mogę zapewnić, że dla literału ciągu otrzymuję tę samą wartość mieszania jak dla std::hash<std::string> bez czasowego budowania std::string i przez to, że nie ma nic ważnego na temat równoważnych kluczy?


13
2017-12-03 12:09


pochodzenie


Na pierwszy rzut oka widzę 2 problemy do pokonania: 1) znajdź (i drugi std::unordered_map funkcje wyszukiwania) wszyscy biorą Key const&, które natychmiast utworzą tymczasowo. 2) Nie ma std::hash specjalizacja dla literałów ciągowych. Podejrzewam, że najlepszą odpowiedzią jest napisanie własnego kontenera, który jest podobny do unordered_map, ale umożliwia wyszukiwanie za pomocą literałów łańcuchowych i używa niestandardowej funkcji skrótu, która może obsłużyć std::string (zapisane wartości), jak również const char* dla wyszukiwań. - Dave S
@DaveS, więc jak to się dzieje, że cppreference to mówi unordered_map zaczynając od C ++ 14 ma przeciążenie dla find który ma "równoważny klucz"? Jestem zmieszany. Artykuł w open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3657.htm które myślałem, że wprowadziłem is_transparent nie wydaje się wprowadzać go dla obiektów funkcji mieszania. Również to, co jest Compare o czym mówi cppreferencja? Mam przeczucie, że brakuje mi czegoś ważnego. Uważam, że to śmierdzące, że nawet w C ++ 14 nadal muszę napisać własny pojemnik dla takich prostych obaw :( - Johannes Schaub - litb
Tak, pomysł polegał na tym, że napisałeś własną funkcję haszującą, która obejmuje wszystkie równoważne typy. W tym przypadku zawsze miałem na myśli parę "pair <const char *, long>". Więc nie używaj std :: hash, ale własnego, który ma op () dla obu typów. - PlasmaHH
@PlasmaHH ahh widzę. coś takiego: coliru.stacked-crooked.com/a/f80fefd2c6c51c2e . Niestety, gcc i clang nie wydają się jeszcze go wspierać: / - Johannes Schaub - litb
Czy jesteśmy tego pewni? std::hash otrzymuje tę pomoc w C ++ 14? Dokument, który łączyłeś, pokazuje go tylko na pojemnikach asocjacyjnych, a nie nieuporządkowanych. cppreference, ze względu na wszystkie korzyści, również intensywnie korzysta z wewnętrznych szablonów w celu ograniczenia duplikacji. Wygląda na to, że oba map i unordered_map używają tego samego bloku opisu dla find, co wyjaśnia użycie Compare::is_transparent w opisie. - Dave S


Odpowiedzi:


To był błąd w cppreference; nie ma szablonów dla nieuporządkowanych powiązanych kontenerów.

Porównaj, od n3690,

od §23.5.4.1[unord.map.overview]

// lookup
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
size_type count(const key_type& k) const;

od §23.4.4.1[map.overview]

// 23.4.4.5, map operations:
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
template <class K> iterator find(const K& x);
template <class K> const_iterator find(const K& x) const;
size_type count(const key_type& x) const;

5
2017-12-03 14:32



Byłoby miło, gdyby dodali również niezamężone kontenery asocjacyjne. Wymagałoby to przezroczystości KeyEqualfunkcja, ale także Hash obsługujący zarówno typ klucza, jak i wkład do szablonu find. Myślę, że określenie tego drugiego byłoby nieco trudniejsze. - Dave S
@DaveS dla unordered_set< T, Hash, Equal >, iff Hash::is_transparent Dodaj unordered_set< T, Hash, Equal >::find<K>(const K& x) to robi Hash(x) następnie Equal( y, x ) gdzie y to element (y) znaleziony przez Hash(x)? Teraz, x musi być Equal-able (albo przez konwersję lub przezroczystość), ale ... - Yakk - Adam Nevraumont


Jak powiedzieli inni, nieuporządkowane pojemniki asocjacyjne nie wspierają is_transparent tryb. Boost.MultiIndex z kolei indeksy mieszane pozwalają na to, co chcesz, jak wyjaśniono w dokumentacja, w przypadku, gdy jest to opcja do zastąpienia std::unordered_map z równoważnym konstruktem opartym na a multi_index_container.


2
2017-12-19 07:24