Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

updated boost from 1_33_1 to 1_34_1

File size: 6.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[def __multi-index-short__ [@../../libs/multi_index/doc/index.html
7    Boost.MultiIndex]]
8
9[section:tutorial Tutorial]
10
11When using a hash index with __multi-index-short__, you don't need to do
12anything to use [classref boost::hash] as it uses it by default.
13To find out how to use a user-defined type, read the
14[link hash.custom section on extending boost::hash for a custom data type].
15
16If your standard library supplies its own implementation of the unordered
17associative containers and you wish to use
18[classref boost::hash], just use an extra template parameter:
19
20    std::unordered_multiset<int, ``[classref boost::hash]``<int> >
21            set_of_ints;
22
23    std::unordered_set<std::pair<int, int>, ``[classref boost::hash]``<std::pair<int, int> >
24            set_of_pairs;
25
26    std::unordered_map<int, std::string, ``[classref boost::hash]``<int> > map_int_to_string;
27
28To use [classref boost::hash] directly, create an instance and call it as a function:
29
30    #include <``[headerref boost/functional/hash.hpp]``>
31
32    int main()
33    {
34        ``[classref boost::hash]``<std::string> string_hash;
35
36        std::size_t h = string_hash("Hash me");
37    }
38
39For an example of generic use, here is a function to generate a vector
40containing the hashes of the elements of a container:
41
42    template <class Container>
43    std::vector<std::size_t> get_hashes(Container const& x)
44    {
45        std::vector<std::size_t> hashes;
46        std::transform(x.begin(), x.end(), std::insert_iterator(hashes),
47            ``[classref boost::hash]``<typename Container::value_type>());
48
49        return hashes;
50    }
51
52[endsect]
53
54[section:custom Extending boost::hash for a custom data type]
55
56[classref boost::hash] is implemented by calling the function
57[funcref boost::hash_value hash_value].
58The namespace isn't specified so that it can detect overloads via argument
59dependant lookup. So if there is a free function `hash_value` in the same
60namespace as a custom type, it will get called.
61
62If you have a structure `library::book`, where each `book` is uniquely
63defined by it's member `id`:
64
65    namespace library
66    {
67        struct book
68        {
69            int id;
70            std::string author;
71            std::string title;
72
73            // ....
74        };
75
76        bool operator==(book const& a, book const& b)
77        {
78            return a.id == b.id;
79        }
80    }
81
82Then all you would need to do is write the function `library::hash_value`:
83
84    namespace library
85    {
86        std::size_t hash_value(book const& b)
87        {
88            ``[classref boost::hash]``<int> hasher;
89            return hasher(b.id);
90        }
91    }
92
93And you can now use [classref boost::hash] with book:
94
95    library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
96    library::book dandelion(1354, "Paul J. Shanley",
97        "Hash & Dandelion Greens");
98
99    ``[classref boost::hash]``<library::book> book_hasher;
100    std::size_t knife_hash_value = book_hasher(knife);
101
102    // If std::unordered_set is available:
103    std::unordered_set<library::book, ``[classref boost::hash]``<library::book> > books;
104    books.insert(knife);
105    books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
106    books.insert(library::book(1953, "Snyder, Bernadette M.",
107        "Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
108
109    assert(books.find(knife) != books.end());
110    assert(books.find(dandelion) == books.end());
111
112The full example can be found in:
113[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.hpp]
114and
115[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.cpp].
116
117[tip
118When writing a hash function, first look at how the equality function works.
119Objects that are equal must generate the same hash value.
120When objects are not equal they should generate different hash values.
121In this object equality was based just on the id so the hash function
122only hash the id. If it was based on the objects name and author
123then the hash function should take them into account
124(how to do this is discussed in the next section).
125]
126
127[endsect]
128
129[section:combine Combining hash values]
130
131Say you have a point class, representing a two dimensional location:
132
133    class point
134    {
135        int x;
136        int y;
137    public:
138        point() : x(0), y(0) {}
139        point(int x, int y) : x(x), y(y) {}
140
141        bool operator==(point const& other) const
142        {
143            return x == other.x && y == other.y;
144        }
145    };
146
147and you wish to use it as the key for an `unordered_map`. You need to
148customise the hash for this structure. To do this we need to combine
149the hash values for `x` and `y`. The function
150[funcref boost::hash_combine] is supplied for this purpose:
151
152    class point
153    {
154        ...
155
156        friend std::size_t hash_value(point const& p)
157        {
158            std::size_t seed = 0;
159            ``[funcref boost::hash_combine]``(seed, p.x);
160            ``[funcref boost::hash_combine]``(seed, p.y);
161
162            return seed;
163        }
164
165        ...
166    };
167
168Calls to hash_combine incrementally build the hash from the different members
169of point, it can be repeatedly called for any number of elements. It calls
170[funcref boost::hash_value hash_value] on the supplied element, and combines it with the seed.
171
172Full code for this example is at
173[@../../libs/functional/hash/examples/point.cpp /libs/functional/hash/examples/point.cpp].
174
175[note
176When using [funcref boost::hash_combine] the order of the
177calls matters.
178'''
179<programlisting>
180    std::size_t seed = 0;
181    boost::hash_combine(seed, 1);
182    boost::hash_combine(seed, 2);
183</programlisting>
184results in a different seed to:
185<programlisting>
186    std::size_t seed = 0;
187    boost::hash_combine(seed, 2);
188    boost::hash_combine(seed, 1);
189</programlisting>
190'''
191If you are calculating a hash value for data where the order of the data
192doesn't matter in comparisons (e.g. a set) you will have to ensure that the
193data is always supplied in the same order.
194]
195
196To calculate the hash of an iterator range you can use [funcref boost::hash_range]:
197
198    std::vector<std::string> some_strings;
199    std::size_t hash = ``[funcref boost::hash_range]``(some_strings.begin(), some_strings.end());
200
201[endsect]
202
Note: See TracBrowser for help on using the repository browser.