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