summaryrefslogtreecommitdiff
path: root/doc/html/hash/portability.html
blob: 48e8f104dc62f7a005bbceb67cbe0c1fdc7e18df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Portability</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../hash.html" title="Chapter&#160;10.&#160;Boost.Functional/Hash">
<link rel="prev" href="combine.html" title="Combining hash values">
<link rel="next" href="disable.html" title="Disabling The Extensions">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="combine.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../hash.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="disable.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="hash.portability"></a><a class="link" href="portability.html" title="Portability">Portability</a>
</h2></div></div></div>
<p>
      <code class="computeroutput"><a class="link" href="../boost/hash.html" title="Struct template hash">boost::hash</a></code> is written to be as portable
      as possible, but unfortunately, several older compilers don't support argument
      dependent lookup (ADL) - the mechanism used for customisation. On those compilers
      custom overloads for <code class="computeroutput"><span class="identifier">hash_value</span></code>
      needs to be declared in the boost namespace.
    </p>
<p>
      On a strictly standards compliant compiler, an overload defined in the boost
      namespace won't be found when <code class="computeroutput"><a class="link" href="../boost/hash.html" title="Struct template hash">boost::hash</a></code>
      is instantiated, so for these compilers the overload should only be declared
      in the same namespace as the class.
    </p>
<p>
      Let's say we have a simple custom type:
    </p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">foo</span>
<span class="special">{</span>
    <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
    <span class="keyword">class</span> <span class="identifier">custom_type</span>
    <span class="special">{</span>
        <span class="identifier">T</span> <span class="identifier">value</span><span class="special">;</span>
    <span class="keyword">public</span><span class="special">:</span>
        <span class="identifier">custom_type</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">value</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>

        <span class="keyword">friend</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hash_value</span><span class="special">(</span><span class="identifier">custom_type</span> <span class="identifier">x</span><span class="special">)</span>
        <span class="special">{</span>
            <code class="computeroutput"><a class="link" href="../boost/hash.html" title="Struct template hash">boost::hash</a></code><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">hasher</span><span class="special">;</span>
            <span class="keyword">return</span> <span class="identifier">hasher</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">);</span>
        <span class="special">}</span>
    <span class="special">};</span>
<span class="special">}</span>
</pre>
<p>
      On a compliant compiler, when <code class="computeroutput"><span class="identifier">hash_value</span></code>
      is called for this type, it will look at the namespace inside the type and
      find <code class="computeroutput"><span class="identifier">hash_value</span></code> but on a compiler
      which doesn't support ADL <code class="computeroutput"><span class="identifier">hash_value</span></code>
      won't be found. To make things worse, some compilers which do support ADL won't
      find a friend class defined inside the class.
    </p>
<p>
      So first move the member function out of the class:
    </p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">foo</span>
<span class="special">{</span>
    <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
    <span class="keyword">class</span> <span class="identifier">custom_type</span>
    <span class="special">{</span>
        <span class="identifier">T</span> <span class="identifier">value</span><span class="special">;</span>
    <span class="keyword">public</span><span class="special">:</span>
        <span class="identifier">custom_type</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">value</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>

        <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hash</span><span class="special">(</span><span class="identifier">custom_type</span> <span class="identifier">x</span><span class="special">)</span>
        <span class="special">{</span>
            <code class="computeroutput"><a class="link" href="../boost/hash.html" title="Struct template hash">boost::hash</a></code><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">hasher</span><span class="special">;</span>
            <span class="keyword">return</span> <span class="identifier">hasher</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
        <span class="special">}</span>
    <span class="special">};</span>

    <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
    <span class="keyword">inline</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hash_value</span><span class="special">(</span><span class="identifier">custom_type</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="keyword">return</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">hash</span><span class="special">();</span>
    <span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
      Unfortunately, I couldn't declare hash_value as a friend, as some compilers
      don't support template friends, so instead I declared a member function to
      calculate the hash, and called it from hash_value.
    </p>
<p>
      For compilers which don't support ADL, hash_value needs to be defined in the
      boost namespace:
    </p>
<pre class="programlisting"><span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP</span>
<span class="keyword">namespace</span> <span class="identifier">boost</span>
<span class="preprocessor">#else</span>
<span class="keyword">namespace</span> <span class="identifier">foo</span>
<span class="preprocessor">#endif</span>
<span class="special">{</span>
    <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hash_value</span><span class="special">(</span><span class="identifier">foo</span><span class="special">::</span><span class="identifier">custom_type</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="keyword">return</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">hash</span><span class="special">();</span>
    <span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
      Full code for this example is at <a href="../../../libs/functional/hash/examples/portable.cpp" target="_top">/libs/functional/hash/examples/portable.cpp</a>.
    </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2005-2008 Daniel
      James<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="combine.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../hash.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="disable.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>