Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/functional/hash/doc/portability.qbk @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 3.2 KB
Line 
1
2[/ Copyright 2005-2006 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
11older compilers don't support argument dependent lookup (ADL) - the mechanism
12used for customisation.  On those compilers custom overloads for `hash_value`
13need to be declared in the boost namespace.
14
15On a strictly standards compliant compiler, an overload defined in the
16boost namespace won't be found when __boost_hash__ is instantiated,
17so for these compilers the overload should only be declared in the same
18namespace as the class.
19
20Let'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
39On a compliant compiler, when `hash_value` is called for this type,
40it will look at the namespace inside the type and find `hash_value`
41but on a compiler which doesn't support ADL `hash_value` won't be found.
42To make things worse, some compilers which do support ADL won't find
43a friend class defined inside the class.
44
45So 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
70Unfortunately, I couldn't declare hash_value as a friend, as some compilers
71don't support template friends, so instead I declared a member function to
72calculate the hash, and called it from hash_value.
73
74For compilers which don't support ADL, hash_value needs to be defined in the
75boost 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
90Full code for this example is at
91[@../../libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp].
92
93[h2 Other Issues]
94
95On Visual C++ versions 6.5 and 7.0, `hash_value` isn't overloaded for built in
96arrays. __boost_hash__, [funcref boost::hash_combine] and [funcref boost::hash_range] all use a workaround to
97support built in arrays so this shouldn't be a problem in most cases.
98
99On Visual C++ versions 6.5 and 7.0, function pointers aren't currently supported.
100
101When using GCC on Solaris, `boost::hash_value(long double)` treats
102`long double`s as `double`s - so the hash function doesn't take into account the
103full range of values.
104
105[endsect]
Note: See TracBrowser for help on using the repository browser.