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