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 #include <memory> 35 36 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 37 #include <boost/type_traits/is_array.hpp> 38 #endif 39 40 namespace boost 41 { 42 template <class A, class B> 43 std::size_t hash_value(std::pair<A, B> const&); 44 template <class T, class A> 45 std::size_t hash_value(std::vector<T, A> const&); 46 template <class T, class A> 47 std::size_t hash_value(std::list<T, A> const& v); 48 template <class T, class A> 49 std::size_t hash_value(std::deque<T, A> const& v); 50 template <class K, class C, class A> 51 std::size_t hash_value(std::set<K, C, A> const& v); 52 template <class K, class C, class A> 53 std::size_t hash_value(std::multiset<K, C, A> const& v); 54 template <class K, class T, class C, class A> 55 std::size_t hash_value(std::map<K, T, C, A> const& v); 56 template <class K, class T, class C, class A> 57 std::size_t hash_value(std::multimap<K, T, C, A> const& v); 58 59 template <class T> 60 std::size_t hash_value(std::complex<T> const&); 61 62 template <class A, class B> hash_value(std::pair<A,B> const & v)63 std::size_t hash_value(std::pair<A, B> const& v) 64 { 65 std::size_t seed = 0; 66 boost::hash_combine(seed, v.first); 67 boost::hash_combine(seed, v.second); 68 return seed; 69 } 70 71 template <class T, class A> hash_value(std::vector<T,A> const & v)72 std::size_t hash_value(std::vector<T, A> const& v) 73 { 74 return boost::hash_range(v.begin(), v.end()); 75 } 76 77 template <class T, class A> hash_value(std::list<T,A> const & v)78 std::size_t hash_value(std::list<T, A> const& v) 79 { 80 return boost::hash_range(v.begin(), v.end()); 81 } 82 83 template <class T, class A> hash_value(std::deque<T,A> const & v)84 std::size_t hash_value(std::deque<T, A> const& v) 85 { 86 return boost::hash_range(v.begin(), v.end()); 87 } 88 89 template <class K, class C, class A> hash_value(std::set<K,C,A> const & v)90 std::size_t hash_value(std::set<K, C, A> const& v) 91 { 92 return boost::hash_range(v.begin(), v.end()); 93 } 94 95 template <class K, class C, class A> hash_value(std::multiset<K,C,A> const & v)96 std::size_t hash_value(std::multiset<K, C, A> const& v) 97 { 98 return boost::hash_range(v.begin(), v.end()); 99 } 100 101 template <class K, class T, class C, class A> hash_value(std::map<K,T,C,A> const & v)102 std::size_t hash_value(std::map<K, T, C, A> const& v) 103 { 104 return boost::hash_range(v.begin(), v.end()); 105 } 106 107 template <class K, class T, class C, class A> hash_value(std::multimap<K,T,C,A> const & v)108 std::size_t hash_value(std::multimap<K, T, C, A> const& v) 109 { 110 return boost::hash_range(v.begin(), v.end()); 111 } 112 113 template <class T> hash_value(std::complex<T> const & v)114 std::size_t hash_value(std::complex<T> const& v) 115 { 116 boost::hash<T> hasher; 117 std::size_t seed = hasher(v.imag()); 118 seed ^= hasher(v.real()) + (seed<<6) + (seed>>2); 119 return seed; 120 } 121 122 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) 123 template <class T, std::size_t N> hash_value(std::array<T,N> const & v)124 std::size_t hash_value(std::array<T, N> const& v) 125 { 126 return boost::hash_range(v.begin(), v.end()); 127 } 128 #endif 129 130 #if !defined(BOOST_NO_CXX11_HDR_TUPLE) 131 namespace hash_detail { 132 template <std::size_t I, typename T> 133 inline typename boost::enable_if_c<(I == std::tuple_size<T>::value), 134 void>::type hash_combine_tuple(std::size_t &,T const &)135 hash_combine_tuple(std::size_t&, T const&) 136 { 137 } 138 139 template <std::size_t I, typename T> 140 inline typename boost::enable_if_c<(I < std::tuple_size<T>::value), 141 void>::type hash_combine_tuple(std::size_t & seed,T const & v)142 hash_combine_tuple(std::size_t& seed, T const& v) 143 { 144 boost::hash_combine(seed, std::get<I>(v)); 145 boost::hash_detail::hash_combine_tuple<I + 1>(seed, v); 146 } 147 148 template <typename T> hash_tuple(T const & v)149 inline std::size_t hash_tuple(T const& v) 150 { 151 std::size_t seed = 0; 152 boost::hash_detail::hash_combine_tuple<0>(seed, v); 153 return seed; 154 } 155 } 156 157 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 158 template <typename... T> hash_value(std::tuple<T...> const & v)159 inline std::size_t hash_value(std::tuple<T...> const& v) 160 { 161 return boost::hash_detail::hash_tuple(v); 162 } 163 #else 164 hash_value(std::tuple<> const & v)165 inline std::size_t hash_value(std::tuple<> const& v) 166 { 167 return boost::hash_detail::hash_tuple(v); 168 } 169 170 template<typename A0> hash_value(std::tuple<A0> const & v)171 inline std::size_t hash_value(std::tuple<A0> const& v) 172 { 173 return boost::hash_detail::hash_tuple(v); 174 } 175 176 template<typename A0, typename A1> hash_value(std::tuple<A0,A1> const & v)177 inline std::size_t hash_value(std::tuple<A0, A1> const& v) 178 { 179 return boost::hash_detail::hash_tuple(v); 180 } 181 182 template<typename A0, typename A1, typename A2> hash_value(std::tuple<A0,A1,A2> const & v)183 inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v) 184 { 185 return boost::hash_detail::hash_tuple(v); 186 } 187 188 template<typename A0, typename A1, typename A2, typename A3> hash_value(std::tuple<A0,A1,A2,A3> const & v)189 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v) 190 { 191 return boost::hash_detail::hash_tuple(v); 192 } 193 194 template<typename A0, typename A1, typename A2, typename A3, typename A4> hash_value(std::tuple<A0,A1,A2,A3,A4> const & v)195 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v) 196 { 197 return boost::hash_detail::hash_tuple(v); 198 } 199 200 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)201 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v) 202 { 203 return boost::hash_detail::hash_tuple(v); 204 } 205 206 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)207 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v) 208 { 209 return boost::hash_detail::hash_tuple(v); 210 } 211 212 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)213 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v) 214 { 215 return boost::hash_detail::hash_tuple(v); 216 } 217 218 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)219 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v) 220 { 221 return boost::hash_detail::hash_tuple(v); 222 } 223 224 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)225 inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v) 226 { 227 return boost::hash_detail::hash_tuple(v); 228 } 229 230 #endif 231 232 #endif 233 234 #if !defined(BOOST_NO_CXX11_SMART_PTR) 235 template <typename T> hash_value(std::shared_ptr<T> const & x)236 inline std::size_t hash_value(std::shared_ptr<T> const& x) { 237 return boost::hash_value(x.get()); 238 } 239 240 template <typename T, typename Deleter> hash_value(std::unique_ptr<T,Deleter> const & x)241 inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) { 242 return boost::hash_value(x.get()); 243 } 244 #endif 245 246 // 247 // call_hash_impl 248 // 249 250 // On compilers without function template ordering, this deals with arrays. 251 252 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 253 namespace hash_detail 254 { 255 template <bool IsArray> 256 struct call_hash_impl 257 { 258 template <class T> 259 struct inner 260 { callboost::hash_detail::call_hash_impl::inner261 static std::size_t call(T const& v) 262 { 263 using namespace boost; 264 return hash_value(v); 265 } 266 }; 267 }; 268 269 template <> 270 struct call_hash_impl<true> 271 { 272 template <class Array> 273 struct inner 274 { callboost::hash_detail::call_hash_impl::inner275 static std::size_t call(Array const& v) 276 { 277 const int size = sizeof(v) / sizeof(*v); 278 return boost::hash_range(v, v + size); 279 } 280 }; 281 }; 282 283 template <class T> 284 struct call_hash 285 : public call_hash_impl<boost::is_array<T>::value> 286 ::BOOST_NESTED_TEMPLATE inner<T> 287 { 288 }; 289 } 290 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 291 292 // 293 // boost::hash 294 // 295 296 297 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) 298 299 template <class T> struct hash 300 : boost::hash_detail::hash_base<T> 301 { 302 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) operator ()boost::hash303 std::size_t operator()(T const& val) const 304 { 305 return hash_value(val); 306 } 307 #else 308 std::size_t operator()(T const& val) const 309 { 310 return hash_detail::call_hash<T>::call(val); 311 } 312 #endif 313 }; 314 315 #if BOOST_WORKAROUND(__DMC__, <= 0x848) 316 template <class T, unsigned int n> struct hash<T[n]> 317 : boost::hash_detail::hash_base<T[n]> 318 { operator ()boost::hash319 std::size_t operator()(const T* val) const 320 { 321 return boost::hash_range(val, val+n); 322 } 323 }; 324 #endif 325 326 #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 327 328 // On compilers without partial specialization, boost::hash<T> 329 // has already been declared to deal with pointers, so just 330 // need to supply the non-pointer version of hash_impl. 331 332 namespace hash_detail 333 { 334 template <bool IsPointer> 335 struct hash_impl; 336 337 template <> 338 struct hash_impl<false> 339 { 340 template <class T> 341 struct inner 342 : boost::hash_detail::hash_base<T> 343 { 344 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) operator ()boost::hash_detail::hash_impl::inner345 std::size_t operator()(T const& val) const 346 { 347 return hash_value(val); 348 } 349 #else 350 std::size_t operator()(T const& val) const 351 { 352 return hash_detail::call_hash<T>::call(val); 353 } 354 #endif 355 }; 356 }; 357 } 358 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 359 } 360 361 #endif 362