diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h index f9f7d2c767caa..489a6f00b8a3d 100644 --- a/libcxx/include/__functional/hash.h +++ b/libcxx/include/__functional/hash.h @@ -19,6 +19,8 @@ #include <__type_traits/invoke.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_enum.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> #include <__type_traits/underlying_type.h> #include <__utility/pair.h> #include <__utility/swap.h> @@ -345,122 +347,43 @@ struct hash<_Tp*> : public __unary_function<_Tp*, size_t> { } }; -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_CHAR8_T -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_CHAR8_T - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_WIDE_CHARACTERS -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT { return static_cast(__v); } +template +struct __hash_impl { + __hash_impl() = delete; + __hash_impl(__hash_impl const&) = delete; + __hash_impl& operator=(__hash_impl const&) = delete; }; -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT { - static_assert(sizeof(size_t) >= sizeof(unsigned long), - "This would be a terrible hash function on a platform where size_t is smaller than unsigned long"); - return static_cast(__v); +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { + using type = __underlying_type_t<_Tp>; + return hash()(static_cast(__v)); } }; -template <> -struct hash : public __scalar_hash {}; - -template <> -struct hash : public __scalar_hash {}; - -#if _LIBCPP_HAS_INT128 - -template <> -struct hash<__int128_t> : public __scalar_hash<__int128_t> {}; - -template <> -struct hash<__uint128_t> : public __scalar_hash<__uint128_t> {}; +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) <= sizeof(size_t))> > + : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { return static_cast(__v); } +}; -#endif +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) > sizeof(size_t))> > + : __scalar_hash<_Tp> {}; -template <> -struct hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT { +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __scalar_hash<_Tp> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0f) return 0; - return __scalar_hash::operator()(__v); - } -}; - -template <> -struct hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT { - // -0.0 and 0.0 should return same hash - if (__v == 0.0) - return 0; - return __scalar_hash::operator()(__v); + return __scalar_hash<_Tp>::operator()(__v); } }; template <> -struct hash : public __scalar_hash { +struct __hash_impl : __scalar_hash { _LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0L) @@ -501,22 +424,8 @@ struct hash : public __scalar_hash { } }; -template ::value> -struct __enum_hash : public __unary_function<_Tp, size_t> { - _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { - using type = __underlying_type_t<_Tp>; - return hash()(static_cast(__v)); - } -}; -template -struct __enum_hash<_Tp, false> { - __enum_hash() = delete; - __enum_hash(__enum_hash const&) = delete; - __enum_hash& operator=(__enum_hash const&) = delete; -}; - template -struct hash : public __enum_hash<_Tp> {}; +struct hash : public __hash_impl<_Tp> {}; #if _LIBCPP_STD_VER >= 17