2011-11-06 14 views
22

I just znalazłem się trochę zaskoczony nie jest w stanie po prostu użyćCzy nie ma specjalizacji od std :: hash dla standardowych kontenerów?

std::unordered_set<std::array<int, 16> > test; 

ponieważ nie wydaje się być std::hash specjalizacja dla std::array s. Dlaczego? A może po prostu go nie znalazłem? Jeśli rzeczywiście tak jest, czy następująca próba implementacji może zostać uproszczona?

namespace std 
{ 
    template<typename T, size_t N> 
    struct hash<array<T, N> > 
    { 
     typedef array<T, N> argument_type; 
     typedef size_t result_type; 

     result_type operator()(const argument_type& a) const 
     { 
      hash<T> hasher; 
      result_type h = 0; 
      for (result_type i = 0; i < N; ++i) 
      { 
       h = h * 31 + hasher(a[i]); 
      } 
      return h; 
     } 
    }; 
} 

Naprawdę uważam, że powinno to być częścią standardowej biblioteki.

+3

Naprawdę nie ma jednego, tylko 'std :: string' i znajomi mają ten przywilej. Czy byłbym naprawdę niepopularny, gdybym powiedział, że to dlatego, że wysiłki C++, aby przeciągnąć się w kierunku obecnego stanu sztuki w kategoriach standardowych struktur danych, jeszcze nie wykonały całej pracy? W rzeczywistości nie ma żadnych wymaganych specjalizacji 'hash' dla szablonów (które z kolei wymagałyby, aby ich argumenty z szablonu były nieosiągalne). Jedynymi wymaganymi specjalizacjami są wbudowane typy i cztery konkretne klasy ciągów. Podejrzewam, że tam narysowano linię. –

+0

@Steve: Jakie 4 konkretne klasy ciągów? – fredoverflow

+2

'string',' u16string', 'u32string',' wstring' (21,6 w C++ 11). Powiedziałbym, że 'pair' i' tuple' powinny być kolejnymi celami o najwyższym priorytecie, a następnie standardowymi kontenerami, po których następuje domyślny skrót dla dowolnego typu agregatu złożonego z hashable członków. –

Odpowiedz

11

Nie jestem pewien, dlaczego średnia biblioteka nie włączyła, ale doładowania ma mieszania dla wszelkiego rodzaju rzeczy wykonanych z hashable typów. Kluczową funkcją jest tutaj hash_combine, którą możesz skopiować z boost/functional/hash/hash.hpp.

Używając hash_combine, Boost uzyskuje range_hash (po prostu łączenie skrótów każdego elementu zakresu), a także parę i tasowanie. Z kolei range_hash może służyć do mieszania dowolnego iterowalnego pojemnika.

+8

Tak, 'range_hash' brzmi jak powinno być w standardzie. – fredoverflow

11

Brak odpowiedzi, ale kilka przydatnych informacji. FEB projekt standardu C++ 11 określa, że ​​std::hash specjalizuje się dla tych typów:

  • error_code § 19.5.5
  • bitset<N> § 20.5.3
  • unique_ptr<T, D> § 20.7.2.36
  • shared_ptr<T, D> § 20.7.2.36
  • type_index § 20.13.4
  • string § 21.6
  • u16string § 21.6
  • u32string § 21.6
  • wstring § 21.6
  • vector<bool, Allocator> § 23.3.8
  • thread::id § 30.3.1.1

I wszystkie te rodzaje: § 20.08.12

template <> struct hash<bool>; 
template <> struct hash<char>; 
template <> struct hash<signed char>; 
template <> struct hash<unsigned char>; 
template <> struct hash<char16_t>; 
template <> struct hash<char32_t>; 
template <> struct hash<wchar_t>; 
template <> struct hash<short>; 
template <> struct hash<unsigned short>; 
template <> struct hash<int>; 
template <> struct hash<unsigned int>; 
template <> struct hash<long>; 
template <> struct hash<long long>; 
template <> struct hash<unsigned long>; 
template <> struct hash<unsigned long long>; 
template <> struct hash<float>; 
template <> struct hash<double>; 
template <> struct hash<long double>; 
template<class T> struct hash<T*>; 
Powiązane problemy