]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/functional/hash/doc/portability.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / functional / hash / doc / portability.qbk
1
2 [/ Copyright 2005-2008 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 [section:portability Portability]
7
8 [def __boost_hash__ [classref boost::hash]]
9
10 __boost_hash__ is written to be as portable as possible, but unfortunately, several
11 older compilers don't support argument dependent lookup (ADL) - the mechanism
12 used for customisation. On those compilers custom overloads for `hash_value`
13 needs to be declared in the boost namespace.
14
15 On a strictly standards compliant compiler, an overload defined in the
16 boost namespace won't be found when __boost_hash__ is instantiated,
17 so for these compilers the overload should only be declared in the same
18 namespace as the class.
19
20 Let's say we have a simple custom type:
21
22 namespace foo
23 {
24 template <class T>
25 class custom_type
26 {
27 T value;
28 public:
29 custom_type(T x) : value(x) {}
30
31 friend std::size_t hash_value(custom_type x)
32 {
33 __boost_hash__<int> hasher;
34 return hasher(x.value);
35 }
36 };
37 }
38
39 On a compliant compiler, when `hash_value` is called for this type,
40 it will look at the namespace inside the type and find `hash_value`
41 but on a compiler which doesn't support ADL `hash_value` won't be found.
42 To make things worse, some compilers which do support ADL won't find
43 a friend class defined inside the class.
44
45 So first move the member function out of the class:
46
47 namespace foo
48 {
49 template <class T>
50 class custom_type
51 {
52 T value;
53 public:
54 custom_type(T x) : value(x) {}
55
56 std::size_t hash(custom_type x)
57 {
58 __boost_hash__<T> hasher;
59 return hasher(value);
60 }
61 };
62
63 template <class T>
64 inline std::size_t hash_value(custom_type<T> x)
65 {
66 return x.hash();
67 }
68 }
69
70 Unfortunately, I couldn't declare hash_value as a friend, as some compilers
71 don't support template friends, so instead I declared a member function to
72 calculate the hash, and called it from hash_value.
73
74 For compilers which don't support ADL, hash_value needs to be defined in the
75 boost namespace:
76
77 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
78 namespace boost
79 #else
80 namespace foo
81 #endif
82 {
83 template <class T>
84 std::size_t hash_value(foo::custom_type<T> x)
85 {
86 return x.hash();
87 }
88 }
89
90 Full code for this example is at
91 [@boost:/libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp].
92
93 [endsect]