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