Skip to content

Commit 4fc3297

Browse files
committed
[libc++] Simplify the implementation of std::hash
1 parent f1886b1 commit 4fc3297

File tree

1 file changed

+26
-117
lines changed
  • libcxx/include/__functional

1 file changed

+26
-117
lines changed

libcxx/include/__functional/hash.h

Lines changed: 26 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <__type_traits/invoke.h>
2020
#include <__type_traits/is_constructible.h>
2121
#include <__type_traits/is_enum.h>
22+
#include <__type_traits/is_floating_point.h>
23+
#include <__type_traits/is_integral.h>
2224
#include <__type_traits/underlying_type.h>
2325
#include <__utility/pair.h>
2426
#include <__utility/swap.h>
@@ -345,122 +347,43 @@ struct hash<_Tp*> : public __unary_function<_Tp*, size_t> {
345347
}
346348
};
347349

348-
template <>
349-
struct hash<bool> : public __unary_function<bool, size_t> {
350-
_LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
351-
};
352-
353-
template <>
354-
struct hash<char> : public __unary_function<char, size_t> {
355-
_LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
356-
};
357-
358-
template <>
359-
struct hash<signed char> : public __unary_function<signed char, size_t> {
360-
_LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
361-
};
362-
363-
template <>
364-
struct hash<unsigned char> : public __unary_function<unsigned char, size_t> {
365-
_LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
366-
};
367-
368-
#if _LIBCPP_HAS_CHAR8_T
369-
template <>
370-
struct hash<char8_t> : public __unary_function<char8_t, size_t> {
371-
_LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
372-
};
373-
#endif // _LIBCPP_HAS_CHAR8_T
374-
375-
template <>
376-
struct hash<char16_t> : public __unary_function<char16_t, size_t> {
377-
_LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
378-
};
379-
380-
template <>
381-
struct hash<char32_t> : public __unary_function<char32_t, size_t> {
382-
_LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
383-
};
384-
385-
#if _LIBCPP_HAS_WIDE_CHARACTERS
386-
template <>
387-
struct hash<wchar_t> : public __unary_function<wchar_t, size_t> {
388-
_LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
389-
};
390-
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
391-
392-
template <>
393-
struct hash<short> : public __unary_function<short, size_t> {
394-
_LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
395-
};
396-
397-
template <>
398-
struct hash<unsigned short> : public __unary_function<unsigned short, size_t> {
399-
_LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
350+
template <class _Tp, class = void>
351+
struct __hash_impl {
352+
__hash_impl() = delete;
353+
__hash_impl(__hash_impl const&) = delete;
354+
__hash_impl& operator=(__hash_impl const&) = delete;
400355
};
401356

402-
template <>
403-
struct hash<int> : public __unary_function<int, size_t> {
404-
_LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
405-
};
406-
407-
template <>
408-
struct hash<unsigned int> : public __unary_function<unsigned int, size_t> {
409-
_LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
410-
};
411-
412-
template <>
413-
struct hash<long> : public __unary_function<long, size_t> {
414-
_LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
415-
};
416-
417-
template <>
418-
struct hash<unsigned long> : public __unary_function<unsigned long, size_t> {
419-
_LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT {
420-
static_assert(sizeof(size_t) >= sizeof(unsigned long),
421-
"This would be a terrible hash function on a platform where size_t is smaller than unsigned long");
422-
return static_cast<size_t>(__v);
357+
template <class _Tp>
358+
struct __hash_impl<_Tp, __enable_if_t<is_enum<_Tp>::value> > : __unary_function<_Tp, size_t> {
359+
_LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT {
360+
using type = __underlying_type_t<_Tp>;
361+
return hash<type>()(static_cast<type>(__v));
423362
}
424363
};
425364

426-
template <>
427-
struct hash<long long> : public __scalar_hash<long long> {};
428-
429-
template <>
430-
struct hash<unsigned long long> : public __scalar_hash<unsigned long long> {};
431-
432-
#if _LIBCPP_HAS_INT128
433-
434-
template <>
435-
struct hash<__int128_t> : public __scalar_hash<__int128_t> {};
436-
437-
template <>
438-
struct hash<__uint128_t> : public __scalar_hash<__uint128_t> {};
365+
template <class _Tp>
366+
struct __hash_impl<_Tp, __enable_if_t<is_integral<_Tp>::value && (sizeof(_Tp) <= sizeof(size_t))> >
367+
: __unary_function<_Tp, size_t> {
368+
_LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
369+
};
439370

440-
#endif
371+
template <class _Tp>
372+
struct __hash_impl<_Tp, __enable_if_t<is_integral<_Tp>::value && (sizeof(_Tp) > sizeof(size_t))> >
373+
: __scalar_hash<_Tp> {};
441374

442-
template <>
443-
struct hash<float> : public __scalar_hash<float> {
444-
_LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT {
375+
template <class _Tp>
376+
struct __hash_impl<_Tp, __enable_if_t<is_floating_point<_Tp>::value> > : __scalar_hash<_Tp> {
377+
_LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT {
445378
// -0.0 and 0.0 should return same hash
446379
if (__v == 0.0f)
447380
return 0;
448-
return __scalar_hash<float>::operator()(__v);
449-
}
450-
};
451-
452-
template <>
453-
struct hash<double> : public __scalar_hash<double> {
454-
_LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT {
455-
// -0.0 and 0.0 should return same hash
456-
if (__v == 0.0)
457-
return 0;
458-
return __scalar_hash<double>::operator()(__v);
381+
return __scalar_hash<_Tp>::operator()(__v);
459382
}
460383
};
461384

462385
template <>
463-
struct hash<long double> : public __scalar_hash<long double> {
386+
struct __hash_impl<long double> : __scalar_hash<long double> {
464387
_LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT {
465388
// -0.0 and 0.0 should return same hash
466389
if (__v == 0.0L)
@@ -501,22 +424,8 @@ struct hash<long double> : public __scalar_hash<long double> {
501424
}
502425
};
503426

504-
template <class _Tp, bool = is_enum<_Tp>::value>
505-
struct __enum_hash : public __unary_function<_Tp, size_t> {
506-
_LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT {
507-
using type = __underlying_type_t<_Tp>;
508-
return hash<type>()(static_cast<type>(__v));
509-
}
510-
};
511-
template <class _Tp>
512-
struct __enum_hash<_Tp, false> {
513-
__enum_hash() = delete;
514-
__enum_hash(__enum_hash const&) = delete;
515-
__enum_hash& operator=(__enum_hash const&) = delete;
516-
};
517-
518427
template <class _Tp>
519-
struct hash : public __enum_hash<_Tp> {};
428+
struct hash : public __hash_impl<_Tp> {};
520429

521430
#if _LIBCPP_STD_VER >= 17
522431

0 commit comments

Comments
 (0)