Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there no specializations of std::hash for standard containers?

I just found myself a little bit surprised being unable to simply use a

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

because there does not seem to be a std::hash specialization for std::arrays. Why is that? Or did I simply not find it? If there is indeed none, can the following implementation attempt be simplified?

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;         }     }; } 

I really feel this should somehow be part of the standard library.

like image 870
fredoverflow Avatar asked Nov 06 '11 13:11

fredoverflow


People also ask

Is STD hash unique?

That means you can only have 256 unique hashes of arbitrary inputs. Since you can definitely create more than 256 different strings, there is no way the hash would be unique for all possible strings.

What does std :: hash do?

std::hash<const char*> produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.

How do I hash a string in CPP?

using c++11, you can: #include <string> #include <unordered_map> std::size_t h1 = std::hash<std::string>{}("MyString"); std::size_t h2 = std::hash<double>{}(3.14159);

Is std :: tuple hashable?

The answer is no, can't be done for all tuples, since a tuple is a variadic template type.


2 Answers

Not an answer, but some useful information. The Feb draft of the C++11 standard specifies that std::hash is specialized for these types:

  • 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

And all these types: § 20.8.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*>; 
like image 167
Mooing Duck Avatar answered Oct 07 '22 17:10

Mooing Duck


I'm not sure why the standard library hasn't included this, but Boost has hashing for all sorts of things made up from hashable types. The key function for this is hash_combine, which you are welcome to copy from boost/functional/hash/hash.hpp.

Using hash_combine, Boost derives a range_hash (just combining the hashes of a each element of a range), as well as pair and tuple hashers. The range_hash in turn can be used to hash any iterable container.

like image 25
Kerrek SB Avatar answered Oct 07 '22 18:10

Kerrek SB