extensions.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. #include <boost/utility/enable_if.hpp>
  14. #include <boost/static_assert.hpp>
  15. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  16. #include <boost/preprocessor/repetition/enum_params.hpp>
  17. #if !defined(BOOST_NO_CXX11_HDR_ARRAY)
  18. # include <array>
  19. #endif
  20. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
  21. # include <tuple>
  22. #endif
  23. #if !defined(BOOST_NO_CXX11_HDR_MEMORY)
  24. # include <memory>
  25. #endif
  26. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  27. # pragma once
  28. #endif
  29. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  30. #include <boost/type_traits/is_array.hpp>
  31. #endif
  32. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  33. #include <boost/type_traits/is_const.hpp>
  34. #endif
  35. namespace boost
  36. {
  37. template <class A, class B>
  38. std::size_t hash_value(std::pair<A, B> const&);
  39. template <class T, class A>
  40. std::size_t hash_value(std::vector<T, A> const&);
  41. template <class T, class A>
  42. std::size_t hash_value(std::list<T, A> const& v);
  43. template <class T, class A>
  44. std::size_t hash_value(std::deque<T, A> const& v);
  45. template <class K, class C, class A>
  46. std::size_t hash_value(std::set<K, C, A> const& v);
  47. template <class K, class C, class A>
  48. std::size_t hash_value(std::multiset<K, C, A> const& v);
  49. template <class K, class T, class C, class A>
  50. std::size_t hash_value(std::map<K, T, C, A> const& v);
  51. template <class K, class T, class C, class A>
  52. std::size_t hash_value(std::multimap<K, T, C, A> const& v);
  53. template <class T>
  54. std::size_t hash_value(std::complex<T> const&);
  55. template <class A, class B>
  56. std::size_t hash_value(std::pair<A, B> const& v)
  57. {
  58. std::size_t seed = 0;
  59. boost::hash_combine(seed, v.first);
  60. boost::hash_combine(seed, v.second);
  61. return seed;
  62. }
  63. template <class T, class A>
  64. std::size_t hash_value(std::vector<T, A> const& v)
  65. {
  66. return boost::hash_range(v.begin(), v.end());
  67. }
  68. template <class T, class A>
  69. std::size_t hash_value(std::list<T, A> const& v)
  70. {
  71. return boost::hash_range(v.begin(), v.end());
  72. }
  73. template <class T, class A>
  74. std::size_t hash_value(std::deque<T, A> const& v)
  75. {
  76. return boost::hash_range(v.begin(), v.end());
  77. }
  78. template <class K, class C, class A>
  79. std::size_t hash_value(std::set<K, C, A> const& v)
  80. {
  81. return boost::hash_range(v.begin(), v.end());
  82. }
  83. template <class K, class C, class A>
  84. std::size_t hash_value(std::multiset<K, C, A> const& v)
  85. {
  86. return boost::hash_range(v.begin(), v.end());
  87. }
  88. template <class K, class T, class C, class A>
  89. std::size_t hash_value(std::map<K, T, C, A> const& v)
  90. {
  91. return boost::hash_range(v.begin(), v.end());
  92. }
  93. template <class K, class T, class C, class A>
  94. std::size_t hash_value(std::multimap<K, T, C, A> const& v)
  95. {
  96. return boost::hash_range(v.begin(), v.end());
  97. }
  98. template <class T>
  99. std::size_t hash_value(std::complex<T> const& v)
  100. {
  101. boost::hash<T> hasher;
  102. std::size_t seed = hasher(v.imag());
  103. seed ^= hasher(v.real()) + (seed<<6) + (seed>>2);
  104. return seed;
  105. }
  106. #if !defined(BOOST_NO_CXX11_HDR_ARRAY)
  107. template <class T, std::size_t N>
  108. std::size_t hash_value(std::array<T, N> const& v)
  109. {
  110. return boost::hash_range(v.begin(), v.end());
  111. }
  112. #endif
  113. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
  114. namespace hash_detail {
  115. template <std::size_t I, typename T>
  116. inline typename boost::enable_if_c<(I == std::tuple_size<T>::value),
  117. void>::type
  118. hash_combine_tuple(std::size_t&, T const&)
  119. {
  120. }
  121. template <std::size_t I, typename T>
  122. inline typename boost::enable_if_c<(I < std::tuple_size<T>::value),
  123. void>::type
  124. hash_combine_tuple(std::size_t& seed, T const& v)
  125. {
  126. boost::hash_combine(seed, std::get<I>(v));
  127. boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
  128. }
  129. template <typename T>
  130. inline std::size_t hash_tuple(T const& v)
  131. {
  132. std::size_t seed = 0;
  133. boost::hash_detail::hash_combine_tuple<0>(seed, v);
  134. return seed;
  135. }
  136. }
  137. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  138. template <typename... T>
  139. inline std::size_t hash_value(std::tuple<T...> const& v)
  140. {
  141. return boost::hash_detail::hash_tuple(v);
  142. }
  143. #else
  144. inline std::size_t hash_value(std::tuple<> const& v)
  145. {
  146. return boost::hash_detail::hash_tuple(v);
  147. }
  148. # define BOOST_HASH_TUPLE_F(z, n, _) \
  149. template< \
  150. BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
  151. > \
  152. inline std::size_t hash_value(std::tuple< \
  153. BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
  154. > const& v) \
  155. { \
  156. return boost::hash_detail::hash_tuple(v); \
  157. }
  158. BOOST_PP_REPEAT_FROM_TO(1, 11, BOOST_HASH_TUPLE_F, _)
  159. # undef BOOST_HASH_TUPLE_F
  160. #endif
  161. #endif
  162. #if !defined(BOOST_NO_CXX11_SMART_PTR)
  163. template <typename T>
  164. inline std::size_t hash_value(std::shared_ptr<T> const& x) {
  165. return boost::hash_value(x.get());
  166. }
  167. template <typename T, typename Deleter>
  168. inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) {
  169. return boost::hash_value(x.get());
  170. }
  171. #endif
  172. //
  173. // call_hash_impl
  174. //
  175. // On compilers without function template ordering, this deals with arrays.
  176. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  177. namespace hash_detail
  178. {
  179. template <bool IsArray>
  180. struct call_hash_impl
  181. {
  182. template <class T>
  183. struct inner
  184. {
  185. static std::size_t call(T const& v)
  186. {
  187. using namespace boost;
  188. return hash_value(v);
  189. }
  190. };
  191. };
  192. template <>
  193. struct call_hash_impl<true>
  194. {
  195. template <class Array>
  196. struct inner
  197. {
  198. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  199. static std::size_t call(Array const& v)
  200. #else
  201. static std::size_t call(Array& v)
  202. #endif
  203. {
  204. const int size = sizeof(v) / sizeof(*v);
  205. return boost::hash_range(v, v + size);
  206. }
  207. };
  208. };
  209. template <class T>
  210. struct call_hash
  211. : public call_hash_impl<boost::is_array<T>::value>
  212. ::BOOST_NESTED_TEMPLATE inner<T>
  213. {
  214. };
  215. }
  216. #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  217. //
  218. // boost::hash
  219. //
  220. #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  221. template <class T> struct hash
  222. : std::unary_function<T, std::size_t>
  223. {
  224. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  225. std::size_t operator()(T const& val) const
  226. {
  227. return hash_value(val);
  228. }
  229. #else
  230. std::size_t operator()(T const& val) const
  231. {
  232. return hash_detail::call_hash<T>::call(val);
  233. }
  234. #endif
  235. };
  236. #if BOOST_WORKAROUND(__DMC__, <= 0x848)
  237. template <class T, unsigned int n> struct hash<T[n]>
  238. : std::unary_function<T[n], std::size_t>
  239. {
  240. std::size_t operator()(const T* val) const
  241. {
  242. return boost::hash_range(val, val+n);
  243. }
  244. };
  245. #endif
  246. #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  247. // On compilers without partial specialization, boost::hash<T>
  248. // has already been declared to deal with pointers, so just
  249. // need to supply the non-pointer version of hash_impl.
  250. namespace hash_detail
  251. {
  252. template <bool IsPointer>
  253. struct hash_impl;
  254. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  255. template <>
  256. struct hash_impl<false>
  257. {
  258. template <class T>
  259. struct inner
  260. : std::unary_function<T, std::size_t>
  261. {
  262. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  263. std::size_t operator()(T const& val) const
  264. {
  265. return hash_value(val);
  266. }
  267. #else
  268. std::size_t operator()(T const& val) const
  269. {
  270. return hash_detail::call_hash<T>::call(val);
  271. }
  272. #endif
  273. };
  274. };
  275. #else // Visual C++ 6.5
  276. // Visual C++ 6.5 has problems with nested member functions and
  277. // applying const to const types in templates. So we get this:
  278. template <bool IsConst>
  279. struct hash_impl_msvc
  280. {
  281. template <class T>
  282. struct inner
  283. : public std::unary_function<T, std::size_t>
  284. {
  285. std::size_t operator()(T const& val) const
  286. {
  287. return hash_detail::call_hash<T const>::call(val);
  288. }
  289. std::size_t operator()(T& val) const
  290. {
  291. return hash_detail::call_hash<T>::call(val);
  292. }
  293. };
  294. };
  295. template <>
  296. struct hash_impl_msvc<true>
  297. {
  298. template <class T>
  299. struct inner
  300. : public std::unary_function<T, std::size_t>
  301. {
  302. std::size_t operator()(T& val) const
  303. {
  304. return hash_detail::call_hash<T>::call(val);
  305. }
  306. };
  307. };
  308. template <class T>
  309. struct hash_impl_msvc2
  310. : public hash_impl_msvc<boost::is_const<T>::value>
  311. ::BOOST_NESTED_TEMPLATE inner<T> {};
  312. template <>
  313. struct hash_impl<false>
  314. {
  315. template <class T>
  316. struct inner : public hash_impl_msvc2<T> {};
  317. };
  318. #endif // Visual C++ 6.5
  319. }
  320. #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  321. }
  322. #endif