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
42namespace 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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
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>
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>
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
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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 {
263 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 {
277 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)
305 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 {
321 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)
347 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

source code of include/boost/container_hash/extensions.hpp