Default implementation of std::hash template

Daniel Frey d.frey@gmx.de
Wed Mar 6 19:13:00 GMT 2013


Hello,

I was trying to implement a traits class to detect whether or not a type is hashable. My attempt looked like this:

#include <type_traits>
#include <unordered_set>
#include <utility>
#include <iostream>

template< typename, typename = void >
struct is_hashable : std::false_type {};

template< typename T >
struct is_hashable< T, typename std::enable_if< !!sizeof( std::declval< std::hash< T > >()( std::declval< T >() ) >::type >
  : std::true_type {};

int main()
{
  std::cout << is_hashable< int >::value << std::endl;
  std::cout << is_hashable< std::pair< int, int > >::value << std::endl;
}

which works with Clang + libc++, but not with GCC or Clang and libstdc++. The reason is bits/functional_hash.h, where the implementation of the primary class template hash looks like this:

template<typename _Tp>
  struct hash : public __hash_base<size_t, _Tp>
  {
    static_assert(sizeof(_Tp) < 0,
                  "std::hash is not specialized for this type");
    size_t operator()(const _Tp&) const noexcept;
  };

Now, this is of course a problem for the above is_hashable, as the static_assert fires for T == std::pair< int, int >. I understand the reason for adding it, so I'm not proposing to remove it, but I had another idea. It consists of two parts:

a) Move the static_assert from the class level into a method. The destructor could be used.
b) Remove the superfluous operator().

With this:

template<typename _Tp>
  struct hash : public __hash_base<size_t, _Tp>
  {
    ~hash() {
      static_assert(sizeof(_Tp) < 0,
                    "std::hash is not specialized for this type");
    }
  };

we can have both is_hashable and the static_assert, which fires if someone tries to instantiate the template:

  std::unordered_set< std::pair< int, int > > dummy; // fires the static_assert.

What do you think?

Best regards, Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 203 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20130306/d2059048/attachment.sig>


More information about the Libstdc++ mailing list