diff --git a/hash/doc/Jamfile.v2 b/hash/doc/Jamfile.v2 new file mode 100644 index 0000000..7f55cd5 --- /dev/null +++ b/hash/doc/Jamfile.v2 @@ -0,0 +1,9 @@ + +# Copyright Daniel James 2005. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using quickbook ; + +xml hash : hash.qbk ; +boostbook standalone : hash ; diff --git a/hash/doc/hash.qbk b/hash/doc/hash.qbk new file mode 100644 index 0000000..bc5e9a9 --- /dev/null +++ b/hash/doc/hash.qbk @@ -0,0 +1,769 @@ +[library Boost.Hash + [authors [James, Daniel]] + [copyright 2005 Daniel James] + [purpose std::tr1 compliant hash function object] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + + http://www.boost.org/LICENSE_1_0.txt + ) + ] +] + +[/ QuickBook Document version 1.0 ] +[/ Feb 8, 2005 ] + +[def __note__ [$images/note.png]] +[def __alert__ [$images/alert.png]] +[def __tip__ [$images/tip.png]] + +[section:intro Introduction] + +[def __tr1__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf + C++ Standard Library Technical Report]] +[def __tr1-short__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf + Technical Report]] +[def __multi-index__ [@../../libs/multi_index/doc/index.html + Boost Multi-Index Containers Library]] +[def __multi-index-short__ [@../../libs/multi_index/doc/index.html + Boost.MultiIndex]] +[def __issues__ [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf + Library Extension Technical Report Issues List]] +[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function hash function]] +[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table hash table]] + +[classref boost::hash] is an implementation of the __hash-function__ object +specified by the __tr1__. It is intended for use as the default hash function +for unordered associative containers, and the __multi-index__'s hash indexes. + +As it is compliant with the __tr1-short__, it will work with: + +* integers +* floats +* pointers +* strings + +It also implements the extension proposed by Peter Dimov in issue 6.18 of the +__issues__, this adds support for: + +* `std::pair` +* the standard containers. + +The extension also allows the user to customise the hash function for +user-defined types. Which means that you don't need to use a custom hash +function object with a container that uses [classref boost::hash] by default. + +[endsect] + +[section:tutorial Tutorial] + +When using __multi-index-short__, you don't need to do anything, as it uses +[classref boost::hash] by default. To find out how to use a user-defined type, +read the [link section.tutorial.custom section on Extending Boost.Hash]. + +If your standard library supplies its own implementation of the unordered +associative containers and you wish to use +[classref boost::hash] you just supply the extra template parameter: + + std::unordered_multiset, boost::hash > + set_of_ints; + + std::unordered_set, boost::hash > + set_of_pairs; + + std::unordered_map > map_int_to_string; + +To use [classref boost::hash] directly, create an instance and call it as a function: + + #include + + int main() + { + boost::hash string_hash; + + std::size_t h = string_hash("Hash me"); + } + +If you wish to make use of the extensions, you will need to include the +appropriate header (see the +[link hash.reference.specification reference documentation] for the full list). + + #include + + int main() + { + boost::hash > pair_hash; + + std::size_t h = pair_hash(std::make_pair(1, 2)); + } + +Or alternatively, include `` for the full library. + +For an example of generic use, here is a function to generate a vector +containing the hashes of the elements of a container: + + template + std::vector get_hashes(Container const& x) + { + std::vector hashes; + std::transform(x.begin(), x.end(), std::insert_iterator(hashes), + boost::hash()); + + return hashes; + } + +[section:custom Extending Boost.Hash for a custom data type] + +[classref boost::hash] is implemented by calling the function +[funcref boost::hash_value hash_value]. +The namespace isn't specified so that it can detect overloads via argument +dependant lookup. So if there is a free function `hash_value` in the same +namespace as a custom type, it will get called. + +If you have a structure `library::book`, where each `book` is uniquely +defined by it's member `id`: + + namespace library + { + struct book + { + int id; + std::string author; + std::string title; + + // .... + }; + + bool operator==(book const& a, book const& b) + { + return a.id == b.id; + } + } + +Then all you would need to do is write the function `library::hash_value`: + + namespace library + { + std::size_t hash_value(book const& b) + { + return boost::hash_value(b.id); + } + } + +And you can now use [classref boost::hash] with book: + + library::book knife(3458, "Zane Grey", "The Hash Knife Outfit"); + library::book dandelion(1354, "Paul J. Shanley", + "Hash & Dandelion Greens"); + + boost::hash book_hasher; + std::size_t knife_hash_value = book_hasher(knife); + + boost::unordered_set books; + books.insert(knife); + books.insert(library::book(2443, "Lindgren, Torgny", "Hash")); + books.insert(library::book(1953, "Snyder, Bernadette M.", + "Heavenly Hash: A Tasty Mix of a Mother's Meditations")); + + assert(books.find(knife) != books.end()); + assert(books.find(dandelion) == books.end()); + +Full code for this example is at +[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.cpp]. + +[blurb +When writing a hash function, first look at how the equality function works. +Objects that are equal must generate the same hash value. +When objects are not equal the should generate different hash values. +In this object equality was based just on the id, if it was based +on the objects name and author the hash function should take them into account +(how to do this is discussed in the next section). +] + + +[endsect] + +[section:combine Combining hash values] + +Say you have a point class, representing a two dimensional location: + + class point + { + int x; + int y; + public: + point() : x(0), y(0) {} + point(int x, int y) : x(x), y(y) {} + + bool operator==(point const& other) const + { + return x = other.x && y == other.y; + } + }; + +and you wish to use it as the key for an `unordered_map`. You need to +customise the hash for this structure. To do this we need to combine +the hash values for `x` and `y`. Boost.Hash supplies the function +[funcref boost::hash_combine] for this purpose: + + class point + { + ... + + friend std::size_t hash_value(point const& p) + { + std::size_t seed = 0; + boost::hash_combine(seed, p.x); + boost::hash_combine(seed, p.y); + + return seed; + } + + ... + }; + +Calls to hash_combine incrementally build the hash from the different members +of point, it can be repeatedly called for any number of elements. It calls +[funcref boost::hash_value hash_value] on the supplied element, and combines +it with the seed. + +Full code for this example is at +[@../../libs/functional/hash/examples/point.cpp /libs/functional/hash/examples/point.cpp]. + +[blurb +''' +When using boost::hash_combine the order of the +calls matters. + + std::size_t seed = 0; + boost::hash_combine(seed, 1); + boost::hash_combine(seed, 2); + +results in a different seed to: + + std::size_t seed = 0; + boost::hash_combine(seed, 2); + boost::hash_combine(seed, 1); + +If you are calculating a hash value for data where the order of the data +doesn't matter in comparisons (e.g. a set) you will have to ensure that the +data is always supplied in the same order. +''' +] + +To calculate the hash of an iterator range you can use +[funcref boost::hash_range]: + + std::vector some_strings; + std::size_t hash = boost::hash_range(some_strings.begin(), some_strings.end()); + +[endsect] + +[endsect] + +[section:portability Portability] + +Boost.Hash is written to be as portable as possible, but unfortunately, several +older compilers don't support argument dependent lookup (ADL) - the mechanism +used for customization. On those compilers custom overloads for hash_value +need to be declared in the boost namespace. + +On a strictly standards compliant compiler, an overload defined in the +boost namespace won't be found when [classref boost::hash] is instantiated, +so for these compilers the overload should only be declared in the same +namespace as the class. + +Let's say we have a simple custom type: + + namespace foo + { + struct custom_type + { + int value; + + friend inline std::size_t hash_value(custom_type x) + { + boost::hash hasher; + return hasher(x.value); + } + }; + } + +On a compliant compiler, when `hash_value` is called for this type, +it will look at the namespace inside the type and find `hash_value` +but on a compiler which doesn't support ADL `hash_value` won't be found. + +So on these compilers define a member function: + + #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + friend inline std::size_t hash_value(custom_type x) + { + boost::hash hasher; + return hasher(x.value); + } + #else + std::size_t hash() const + { + boost::hash hasher; + return hasher(value); + } + #endif + +which will be called from the `boost` namespace: + + #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + namespace boost + { + std::size_t hash_value(foo::custom_type x) + { + return x.hash(); + } + } + #endif + +Full code for this example is at +[@../../libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp]. + +[endsect] + +[/ Quickbook insists on putting a paragraph around the escaped code, which +messes up the library section, so I wrap it in another section. This is no good, +but there you go. ] + +[section:reference_ Reference] +''' + +
+ For the full specification, see section 6.3 of the + C++ Standard Library Technical Report + and issue 6.18 of the + Library Extension Technical Report Issues List. + +
+
+ Includes all the following headers. +
+
+ + Defines boost::hash, + the implementation for built in types and + std::string and customisation functions. + + + + + + + + + + + std::unary_function<T, std::size_t> + + + An STL compliant hash function object. + + + std::size_t + + T const& + + + hash_value(val) + + + The call to hash_value + is always unqualified, so that custom overloads can be + found via argument dependent lookup. + + + Only throws if + hash_value(T) throws. + + + + + + + + + + Implementation of a hash function for various types. + + + + Should never be called directly by users, instead they should use + boost::hash, boost::hash_range + or boost::hash_combine which + call hash_value without namespace qualification so that overloads + for custom types are found via ADL. + + + Overloads for other types supplied in other headers. + This is an extension to TR1 + + + + std::size_t + int + + + + std::size_t + unsigned int + + + + std::size_t + long + + + + std::size_t + unsigned long + + + + std::size_t + float + + + + std::size_t + double + + + + std::size_t + long double + + + + + std::size_t + T* + + + + + std::size_t + + std::basic_string<Ch, std::char_traits<Ch>, A> const& + + + + + + + + + + int, unsigned int, long, unsigned long + v + + + float, double, long double, T* + + An unspecified value, except that equal arguments shall yield the same + result + + + + std::basic_string<Ch, std::char_traits<Ch>, A> const& + hash_range(v.begin(), v.end()); + + + + + + + + + + + + + + void + size_t & + T const & + + Called repeatedly to incrementally create a hash value from + several variables. + + seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + + hash_value is called without + qualification, so that overloads can be found via ADL. + This is an extension to TR1 + + + Only throws if hash_value(T) throws. + Strong exception safety, as long as hash_value(T) + also has strong exception safety. + + + + + + + + + std::size_t + It + It + + + + + void + std::size_t& + It + It + + + + Calculate the combined hash value of the elements of an iterator + range. + + +size_t seed = 0; + +for(; first != last; ++first) +{ + hash_combine(seed, *first); +} + +return seed; + + + + hash_range is sensitive to the order of the elements + so it wouldn't be appropriate to use this with an unordered + container. + + This is an extension to TR1 + + + Only throws if hash_value(std::iterator_traits<It>::value_type) + throws. hash_range(std::size_t&, It, It) has basic exception safety as long as + hash_value(std::iterator_traits<It>::value_type) + has basic exception safety. + + + +
+ +
+ + Hash implementation for std::pair. + + + + + + std::size_t + std::pair<A, B> const & + + +size_t seed = 0; +hash_combine(seed, val.first); +hash_combine(seed, val.second); +return seed; + + + Only throws if hash_value(A) + or hash_value(B) throws. + + This is an extension to TR1 + + +
+ +
+ + Hash implementation for std::vector. + + + + + + std::size_t + std::vector<T, A> const & + + + hash_range(val.begin(), val.end()); + + + Only throws if hash_value(T) throws. + + This is an extension to TR1 + + +
+ +
+ + Hash implementation for std::list. + + + + + + std::size_t + std::list<T, A> const & + + + hash_range(val.begin(), val.end()); + + + Only throws if hash_value(T) throws. + + This is an extension to TR1 + + +
+ +
+ + Hash implementation for std::deque. + + + + + + std::size_t + std::deque<T, A> const & + + + hash_range(val.begin(), val.end()); + + + Only throws if hash_value(T) throws. + + This is an extension to TR1 + + +
+ +
+ + Hash implementation for std::set and std::multiset. + + + + + + std::size_t + std::set<K, C, A> const & + + + + + std::size_t + std::multiset<K, C, A> const & + + + hash_range(val.begin(), val.end()); + + + Only throws if hash_value(T) throws. + + This is an extension to TR1 + + +
+ +
+ + Hash implementation for std::map and std::multimap. + + + + + + std::size_t + std::map<K, T, C, A> const & + + + + + std::size_t + std::multimap<K, T, C, A> const & + + + hash_range(val.begin(), val.end()); + + + Only throws if + hash_value(std::pair<K const, T>) + throws. + + This is an extension to TR1 + + +
+
+''' +[/ Remove this comment and everything goes wrong! ;) ] +[endsect] + +[section:acknowledgements Acknowledgements] + +This library is based on the design by Peter Dimov. During the inital development +Joaquín M López Muñoz made many useful suggestions and contributed fixes. + +The original implementation came from Jeremy B. Maitin-Shepard's hash table +library, although this is a complete rewrite. + +[endsect]