extensions.hpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright 2005-2009 Daniel James.
  2. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. // Based on Peter Dimov's proposal
  5. // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
  6. // issue 6.18.
  7. // This implements the extensions to the standard.
  8. // It's undocumented, so you shouldn't use it....
  9. #if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
  10. #define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
  11. #include <boost/functional/hash/hash.hpp>
  12. #include <boost/detail/container_fwd.hpp>
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  14. # pragma once
  15. #endif
  16. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  17. #include <boost/type_traits/is_array.hpp>
  18. #endif
  19. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  20. #include <boost/type_traits/is_const.hpp>
  21. #endif
  22. namespace boost
  23. {
  24. template <class A, class B>
  25. std::size_t hash_value(std::pair<A, B> const&);
  26. template <class T, class A>
  27. std::size_t hash_value(std::vector<T, A> const&);
  28. template <class T, class A>
  29. std::size_t hash_value(std::list<T, A> const& v);
  30. template <class T, class A>
  31. std::size_t hash_value(std::deque<T, A> const& v);
  32. template <class K, class C, class A>
  33. std::size_t hash_value(std::set<K, C, A> const& v);
  34. template <class K, class C, class A>
  35. std::size_t hash_value(std::multiset<K, C, A> const& v);
  36. template <class K, class T, class C, class A>
  37. std::size_t hash_value(std::map<K, T, C, A> const& v);
  38. template <class K, class T, class C, class A>
  39. std::size_t hash_value(std::multimap<K, T, C, A> const& v);
  40. template <class T>
  41. std::size_t hash_value(std::complex<T> const&);
  42. template <class A, class B>
  43. std::size_t hash_value(std::pair<A, B> const& v)
  44. {
  45. std::size_t seed = 0;
  46. hash_combine(seed, v.first);
  47. hash_combine(seed, v.second);
  48. return seed;
  49. }
  50. template <class T, class A>
  51. std::size_t hash_value(std::vector<T, A> const& v)
  52. {
  53. return hash_range(v.begin(), v.end());
  54. }
  55. template <class T, class A>
  56. std::size_t hash_value(std::list<T, A> const& v)
  57. {
  58. return hash_range(v.begin(), v.end());
  59. }
  60. template <class T, class A>
  61. std::size_t hash_value(std::deque<T, A> const& v)
  62. {
  63. return hash_range(v.begin(), v.end());
  64. }
  65. template <class K, class C, class A>
  66. std::size_t hash_value(std::set<K, C, A> const& v)
  67. {
  68. return hash_range(v.begin(), v.end());
  69. }
  70. template <class K, class C, class A>
  71. std::size_t hash_value(std::multiset<K, C, A> const& v)
  72. {
  73. return hash_range(v.begin(), v.end());
  74. }
  75. template <class K, class T, class C, class A>
  76. std::size_t hash_value(std::map<K, T, C, A> const& v)
  77. {
  78. return hash_range(v.begin(), v.end());
  79. }
  80. template <class K, class T, class C, class A>
  81. std::size_t hash_value(std::multimap<K, T, C, A> const& v)
  82. {
  83. return hash_range(v.begin(), v.end());
  84. }
  85. template <class T>
  86. std::size_t hash_value(std::complex<T> const& v)
  87. {
  88. boost::hash<T> hasher;
  89. std::size_t seed = hasher(v.imag());
  90. seed ^= hasher(v.real()) + (seed<<6) + (seed>>2);
  91. return seed;
  92. }
  93. //
  94. // call_hash_impl
  95. //
  96. // On compilers without function template ordering, this deals with arrays.
  97. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  98. namespace hash_detail
  99. {
  100. template <bool IsArray>
  101. struct call_hash_impl
  102. {
  103. template <class T>
  104. struct inner
  105. {
  106. static std::size_t call(T const& v)
  107. {
  108. using namespace boost;
  109. return hash_value(v);
  110. }
  111. };
  112. };
  113. template <>
  114. struct call_hash_impl<true>
  115. {
  116. template <class Array>
  117. struct inner
  118. {
  119. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  120. static std::size_t call(Array const& v)
  121. #else
  122. static std::size_t call(Array& v)
  123. #endif
  124. {
  125. const int size = sizeof(v) / sizeof(*v);
  126. return boost::hash_range(v, v + size);
  127. }
  128. };
  129. };
  130. template <class T>
  131. struct call_hash
  132. : public call_hash_impl<boost::is_array<T>::value>
  133. ::BOOST_NESTED_TEMPLATE inner<T>
  134. {
  135. };
  136. }
  137. #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  138. //
  139. // boost::hash
  140. //
  141. #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  142. template <class T> struct hash
  143. : std::unary_function<T, std::size_t>
  144. {
  145. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  146. std::size_t operator()(T const& val) const
  147. {
  148. return hash_value(val);
  149. }
  150. #else
  151. std::size_t operator()(T const& val) const
  152. {
  153. return hash_detail::call_hash<T>::call(val);
  154. }
  155. #endif
  156. };
  157. #if BOOST_WORKAROUND(__DMC__, <= 0x848)
  158. template <class T, unsigned int n> struct hash<T[n]>
  159. : std::unary_function<T[n], std::size_t>
  160. {
  161. std::size_t operator()(const T* val) const
  162. {
  163. return boost::hash_range(val, val+n);
  164. }
  165. };
  166. #endif
  167. #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  168. // On compilers without partial specialization, boost::hash<T>
  169. // has already been declared to deal with pointers, so just
  170. // need to supply the non-pointer version of hash_impl.
  171. namespace hash_detail
  172. {
  173. template <bool IsPointer>
  174. struct hash_impl;
  175. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  176. template <>
  177. struct hash_impl<false>
  178. {
  179. template <class T>
  180. struct inner
  181. : std::unary_function<T, std::size_t>
  182. {
  183. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  184. std::size_t operator()(T const& val) const
  185. {
  186. return hash_value(val);
  187. }
  188. #else
  189. std::size_t operator()(T const& val) const
  190. {
  191. return hash_detail::call_hash<T>::call(val);
  192. }
  193. #endif
  194. };
  195. };
  196. #else // Visual C++ 6.5
  197. // Visual C++ 6.5 has problems with nested member functions and
  198. // applying const to const types in templates. So we get this:
  199. template <bool IsConst>
  200. struct hash_impl_msvc
  201. {
  202. template <class T>
  203. struct inner
  204. : public std::unary_function<T, std::size_t>
  205. {
  206. std::size_t operator()(T const& val) const
  207. {
  208. return hash_detail::call_hash<T const>::call(val);
  209. }
  210. std::size_t operator()(T& val) const
  211. {
  212. return hash_detail::call_hash<T>::call(val);
  213. }
  214. };
  215. };
  216. template <>
  217. struct hash_impl_msvc<true>
  218. {
  219. template <class T>
  220. struct inner
  221. : public std::unary_function<T, std::size_t>
  222. {
  223. std::size_t operator()(T& val) const
  224. {
  225. return hash_detail::call_hash<T>::call(val);
  226. }
  227. };
  228. };
  229. template <class T>
  230. struct hash_impl_msvc2
  231. : public hash_impl_msvc<boost::is_const<T>::value>
  232. ::BOOST_NESTED_TEMPLATE inner<T> {};
  233. template <>
  234. struct hash_impl<false>
  235. {
  236. template <class T>
  237. struct inner : public hash_impl_msvc2<T> {};
  238. };
  239. #endif // Visual C++ 6.5
  240. }
  241. #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  242. }
  243. #endif