From be3a039e8854d9f140129dcda5dce86b44d392cb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 16 Feb 2006 23:10:26 +0000 Subject: [PATCH] Split the hash documentation into several files. [SVN r32973] --- hash/doc/hash.qbk | 849 +-------------------------------------- hash/doc/intro.qbk | 36 ++ hash/doc/links.qbk | 22 + hash/doc/portability.qbk | 98 +++++ hash/doc/ref.xml | 459 +++++++++++++++++++++ hash/doc/thanks.qbk | 18 + hash/doc/tutorial.qbk | 192 +++++++++ 7 files changed, 831 insertions(+), 843 deletions(-) create mode 100644 hash/doc/intro.qbk create mode 100644 hash/doc/links.qbk create mode 100644 hash/doc/portability.qbk create mode 100644 hash/doc/ref.xml create mode 100644 hash/doc/thanks.qbk create mode 100644 hash/doc/tutorial.qbk diff --git a/hash/doc/hash.qbk b/hash/doc/hash.qbk index 591af65..04b86fa 100644 --- a/hash/doc/hash.qbk +++ b/hash/doc/hash.qbk @@ -14,846 +14,9 @@ ] ] -[def __note__ [$images/note.png]] -[def __alert__ [$images/alert.png]] -[def __tip__ [$images/tip.png]] -[def __boost_hash [classref boost::hash]] -[def __hash_value [funcref boost::hash_value hash_value]] -[def __hash_combine [funcref boost::hash_combine]] -[def __hash_range [funcref boost::hash_range]] - -[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]] - -__boost_hash is an implementation of the __hash-function__ object -specified by the __tr1-short__. 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: - -* arrays -* `std::pair` -* the standard containers. -* extending __boost_hash for custom types. - -[endsect] - -[section:tutorial Tutorial] - -When using a hash index with __multi-index-short__, you don't need to do -anything to use __boost_hash as it uses it by default. -To find out how to use a user-defined type, read the -[link hash.custom section on extending boost::hash for a custom data type]. - -If your standard library supplies its own implementation of the unordered -associative containers and you wish to use -__boost_hash, just use an 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 __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"); - } - -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; - } - -[endsect] - -[section:custom Extending boost::hash for a custom data type] - -__boost_hash is implemented by calling the function __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) - { - __boost_hash hasher; - return hasher(b.id); - } - } - -And you can now use __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); - - // If std::unordered_set is available: - std::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()); - -The full example can be found in: -[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.hpp] -and -[@../../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`. The function -__hash_combine is supplied for this purpose: - - class point - { - ... - - friend std::size_t hash_value(point const& p) - { - std::size_t seed = 0; - __hash_combine(seed, p.x); - __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 -__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 __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 __hash_range: - - std::vector some_strings; - std::size_t hash = __hash_range(some_strings.begin(), some_strings.end()); - -[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 __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 - { - template - class custom_type - { - T value; - public: - custom_type(T x) : value(x) {} - - friend 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. -To make things worse, some compilers which do support ADL won't find -a friend class defined inside the class. - -So first move the member function out of the class: - - namespace foo - { - template - class custom_type - { - T value; - public: - custom_type(T x) : value(x) {} - - std::size_t hash(custom_type x) - { - __boost_hash hasher; - return hasher(value); - } - }; - - template - inline std::size_t hash_value(custom_type x) - { - return x.hash(); - } - } - -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, can called it from hash_value. - -For compilers which don't support ADL, hash_value needs to be defined in the -boost namespace: - - #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP - namespace boost - #else - namespace foo - #endif - { - template - std::size_t hash_value(foo::custom_type x) - { - return x.hash(); - } - } - -Full code for this example is at -[@../../libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp]. - -[h2 Other Issues] - -On Visual C++ versions 6.5 and 7.0, `hash_value` isn't overloaded for built in -arrays. __boost_hash, __hash_combine and __hash_range all use a workaround to -support built in arrays so this shouldn't be a problem in most cases. - -On Visual C++ versions 6.5 and 7.0, function pointers aren't currently supported. - -When using GCC on Solaris, `boost::hash_value(long double)` treats -`long double`s as doubles - so the hash function doesn't take into account the -full range of values. - -[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. - -
-
- - Defines boost::hash, - and helper 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 unqualified, so that custom overloads can be - found via argument dependent lookup. - - - Only throws if - hash_value(T) throws. - - - - - - - - - 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. - - - For the two argument overload: - -size_t seed = 0; - -for(; first != last; ++first) -{ - hash_combine(seed, *first); -} - -return seed; - - For the three arguments overload: - -for(; first != last; ++first) -{ - hash_combine(seed, *first); -} - - - - - - - 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. - - - - - - - - Implementation of a hash function for integers. - - - - Generally shouldn't 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 - - - - val - - - - - - - - Implementation of a hash function for floating point values. - - - - Generally shouldn't 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 - float - - - - std::size_t - double - - - - std::size_t - long double - - - - - An unspecified value, except that equal arguments shall yield the same - result - - - - - - - - - Implementation of a hash function for pointers. - - - - Generally shouldn't 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 - T* const& - - - - - An unspecified value, except that equal arguments shall yield the same - result - - - - - - - - - Implementation of a hash function for built in arrays. - - - - Generally shouldn't 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 - T (&val)[N] - - - - - std::size_t - const T (&val)[N] - - - hash_range(val, val+N) - - - - - - - Implementation of a hash function for std::basic_string. - - - - Generally shouldn't 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 - - std::basic_string<Ch, std::char_traits<Ch>, A> const& - - - - hash_range(val.begin(), val.end()) - - - - - - - - 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 - - - - - - - - std::size_t - std::vector<T, A> const & - - - - - std::size_t - std::list<T, A> const & - - - - - std::size_t - std::deque<T, A> const & - - - - - std::size_t - std::set<K, C, A> const & - - - - - std::size_t - std::multiset<K, C, A> const & - - - - - 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(T) throws. - - This is an extension to TR1 - - -
-
-''' -[/ Remove this comment and everything goes wrong! ;) ] -[endsect] - -[section:links Links] - -[*A Proposal to Add Hash Tables to the Standard Library]\n -[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html]\n -The hash table proposal explains much of the design. The hash function object -is discussed in Section D. - -[*The C++ Standard Library Technical Report.]\n -[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf]\n -Contains the hash function specification in section 6.3.2. - -[*Library Extension Technical Report Issues List.]\n -[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf]\n -The library implements the extension described in Issue 6.18, pages 63-67. - -[*Methods for Identifying Versioned and Plagiarised Documents]\n -Timothy C. Hoad, Justin Zobel\n -[@http://www.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf]\n -Contains the hash function that __hash_combine is based on. - -[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 review was managed by Thorsten Ottosen, and the library reviewed by: -David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris, -Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger,Jaap Suter -and Rob Stewart. - -The implementation of the hash function for pointers is based on suggestions -made by Alberto Barbati and Dave Harris. Dave Harris also suggested an -important improvement to __hash_combine that was taken up. - -The original implementation came from Jeremy B. Maitin-Shepard's hash table -library, although this is a complete rewrite. - -[endsect] +[include:hash intro.qbk] +[include:hash tutorial.qbk] +[include:hash portability.qbk] +[xinclude ref.xml] +[include:hash links.qbk] +[include:hash thanks.qbk] diff --git a/hash/doc/intro.qbk b/hash/doc/intro.qbk new file mode 100644 index 0000000..6e11647 --- /dev/null +++ b/hash/doc/intro.qbk @@ -0,0 +1,36 @@ +[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-short__. 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: + +* arrays +* `std::pair` +* the standard containers. +* extending [classref boost::hash] for custom types. + +[endsect] + diff --git a/hash/doc/links.qbk b/hash/doc/links.qbk new file mode 100644 index 0000000..e5e5007 --- /dev/null +++ b/hash/doc/links.qbk @@ -0,0 +1,22 @@ +[section:links Links] + +[*A Proposal to Add Hash Tables to the Standard Library]\n +[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html]\n +The hash table proposal explains much of the design. The hash function object +is discussed in Section D. + +[*The C++ Standard Library Technical Report.]\n +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf]\n +Contains the hash function specification in section 6.3.2. + +[*Library Extension Technical Report Issues List.]\n +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf]\n +The library implements the extension described in Issue 6.18, pages 63-67. + +[*Methods for Identifying Versioned and Plagiarised Documents]\n +Timothy C. Hoad, Justin Zobel\n +[@http://www.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf]\n +Contains the hash function that [funcref boost::hash_combine] is based on. + +[endsect] + diff --git a/hash/doc/portability.qbk b/hash/doc/portability.qbk new file mode 100644 index 0000000..f0eb333 --- /dev/null +++ b/hash/doc/portability.qbk @@ -0,0 +1,98 @@ +[section:portability Portability] + +[classref 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 + { + template + class custom_type + { + T value; + public: + custom_type(T x) : value(x) {} + + friend std::size_t hash_value(custom_type x) + { + [classref 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. +To make things worse, some compilers which do support ADL won't find +a friend class defined inside the class. + +So first move the member function out of the class: + + namespace foo + { + template + class custom_type + { + T value; + public: + custom_type(T x) : value(x) {} + + std::size_t hash(custom_type x) + { + [classref boost::hash] hasher; + return hasher(value); + } + }; + + template + inline std::size_t hash_value(custom_type x) + { + return x.hash(); + } + } + +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, can called it from hash_value. + +For compilers which don't support ADL, hash_value needs to be defined in the +boost namespace: + + #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + namespace boost + #else + namespace foo + #endif + { + template + std::size_t hash_value(foo::custom_type x) + { + return x.hash(); + } + } + +Full code for this example is at +[@../../libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp]. + +[h2 Other Issues] + +On Visual C++ versions 6.5 and 7.0, `hash_value` isn't overloaded for built in +arrays. [classref boost::hash], [funcref boost::hash_combine] and [funcref boost::hash_range] all use a workaround to +support built in arrays so this shouldn't be a problem in most cases. + +On Visual C++ versions 6.5 and 7.0, function pointers aren't currently supported. + +When using GCC on Solaris, `boost::hash_value(long double)` treats +`long double`s as doubles - so the hash function doesn't take into account the +full range of values. + +[endsect] diff --git a/hash/doc/ref.xml b/hash/doc/ref.xml new file mode 100644 index 0000000..56c0a24 --- /dev/null +++ b/hash/doc/ref.xml @@ -0,0 +1,459 @@ + +
+ 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. + +
+
+ + Defines boost::hash, + and helper 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 unqualified, so that custom overloads can be + found via argument dependent lookup. + + + Only throws if + hash_value(T) throws. + + + + + + + + + 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. + + + For the two argument overload: + +size_t seed = 0; + +for(; first != last; ++first) +{ + hash_combine(seed, *first); +} + +return seed; + + For the three arguments overload: + +for(; first != last; ++first) +{ + hash_combine(seed, *first); +} + + + + + + + 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. + + + + + + + + Implementation of a hash function for integers. + + + + Generally shouldn't 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 + + + + val + + + + + + + + Implementation of a hash function for floating point values. + + + + Generally shouldn't 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 + float + + + + std::size_t + double + + + + std::size_t + long double + + + + + An unspecified value, except that equal arguments shall yield the same + result + + + + + + + + + Implementation of a hash function for pointers. + + + + Generally shouldn't 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 + T* const& + + + + + An unspecified value, except that equal arguments shall yield the same + result + + + + + + + + + Implementation of a hash function for built in arrays. + + + + Generally shouldn't 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 + T (&val)[N] + + + + + std::size_t + const T (&val)[N] + + + hash_range(val, val+N) + + + + + + + Implementation of a hash function for std::basic_string. + + + + Generally shouldn't 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 + + std::basic_string<Ch, std::char_traits<Ch>, A> const& + + + + hash_range(val.begin(), val.end()) + + + + + + + + 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 + + + + + + + + std::size_t + std::vector<T, A> const & + + + + + std::size_t + std::list<T, A> const & + + + + + std::size_t + std::deque<T, A> const & + + + + + std::size_t + std::set<K, C, A> const & + + + + + std::size_t + std::multiset<K, C, A> const & + + + + + 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(T) throws. + + This is an extension to TR1 + + +
+
+ diff --git a/hash/doc/thanks.qbk b/hash/doc/thanks.qbk new file mode 100644 index 0000000..603e66b --- /dev/null +++ b/hash/doc/thanks.qbk @@ -0,0 +1,18 @@ +[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 review was managed by Thorsten Ottosen, and the library reviewed by: +David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris, +Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger,Jaap Suter +and Rob Stewart. + +The implementation of the hash function for pointers is based on suggestions +made by Alberto Barbati and Dave Harris. Dave Harris also suggested an +important improvement to [funcref boost::hash_combine] that was taken up. + +The original implementation came from Jeremy B. Maitin-Shepard's hash table +library, although this is a complete rewrite. + +[endsect] diff --git a/hash/doc/tutorial.qbk b/hash/doc/tutorial.qbk new file mode 100644 index 0000000..cda8df5 --- /dev/null +++ b/hash/doc/tutorial.qbk @@ -0,0 +1,192 @@ +[section:tutorial Tutorial] + +When using a hash index with __multi-index-short__, you don't need to do +anything to use [classref boost::hash] as it uses it by default. +To find out how to use a user-defined type, read the +[link hash.custom section on extending boost::hash for a custom data type]. + +If your standard library supplies its own implementation of the unordered +associative containers and you wish to use +[classref boost::hash], just use an extra template parameter: + + std::unordered_multiset, ``[classref boost::hash]`` > + set_of_ints; + + std::unordered_set, ``[classref 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() + { + ``[classref boost::hash]`` string_hash; + + std::size_t h = string_hash("Hash me"); + } + +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), + ``[classref boost::hash]``()); + + return hashes; + } + +[endsect] + +[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) + { + ``[classref boost::hash]`` hasher; + return hasher(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"); + + ``[classref boost::hash]`` book_hasher; + std::size_t knife_hash_value = book_hasher(knife); + + // If std::unordered_set is available: + std::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()); + +The full example can be found in: +[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.hpp] +and +[@../../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`. The function +[funcref boost::hash_combine] is supplied for this purpose: + + class point + { + ... + + friend std::size_t hash_value(point const& p) + { + std::size_t seed = 0; + [funcref boost::hash_combine](seed, p.x); + [funcref 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 [funcref 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 = [funcref boost::hash_range](some_strings.begin(), some_strings.end()); + +[endsect] +