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