1 2 // Copyright 2005-2009 Daniel James. 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 // Based on Peter Dimov's proposal 7 // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf 8 // issue 6.18. 9 10 // This implements the extensions to the standard. 11 // It's undocumented, so you shouldn't use it.... 12 13 #if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) 14 #define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP 15 16 #include <boost/config.hpp> 17 #if defined(BOOST_HAS_PRAGMA_ONCE) 18 #pragma once 19 #endif 20 21 #include <boost/container_hash/hash.hpp> 22 #include <boost/detail/container_fwd.hpp> 23 #include <boost/core/enable_if.hpp> 24 #include <boost/static_assert.hpp> 25 26 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) 27 # include <array> 28 #endif 29 30 #if !defined(BOOST_NO_CXX11_HDR_TUPLE) 31 # include <tuple> 32 #endif 33 34 #if !defined(BOOST_NO_CXX11_HDR_MEMORY) 35 # include <memory> 36 #endif 37 38 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 39 #include <boost/type_traits/is_array.hpp> 40 #endif 41 42 namespace boost 43 { 44 template <class A, class B> 45 std::size_t hash_value(std::pair<A, B> const&); 46 template <class T, class A> 47 std::size_t hash_value(std::vector<T, A> const&); 48 template <class T, class A> 49 std::size_t hash_value(std::list<T, A> const& v); 50 template <class T, class A> 51 std::size_t hash_value(std::deque<T, A> const& v); 52 template <class K, class C, class A> 53 std::size_t hash_value(std::set<K, C, A> const& v); 54 template <class K, class C, class A> 55 std::size_t hash_value(std::multiset<K, C, A> const& v); 56 template <class K, class T, class C, class A> 57 std::size_t hash_value(std::map<K, T, C, A> const& v); 58 template <class K, class T, class C, class A> 59 std::size_t hash_value(std::multimap<K, T, C, A> const& v); 60 61 template <class T> 62 std::size_t hash_value(std::complex<T> const&); 63 64 template <class A, class B> hash_value(std::pair<A,B> const & v)65 std::size_t hash_value(std::pair<A, B> const& v) 66 { 67 std::size_t seed = 0; 68 boost::hash_combine(seed, v.first); 69 boost::hash_combine(seed, v.second); 70 return seed; 71 } 72 73 template <class T, class A> hash_value(std::vector<T,A> const & v)74 std::size_t hash_value(std::vector<T, A> const& v) 75 { 76 return boost::hash_range(v.begin(), v.end()); 77 } 78 79 template <class T, class A> hash_value(std::list<T,A> const & v)80 std::size_t hash_value(std::list<T, A> const& v) 81 { 82 return boost::hash_range(v.begin(), v.end()); 83 } 84 85 template <class T, class A> hash_value(std::deque<T,A> const & v)86 std::size_t hash_value(std::deque<T, A> const& v) 87 { 88 return boost::hash_range(v.begin(), v.end()); 89 } 90 91 template <class K, class C, class A> hash_value(std::set<K,C,A> const & v)92 std::size_t hash_value(std::set<K, C, A> const& v) 93 { 94 return boost::hash_range(v.begin(), v.end()); 95 } 96 97 template <class K, class C, class A> hash_value(std::multiset<K,C,A> const & v)98 std::size_t hash_value(std::multiset<K, C, A> const& v) 99 { 100 return boost::hash_range(v.begin(), v.end()); 101 } 102 103 template <class K, class T, class C, class A> hash_value(std::map<K,T,C,A> const & v)104 std::size_t hash_value(std::map<K, T, C, A> const& v) 105 { 106 return boost::hash_range(v.begin(), v.end()); 107 } 108 109 template <class K, class T, class C, class A> hash_value(std::multimap<K,T,C,A> const & v)110 std::size_t hash_value(std::multimap<K, T, C, A> const& v) 111 { 112 return boost::hash_range(v.begin(), v.end()); 113 } 114 115 template <class T> hash_value(std::complex<T> const & v)116 std::size_t hash_value(std::complex<T> const& v) 117 { 118 boost::hash<T> hasher; 119 std::size_t seed = hasher(v.imag()); 120 seed ^= hasher(v.real()) + (seed<<6) + (seed>>2); 121 return seed; 122 } 123 124 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) 125 template <class T, std::size_t N> hash_value(std::array<T,N> const & v)126 std::size_t hash_value(std::array<T, N> const& v) 127 { 128 return boost::hash_range(v.begin(), v.end()); 129 } 130 #endif 131 132 #if !defined(BOOST_NO_CXX11_HDR_TUPLE) 133 namespace hash_detail { 134 template <std::size_t I, typename T> 135 inline typename boost::enable_if_c<(I == std::tuple_size<T>::value), 136 void>::type hash_combine_tuple(std::size_t &,T const &)137 hash_combine_tuple(std::size_t&, T const&) 138 { 139 } 140 141 template <std::size_t I, typename T> 142 inline typename boost::enable_if_c<(I < std::tuple_size<T>::value), 143 void>::type hash_combine_tuple(std::size_t & seed,T const & v)144 hash_combine_tuple(std::size_t& seed, T const& v) 145 { 146 boost::hash_combine(seed, std::get<I>(v)); 147 boost::hash_detail::hash_combine_tuple<I + 1>(seed, v); 148 } 149 150 template <typename T> hash_tuple(T const & v)151 inline std::size_t hash_tuple(T const& v) 152 { 153 std::size_t seed = 0; 154 boost::hash_detail::hash_combine_tuple<0>(seed, v); 155 return seed; 156 } 157 } 158 159 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 160 template <typename... T> hash_value(std::tuple<T...> const & v)161 inline std::size_t hash_value(std::tuple<T...> const& v) 162 { 163 return boost::hash_detail::hash_tuple(v); 164 } 165 #else 166 hash_value(std::tuple<> const & v)167 inline std::size_t hash_value(std::tuple<> const& v) 168 { 169 return boost::hash_detail::hash_tuple(v); 170 } 171 172 template<typename A0> hash_value(std::tuple<A0> const & v)173 inline std::size_t hash_value(std::tuple<A0> const& v) 174 { 175 return boost::hash_detail::hash_tuple(v); 176 } 177 178 template<typename A0, typename A1> hash_value(std::tuple<A0,A1> const & v)179 inline std::size_t hash_value(std::tuple<A0, A1> const& v) 180 { 181 return boost::hash_detail::hash_tuple(v); 182 } 183 184 template<typename A0, typename A1, typename A2> hash_value(std::tuple<A0,A1,A2> const & v)185 inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v) 186 { 187 return boost::hash_detail::hash_tuple(v); 188 } 189 190 template<typename A0, typename A1, typename A2, typename A3> hash_value(std::tuple<A0,A1,A2,A3> const & v)191 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v) 192 { 193 return boost::hash_detail::hash_tuple(v); 194 } 195 196 template<typename A0, typename A1, typename A2, typename A3, typename A4> hash_value(std::tuple<A0,A1,A2,A3,A4> const & v)197 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v) 198 { 199 return boost::hash_detail::hash_tuple(v); 200 } 201 202 template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> hash_value(std::tuple<A0,A1,A2,A3,A4,A5> const & v)203 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v) 204 { 205 return boost::hash_detail::hash_tuple(v); 206 } 207 208 template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> hash_value(std::tuple<A0,A1,A2,A3,A4,A5,A6> const & v)209 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v) 210 { 211 return boost::hash_detail::hash_tuple(v); 212 } 213 214 template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> hash_value(std::tuple<A0,A1,A2,A3,A4,A5,A6,A7> const & v)215 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v) 216 { 217 return boost::hash_detail::hash_tuple(v); 218 } 219 220 template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> hash_value(std::tuple<A0,A1,A2,A3,A4,A5,A6,A7,A8> const & v)221 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v) 222 { 223 return boost::hash_detail::hash_tuple(v); 224 } 225 226 template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> hash_value(std::tuple<A0,A1,A2,A3,A4,A5,A6,A7,A8,A9> const & v)227 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v) 228 { 229 return boost::hash_detail::hash_tuple(v); 230 } 231 232 #endif 233 234 #endif 235 236 #if !defined(BOOST_NO_CXX11_SMART_PTR) 237 template <typename T> hash_value(std::shared_ptr<T> const & x)238 inline std::size_t hash_value(std::shared_ptr<T> const& x) { 239 return boost::hash_value(x.get()); 240 } 241 242 template <typename T, typename Deleter> hash_value(std::unique_ptr<T,Deleter> const & x)243 inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) { 244 return boost::hash_value(x.get()); 245 } 246 #endif 247 248 // 249 // call_hash_impl 250 // 251 252 // On compilers without function template ordering, this deals with arrays. 253 254 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 255 namespace hash_detail 256 { 257 template <bool IsArray> 258 struct call_hash_impl 259 { 260 template <class T> 261 struct inner 262 { callboost::hash_detail::call_hash_impl::inner263 static std::size_t call(T const& v) 264 { 265 using namespace boost; 266 return hash_value(v); 267 } 268 }; 269 }; 270 271 template <> 272 struct call_hash_impl<true> 273 { 274 template <class Array> 275 struct inner 276 { callboost::hash_detail::call_hash_impl::inner277 static std::size_t call(Array const& v) 278 { 279 const int size = sizeof(v) / sizeof(*v); 280 return boost::hash_range(v, v + size); 281 } 282 }; 283 }; 284 285 template <class T> 286 struct call_hash 287 : public call_hash_impl<boost::is_array<T>::value> 288 ::BOOST_NESTED_TEMPLATE inner<T> 289 { 290 }; 291 } 292 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 293 294 // 295 // boost::hash 296 // 297 298 299 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) 300 301 template <class T> struct hash 302 : boost::hash_detail::hash_base<T> 303 { 304 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) operator ()boost::hash305 std::size_t operator()(T const& val) const 306 { 307 return hash_value(val); 308 } 309 #else 310 std::size_t operator()(T const& val) const 311 { 312 return hash_detail::call_hash<T>::call(val); 313 } 314 #endif 315 }; 316 317 #if BOOST_WORKAROUND(__DMC__, <= 0x848) 318 template <class T, unsigned int n> struct hash<T[n]> 319 : boost::hash_detail::hash_base<T[n]> 320 { operator ()boost::hash321 std::size_t operator()(const T* val) const 322 { 323 return boost::hash_range(val, val+n); 324 } 325 }; 326 #endif 327 328 #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 329 330 // On compilers without partial specialization, boost::hash<T> 331 // has already been declared to deal with pointers, so just 332 // need to supply the non-pointer version of hash_impl. 333 334 namespace hash_detail 335 { 336 template <bool IsPointer> 337 struct hash_impl; 338 339 template <> 340 struct hash_impl<false> 341 { 342 template <class T> 343 struct inner 344 : boost::hash_detail::hash_base<T> 345 { 346 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) operator ()boost::hash_detail::hash_impl::inner347 std::size_t operator()(T const& val) const 348 { 349 return hash_value(val); 350 } 351 #else 352 std::size_t operator()(T const& val) const 353 { 354 return hash_detail::call_hash<T>::call(val); 355 } 356 #endif 357 }; 358 }; 359 } 360 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 361 } 362 363 #endif 364