• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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