sl@0: sl@0: // Copyright Daniel James 2005-2006. Use, modification, and distribution are sl@0: // subject to the Boost Software License, Version 1.0. (See accompanying sl@0: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: // Based on Peter Dimov's proposal sl@0: // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf sl@0: // issue 6.18. sl@0: /* sl@0: * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. sl@0: */ sl@0: #if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP) sl@0: #define BOOST_FUNCTIONAL_HASH_HASH_HPP sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) sl@0: #include sl@0: #endif sl@0: sl@0: #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: #include sl@0: #endif sl@0: sl@0: #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: #include sl@0: #endif sl@0: sl@0: namespace boost sl@0: { sl@0: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) sl@0: // Borland complains about an ambiguous function overload sl@0: // when compiling boost::hash. sl@0: std::size_t hash_value(bool); sl@0: #endif sl@0: sl@0: std::size_t hash_value(int); sl@0: std::size_t hash_value(unsigned int); sl@0: std::size_t hash_value(long); sl@0: std::size_t hash_value(unsigned long); sl@0: sl@0: #if defined(BOOST_MSVC) && defined(_WIN64) sl@0: // On 64-bit windows std::size_t is a typedef for unsigned long long, which sl@0: // isn't due to be supported until Boost 1.35. So add support here. sl@0: // (Technically, Boost.Hash isn't actually documented as supporting sl@0: // std::size_t. But it would be pretty silly not to). sl@0: std::size_t hash_value(std::size_t); sl@0: #endif sl@0: sl@0: #if !BOOST_WORKAROUND(__DMC__, <= 0x848) sl@0: template std::size_t hash_value(T* const&); sl@0: #else sl@0: template std::size_t hash_value(T*); sl@0: #endif sl@0: sl@0: #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: template< class T, unsigned N > sl@0: std::size_t hash_value(const T (&array)[N]); sl@0: sl@0: template< class T, unsigned N > sl@0: std::size_t hash_value(T (&array)[N]); sl@0: #endif sl@0: sl@0: std::size_t hash_value(float v); sl@0: std::size_t hash_value(double v); sl@0: std::size_t hash_value(long double v); sl@0: sl@0: template sl@0: std::size_t hash_value(std::basic_string, A> const&); sl@0: sl@0: template sl@0: std::size_t hash_value(std::pair const&); sl@0: template sl@0: std::size_t hash_value(std::vector const&); sl@0: template sl@0: std::size_t hash_value(std::list const& v); sl@0: template sl@0: std::size_t hash_value(std::deque const& v); sl@0: template sl@0: std::size_t hash_value(std::set const& v); sl@0: template sl@0: std::size_t hash_value(std::multiset const& v); sl@0: template sl@0: std::size_t hash_value(std::map const& v); sl@0: template sl@0: std::size_t hash_value(std::multimap const& v); sl@0: sl@0: // Implementation sl@0: sl@0: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) sl@0: inline std::size_t hash_value(bool v) sl@0: { sl@0: return static_cast(v); sl@0: } sl@0: #endif sl@0: sl@0: inline std::size_t hash_value(int v) sl@0: { sl@0: return static_cast(v); sl@0: } sl@0: sl@0: inline std::size_t hash_value(unsigned int v) sl@0: { sl@0: return static_cast(v); sl@0: } sl@0: sl@0: inline std::size_t hash_value(long v) sl@0: { sl@0: return static_cast(v); sl@0: } sl@0: sl@0: inline std::size_t hash_value(unsigned long v) sl@0: { sl@0: return static_cast(v); sl@0: } sl@0: sl@0: #if defined(_M_X64) && defined(_WIN64) sl@0: inline std::size_t hash_value(long long v) sl@0: { sl@0: return v; sl@0: } sl@0: sl@0: inline std::size_t hash_value(unsigned long long v) sl@0: { sl@0: return v; sl@0: } sl@0: #endif sl@0: sl@0: // Implementation by Alberto Barbati and Dave Harris. sl@0: #if !BOOST_WORKAROUND(__DMC__, <= 0x848) sl@0: template std::size_t hash_value(T* const& v) sl@0: #else sl@0: template std::size_t hash_value(T* v) sl@0: #endif sl@0: { sl@0: std::size_t x = static_cast( sl@0: reinterpret_cast(v)); sl@0: return x + (x >> 3); sl@0: } sl@0: sl@0: #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: template sl@0: inline void hash_combine(std::size_t& seed, T& v) sl@0: #else sl@0: template sl@0: inline void hash_combine(std::size_t& seed, T const& v) sl@0: #endif sl@0: { sl@0: boost::hash hasher; sl@0: seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); sl@0: } sl@0: sl@0: template sl@0: inline std::size_t hash_range(It first, It last) sl@0: { sl@0: std::size_t seed = 0; sl@0: sl@0: for(; first != last; ++first) sl@0: { sl@0: hash_combine(seed, *first); sl@0: } sl@0: sl@0: return seed; sl@0: } sl@0: sl@0: template sl@0: inline void hash_range(std::size_t& seed, It first, It last) sl@0: { sl@0: for(; first != last; ++first) sl@0: { sl@0: hash_combine(seed, *first); sl@0: } sl@0: } sl@0: sl@0: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) sl@0: template sl@0: inline std::size_t hash_range(T* first, T* last) sl@0: { sl@0: std::size_t seed = 0; sl@0: sl@0: for(; first != last; ++first) sl@0: { sl@0: boost::hash hasher; sl@0: seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); sl@0: } sl@0: sl@0: return seed; sl@0: } sl@0: sl@0: template sl@0: inline void hash_range(std::size_t& seed, T* first, T* last) sl@0: { sl@0: for(; first != last; ++first) sl@0: { sl@0: boost::hash hasher; sl@0: seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); sl@0: } sl@0: } sl@0: #endif sl@0: sl@0: #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: template< class T, unsigned N > sl@0: inline std::size_t hash_value(const T (&array)[N]) sl@0: { sl@0: return hash_range(array, array + N); sl@0: } sl@0: sl@0: template< class T, unsigned N > sl@0: inline std::size_t hash_value(T (&array)[N]) sl@0: { sl@0: return hash_range(array, array + N); sl@0: } sl@0: #endif sl@0: sl@0: template sl@0: inline std::size_t hash_value(std::basic_string, A> const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: inline std::size_t hash_value(float v) sl@0: { sl@0: return boost::hash_detail::float_hash_value(v); sl@0: } sl@0: sl@0: inline std::size_t hash_value(double v) sl@0: { sl@0: return boost::hash_detail::float_hash_value(v); sl@0: } sl@0: sl@0: #ifndef __SYMBIAN32__ //long double not supported sl@0: inline std::size_t hash_value(long double v) sl@0: { sl@0: return boost::hash_detail::float_hash_value(v); sl@0: } sl@0: #endif sl@0: template sl@0: std::size_t hash_value(std::pair const& v) sl@0: { sl@0: std::size_t seed = 0; sl@0: hash_combine(seed, v.first); sl@0: hash_combine(seed, v.second); sl@0: return seed; sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::vector const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::list const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::deque const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::set const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::multiset const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::map const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: template sl@0: std::size_t hash_value(std::multimap const& v) sl@0: { sl@0: return hash_range(v.begin(), v.end()); sl@0: } sl@0: sl@0: // sl@0: // boost::hash sl@0: // sl@0: sl@0: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: #define BOOST_HASH_SPECIALIZE(type) \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(type v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; sl@0: sl@0: #define BOOST_HASH_SPECIALIZE_REF(type) \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(type const& v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; sl@0: #else sl@0: #define BOOST_HASH_SPECIALIZE(type) \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(type v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; \ sl@0: \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(const type v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; sl@0: sl@0: #define BOOST_HASH_SPECIALIZE_REF(type) \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(type const& v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; \ sl@0: \ sl@0: template <> struct hash \ sl@0: : public std::unary_function \ sl@0: { \ sl@0: std::size_t operator()(type const& v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; sl@0: #endif sl@0: sl@0: BOOST_HASH_SPECIALIZE(bool) sl@0: BOOST_HASH_SPECIALIZE(char) sl@0: BOOST_HASH_SPECIALIZE(signed char) sl@0: BOOST_HASH_SPECIALIZE(unsigned char) sl@0: #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) || defined(__SYMBIAN32__) sl@0: BOOST_HASH_SPECIALIZE(wchar_t) sl@0: #endif sl@0: BOOST_HASH_SPECIALIZE(short) sl@0: BOOST_HASH_SPECIALIZE(unsigned short) sl@0: BOOST_HASH_SPECIALIZE(int) sl@0: BOOST_HASH_SPECIALIZE(unsigned int) sl@0: BOOST_HASH_SPECIALIZE(long) sl@0: BOOST_HASH_SPECIALIZE(unsigned long) sl@0: sl@0: BOOST_HASH_SPECIALIZE(float) sl@0: BOOST_HASH_SPECIALIZE(double) sl@0: BOOST_HASH_SPECIALIZE(long double) sl@0: sl@0: BOOST_HASH_SPECIALIZE_REF(std::string) sl@0: #if !defined(BOOST_NO_STD_WSTRING) sl@0: BOOST_HASH_SPECIALIZE_REF(std::wstring) sl@0: #endif sl@0: sl@0: #undef BOOST_HASH_SPECIALIZE sl@0: #undef BOOST_HASH_SPECIALIZE_REF sl@0: sl@0: #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) sl@0: template sl@0: struct hash sl@0: : public std::unary_function sl@0: { sl@0: std::size_t operator()(T* v) const \ sl@0: { \ sl@0: return boost::hash_value(v); \ sl@0: } \ sl@0: }; sl@0: #else sl@0: namespace hash_detail sl@0: { sl@0: template sl@0: struct hash_impl; sl@0: sl@0: template <> sl@0: struct hash_impl sl@0: { sl@0: template sl@0: struct inner sl@0: : public std::unary_function sl@0: { sl@0: std::size_t operator()(T val) const sl@0: { sl@0: return boost::hash_value(val); sl@0: } sl@0: }; sl@0: }; sl@0: } sl@0: sl@0: template struct hash sl@0: : public boost::hash_detail::hash_impl::value> sl@0: ::BOOST_NESTED_TEMPLATE inner sl@0: { sl@0: }; sl@0: #endif sl@0: } sl@0: sl@0: #endif // BOOST_FUNCTIONAL_HASH_HASH_HPP sl@0: sl@0: //////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: #if !defined(BOOST_HASH_NO_EXTENSIONS) \ sl@0: && !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) sl@0: #define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP sl@0: sl@0: namespace boost sl@0: { sl@0: sl@0: #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: namespace hash_detail sl@0: { sl@0: template sl@0: struct call_hash_impl sl@0: { sl@0: template sl@0: struct inner sl@0: { sl@0: static std::size_t call(T const& v) sl@0: { sl@0: using namespace boost; sl@0: return hash_value(v); sl@0: } sl@0: }; sl@0: }; sl@0: sl@0: template <> sl@0: struct call_hash_impl sl@0: { sl@0: template sl@0: struct inner sl@0: { sl@0: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: static std::size_t call(Array const& v) sl@0: #else sl@0: static std::size_t call(Array& v) sl@0: #endif sl@0: { sl@0: const int size = sizeof(v) / sizeof(*v); sl@0: return boost::hash_range(v, v + size); sl@0: } sl@0: }; sl@0: }; sl@0: sl@0: template sl@0: struct call_hash sl@0: : public call_hash_impl::value> sl@0: ::BOOST_NESTED_TEMPLATE inner sl@0: { sl@0: }; sl@0: } sl@0: #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING sl@0: sl@0: #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) sl@0: sl@0: template struct hash sl@0: : std::unary_function sl@0: { sl@0: #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: std::size_t operator()(T const& val) const sl@0: { sl@0: return hash_value(val); sl@0: } sl@0: #else sl@0: std::size_t operator()(T const& val) const sl@0: { sl@0: return hash_detail::call_hash::call(val); sl@0: } sl@0: #endif sl@0: }; sl@0: sl@0: #if BOOST_WORKAROUND(__DMC__, <= 0x848) sl@0: template struct hash sl@0: : std::unary_function sl@0: { sl@0: std::size_t operator()(const T* val) const sl@0: { sl@0: return boost::hash_range(val, val+n); sl@0: } sl@0: }; sl@0: #endif sl@0: sl@0: #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION sl@0: sl@0: // On compilers without partial specialization, boost::hash sl@0: // has already been declared to deal with pointers, so just sl@0: // need to supply the non-pointer version. sl@0: sl@0: namespace hash_detail sl@0: { sl@0: template sl@0: struct hash_impl; sl@0: sl@0: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: sl@0: template <> sl@0: struct hash_impl sl@0: { sl@0: template sl@0: struct inner sl@0: : std::unary_function sl@0: { sl@0: #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) sl@0: std::size_t operator()(T const& val) const sl@0: { sl@0: return hash_value(val); sl@0: } sl@0: #else sl@0: std::size_t operator()(T const& val) const sl@0: { sl@0: return hash_detail::call_hash::call(val); sl@0: } sl@0: #endif sl@0: }; sl@0: }; sl@0: sl@0: #else // Visual C++ 6.5 sl@0: sl@0: // There's probably a more elegant way to Visual C++ 6.5 to work sl@0: // but I don't know what it is. sl@0: sl@0: template sl@0: struct hash_impl_msvc sl@0: { sl@0: template sl@0: struct inner sl@0: : public std::unary_function sl@0: { sl@0: std::size_t operator()(T const& val) const sl@0: { sl@0: return hash_detail::call_hash::call(val); sl@0: } sl@0: sl@0: std::size_t operator()(T& val) const sl@0: { sl@0: return hash_detail::call_hash::call(val); sl@0: } sl@0: }; sl@0: }; sl@0: sl@0: template <> sl@0: struct hash_impl_msvc sl@0: { sl@0: template sl@0: struct inner sl@0: : public std::unary_function sl@0: { sl@0: std::size_t operator()(T& val) const sl@0: { sl@0: return hash_detail::call_hash::call(val); sl@0: } sl@0: }; sl@0: }; sl@0: sl@0: template sl@0: struct hash_impl_msvc2 sl@0: : public hash_impl_msvc::value> sl@0: ::BOOST_NESTED_TEMPLATE inner {}; sl@0: sl@0: template <> sl@0: struct hash_impl sl@0: { sl@0: template sl@0: struct inner : public hash_impl_msvc2 {}; sl@0: }; sl@0: sl@0: #endif // Visual C++ 6.5 sl@0: } sl@0: #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION sl@0: } sl@0: sl@0: #endif sl@0: