1 /*! 2 @file 3 Defines `boost::hana::hash`. 4 5 @copyright Jason Rice 2016 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_HASH_HPP 11 #define BOOST_HANA_HASH_HPP 12 13 #include <boost/hana/fwd/hash.hpp> 14 15 #include <boost/hana/concept/hashable.hpp> 16 #include <boost/hana/concept/integral_constant.hpp> 17 #include <boost/hana/config.hpp> 18 #include <boost/hana/core/dispatch.hpp> 19 #include <boost/hana/fwd/integral_constant.hpp> 20 #include <boost/hana/type.hpp> 21 22 #include <type_traits> 23 24 25 BOOST_HANA_NAMESPACE_BEGIN 26 //! @cond 27 template <typename X> operator ()(X const & x) const28 constexpr auto hash_t::operator()(X const& x) const { 29 using Tag = typename hana::tag_of<X>::type; 30 using Hash = BOOST_HANA_DISPATCH_IF(hash_impl<Tag>, 31 hana::Hashable<Tag>::value 32 ); 33 34 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS 35 static_assert(hana::Hashable<Tag>::value, 36 "hana::hash(x) requires 'x' to be Hashable"); 37 #endif 38 39 return Hash::apply(x); 40 } 41 //! @endcond 42 43 template <typename Tag, bool condition> 44 struct hash_impl<Tag, when<condition>> : default_ { 45 template <typename X> 46 static constexpr auto apply(X const&) = delete; 47 }; 48 49 namespace detail { 50 template <typename T, typename = void> 51 struct hash_integral_helper; 52 53 template <typename Member, typename T> 54 struct hash_integral_helper<Member T::*> { 55 template <typename X> applydetail::hash_integral_helper56 static constexpr auto apply(X const&) { 57 return hana::type_c<hana::integral_constant<Member T::*, X::value>>; 58 } 59 }; 60 61 template <typename T> 62 struct hash_integral_helper<T, 63 typename std::enable_if<std::is_signed<T>::value>::type 64 > { 65 template <typename X> applydetail::hash_integral_helper66 static constexpr auto apply(X const&) { 67 constexpr signed long long x = X::value; 68 return hana::type_c<hana::integral_constant<signed long long, x>>; 69 } 70 }; 71 72 template <typename T> 73 struct hash_integral_helper<T, 74 typename std::enable_if<std::is_unsigned<T>::value>::type 75 > { 76 template <typename X> applydetail::hash_integral_helper77 static constexpr auto apply(X const&) { 78 constexpr unsigned long long x = X::value; 79 return hana::type_c<hana::integral_constant<unsigned long long, x>>; 80 } 81 }; 82 83 template <> 84 struct hash_integral_helper<bool> { 85 template <typename X> applydetail::hash_integral_helper86 static constexpr auto apply(X const&) { 87 return hana::type_c<hana::integral_constant<bool, X::value>>; 88 } 89 }; 90 91 template <> 92 struct hash_integral_helper<char> { 93 template <typename X> applydetail::hash_integral_helper94 static constexpr auto apply(X const&) { 95 using T = std::conditional<std::is_signed<char>::value, 96 signed long long, unsigned long long 97 >::type; 98 constexpr T x = X::value; 99 return hana::type_c<hana::integral_constant<T, x>>; 100 } 101 }; 102 } 103 104 template <typename Tag> 105 struct hash_impl<Tag, when<hana::IntegralConstant<Tag>::value>> { 106 template <typename X> applyhash_impl107 static constexpr auto apply(X const& x) { 108 using T = typename std::remove_cv<decltype(X::value)>::type; 109 return detail::hash_integral_helper<T>::apply(x); 110 } 111 }; 112 BOOST_HANA_NAMESPACE_END 113 114 #endif // !BOOST_HANA_HASH_HPP 115