diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 13ac5162..26bd33ac 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -1,72 +1,21 @@ - # Copyright 2005 Daniel James. # 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) -using boostbook ; -using quickbook ; +import asciidoctor ; -path-constant images_location : ../ ; -path-constant admonishment_location : ../../../../doc/src/images ; +html unordered.html : unordered.adoc ; -xml unordered : unordered.qbk : - generate.consistent.ids=1 ; +install html_ : unordered.html : html ; -boostbook standalone : unordered : - chunk.first.sections=1 - chunk.section.depth=2 - generate.section.toc.level=2 - toc.section.depth=1 - toc.max.depth=1 +pdf unordered.pdf : unordered.adoc ; +explicit unordered.pdf ; - boost.compact.typedef=0 - boost.compact.function=0 - boost.compact.enum=0 - - generate.consistent.ids=1 - - # HTML Options: - - html:boost.root=../../../.. - html:img.src.path=../../../../doc/html/ - xhtml:boost.root=../../../.. - xhtml:img.src.path=../../../../doc/html/ - - # PDF Options: - - # TOC Generation: this is needed for FOP-0.9 and later: - fop1.extensions=0 - pdf:xep.extensions=1 - # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! - pdf:fop.extensions=0 - # No indent on body text: - pdf:body.start.indent=0pt - # Margin size: - pdf:page.margin.inner=0.5in - # Margin size: - pdf:page.margin.outer=0.5in - # Paper type = A4 - pdf:paper.type=A4 - # Yes, we want graphics for admonishments: - admon.graphics=1 - # Set this one for PDF generation *only*: - # default png graphics are awful in PDF form, - # better use SVG's instead: - pdf:admon.graphics.extension=".svg" - pdf:use.role.for.mediaobject=1 - pdf:preferred.mediaobject.role=print - pdf:img.src.path=$(images_location)/ - #pdf:admon.graphics.path=$(admonishment_location) - pdf:draft.mode="no" - pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html - ; +install pdf_ : unordered.pdf : pdf ; +explicit pdf_ ; ############################################################################### -alias boostdoc - : unordered - : - : - : ; +alias boostdoc ; explicit boostdoc ; -alias boostrelease ; +alias boostrelease : html_ ; explicit boostrelease ; diff --git a/doc/unordered.adoc b/doc/unordered.adoc new file mode 100644 index 00000000..1fe32de9 --- /dev/null +++ b/doc/unordered.adoc @@ -0,0 +1,22 @@ += Boost.Unordered +:toc: left +:toclevels: 3 +:idprefix: +:docinfo: private-footer +:source-highlighter: rouge +:source-language: c++ +:nofooter: +:sectlinks: + +:leveloffset: +1 + +include::unordered/intro.adoc[] +include::unordered/buckets.adoc[] +include::unordered/hash_equality.adoc[] +include::unordered/comparison.adoc[] +include::unordered/compliance.adoc[] +include::unordered/rationale.adoc[] +include::unordered/ref.adoc[] +include::unordered/changes.adoc[] +include::unordered/bibliography.adoc[] +include::unordered/copyright.adoc[] diff --git a/doc/unordered/bibliography.adoc b/doc/unordered/bibliography.adoc new file mode 100644 index 00000000..5a2e3f11 --- /dev/null +++ b/doc/unordered/bibliography.adoc @@ -0,0 +1,10 @@ +[#bibliography] + +:idprefix: bibliography_ + += Bibliography + +* _C/C++ Users Journal_. February, 2006. Pete Becker. http://www.ddj.com/cpp/184402066[STL and TR1: Part III - Unordered containers^]. + +An introducation to the standard unordered containers. + + diff --git a/doc/unordered/buckets.adoc b/doc/unordered/buckets.adoc new file mode 100644 index 00000000..01839c5d --- /dev/null +++ b/doc/unordered/buckets.adoc @@ -0,0 +1,142 @@ +[#buckets] +:idprefix: buckets_ + += The Data Structure + +The containers are made up of a number of 'buckets', each of which can contain +any number of elements. For example, the following diagram shows an <> with 7 buckets containing 5 elements, `A`, +`B`, `C`, `D` and `E` (this is just for illustration, containers will typically +have more buckets). + +image::../diagrams/buckets.png[] + +In order to decide which bucket to place an element in, the container applies +the hash function, `Hash`, to the element's key (for `unordered_set` and +`unordered_multiset` the key is the whole element, but is referred to as the key +so that the same terminology can be used for sets and maps). This returns a +value of type `std::size_t`. `std::size_t` has a much greater range of values +then the number of buckets, so the container applies another transformation to +that value to choose a bucket to place the element in. + +Retrieving the elements for a given key is simple. The same process is applied +to the key to find the correct bucket. Then the key is compared with the +elements in the bucket to find any elements that match (using the equality +predicate `Pred`). If the hash function has worked well the elements will be +evenly distributed amongst the buckets so only a small number of elements will +need to be examined. + +There is <>. + +You can see in the diagram that `A` & `D` have been placed in the same bucket. +When looking for elements in this bucket up to 2 comparisons are made, making +the search slower. This is known as a collision. To keep things fast we try to +keep collisions to a minimum. + +[caption=, title='Table {counter:table-counter}. Methods for Accessing Buckets'] +[cols="1,.^1", frame=all, grid=rows] +|=== +|Method |Description + +|`size_type bucket_count() const` +|The number of buckets. + +|`size_type max_bucket_count() const` +|An upper bound on the number of buckets. + +|`size_type bucket_size(size_type n) const` +|The number of elements in bucket `n`. + +|`size_type bucket(key_type const& k) const` +|Returns the index of the bucket which would contain `k`. + +|`local_iterator begin(size_type n)` +1.6+|Return begin and end iterators for bucket `n`. + +|`local_iterator end(size_type n)` + +|`const_local_iterator begin(size_type n) const` + +|`const_local_iterator end(size_type n) const` + +|`const_local_iterator cbegin(size_type n) const` + +|`const_local_iterator cend(size_type n) const` + +|=== + +== Controlling the number of buckets + +As more elements are added to an unordered associative container, the number +of elements in the buckets will increase causing performance to degrade. +To combat this the containers increase the bucket count as elements are inserted. +You can also tell the container to change the bucket count (if required) by +calling `rehash`. + +The standard leaves a lot of freedom to the implementer to decide how the +number of buckets is chosen, but it does make some requirements based on the +container's 'load factor', the average number of elements per bucket. +Containers also have a 'maximum load factor' which they should try to keep the +load factor below. + +You can't control the bucket count directly but there are two ways to +influence it: + +* Specify the minimum number of buckets when constructing a container or when calling `rehash`. +* Suggest a maximum load factor by calling `max_load_factor`. + +`max_load_factor` doesn't let you set the maximum load factor yourself, it just +lets you give a _hint_. And even then, the draft standard doesn't actually +require the container to pay much attention to this value. The only time the +load factor is _required_ to be less than the maximum is following a call to +`rehash`. But most implementations will try to keep the number of elements +below the max load factor, and set the maximum load factor to be the same as +or close to the hint - unless your hint is unreasonably small or large. + +[caption=, title='Table {counter:table-counter}. Methods for Controlling Bucket Size'] +[cols="1,.^1", frame=all, grid=rows] +|=== +|Method |Description + +|`X(size_type n)` +|Construct an empty container with at least `n` buckets (`X` is the container type). + +|`X(InputIterator i, InputIterator j, size_type n)` +|Construct an empty container with at least `n` buckets and insert elements from the range `[i, j)` (`X` is the container type). + +|`float load_factor() const` +|The average number of elements per bucket. + +|`float max_load_factor() const` +|Returns the current maximum load factor. + +|`float max_load_factor(float z)` +|Changes the container's maximum load factor, using `z` as a hint. + +|`void rehash(size_type n)` +|Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor. + +|=== + +== Iterator Invalidation + +It is not specified how member functions other than `rehash` affect +the bucket count, although `insert` is only allowed to invalidate iterators +when the insertion causes the load factor to be greater than or equal to the +maximum load factor. For most implementations this means that `insert` will only +change the number of buckets when this happens. While iterators can be +invalidated by calls to `insert` and `rehash`, pointers and references to the +container's elements are never invalidated. + +In a similar manner to using `reserve` for ``vector``s, it can be a good idea +to call `rehash` before inserting a large number of elements. This will get +the expensive rehashing out of the way and let you store iterators, safe in +the knowledge that they won't be invalidated. If you are inserting `n` +elements into container `x`, you could first call: + +``` +x.rehash((x.size() + n) / x.max_load_factor()); +``` + +Note:: ``rehash``'s argument is the minimum number of buckets, not the +number of elements, which is why the new size is divided by the maximum load factor. diff --git a/doc/unordered/changes.adoc b/doc/unordered/changes.adoc new file mode 100644 index 00000000..2a4cab68 --- /dev/null +++ b/doc/unordered/changes.adoc @@ -0,0 +1,371 @@ +[#changes] += Change Log + +:idprefix: changes_ +:svn-ticket-url: https://svn.boost.org/trac/boost/ticket +:github-pr-url: https://github.com/boostorg/unordered/pull +:cpp: C++ + +== Changes in Boost 1.79.0 + +* Improved {cpp}20 support: + ** All containers have been updated to support + heterogeneous `count`, `equal_range` and `find`. + ** All containers now implement the member function `contains` +* Improved {cpp}23 support: + ** All containers have been updated to support + heterogeneous `erase` and `extract`. +* Changed behavior of `reserve` to eagerly + allocate ({github-pr-url}/59[PR#59^]). +* Various warning fixes in the test suite. +* Update code to internally use `boost::allocator_traits`. + +== Changes in Boost 1.67.0 + +* Improved {cpp}17 support: + ** Add template deduction guides from the standard. + ** Use a simple implementation of `optional` in node handles, so + that they're closer to the standard. + ** Add missing `noexcept` specifications to `swap`, `operator=` + and node handles, and change the implementation to match. + Using `std::allocator_traits::is_always_equal`, or our own + implementation when not available, and + `boost::is_nothrow_swappable` in the implementation. +* Improved {cpp}20 support: + ** Use `boost::to_address`, which has the proposed {cpp}20 semantics, + rather than the old custom implementation. +* Add `element_type` to iterators, so that `std::pointer_traits` + will work. +* Use `std::piecewise_construct` on recent versions of Visual {cpp}, + and other uses of the Dinkumware standard library, + now using Boost.Predef to check compiler and library versions. +* Use `std::iterator_traits` rather than the boost iterator traits + in order to remove dependency on Boost.Iterator. +* Remove iterators' inheritance from `std::iterator`, which is + deprecated in {cpp}17, thanks to Daniela Engert + ({github-pr-url}/7[PR#7^]). +* Stop using `BOOST_DEDUCED_TYPENAME`. +* Update some Boost include paths. +* Rename some internal methods, and variables. +* Various testing improvements. +* Miscellaneous internal changes. + +== Changes in Boost 1.66.0 + +* Simpler move construction implementation. +* Documentation fixes ({github-pr-url}/6[GitHub #6^]). + +== Changes in Boost 1.65.0 + +* Add deprecated attributes to `quick_erase` and `erase_return_void`. + I really will remove them in a future version this time. +* Small standards compliance fixes: + ** `noexpect` specs for `swap` free functions. + ** Add missing `insert(P&&)` methods. + +== Changes in Boost 1.64.0 + +* Initial support for new {cpp}17 member functions: + `insert_or_assign` and `try_emplace` in `unordered_map`, +* Initial support for `merge` and `extract`. + Does not include transferring nodes between + `unordered_map` and `unordered_multimap` or between `unordered_set` and + `unordered_multiset` yet. That will hopefully be in the next version of + Boost. + +== Changes in Boost 1.63.0 + +* Check hint iterator in `insert`/`emplace_hint`. +* Fix some warnings, mostly in the tests. +* Manually write out `emplace_args` for small numbers of arguments - + should make template error messages a little more bearable. +* Remove superfluous use of `boost::forward` in emplace arguments, + which fixes emplacing string literals in old versions of Visual {cpp}. +* Fix an exception safety issue in assignment. If bucket allocation + throws an exception, it can overwrite the hash and equality functions while + leaving the existing elements in place. This would mean that the function + objects wouldn't match the container elements, so elements might be in the + wrong bucket and equivalent elements would be incorrectly handled. +* Various reference documentation improvements. +* Better allocator support ({svn-ticket-url}/12459[#12459^]). +* Make the no argument constructors implicit. +* Implement missing allocator aware constructors. +* Fix assigning the hash/key equality functions for empty containers. +* Remove unary/binary_function from the examples in the documentation. + They are removed in {cpp}17. +* Support 10 constructor arguments in emplace. It was meant to support up to 10 + arguments, but an off by one error in the preprocessor code meant it only + supported up to 9. + +== Changes in Boost 1.62.0 + +* Remove use of deprecated `boost::iterator`. +* Remove `BOOST_NO_STD_DISTANCE` workaround. +* Remove `BOOST_UNORDERED_DEPRECATED_EQUALITY` warning. +* Simpler implementation of assignment, fixes an exception safety issue + for `unordered_multiset` and `unordered_multimap`. Might be a little slower. +* Stop using return value SFINAE which some older compilers have issues + with. + +== Changes in Boost 1.58.0 + +* Remove unnecessary template parameter from const iterators. +* Rename private `iterator` typedef in some iterator classes, as it + confuses some traits classes. +* Fix move assignment with stateful, propagate_on_container_move_assign + allocators ({svn-ticket-url}/10777[#10777^]). +* Fix rare exception safety issue in move assignment. +* Fix potential overflow when calculating number of buckets to allocate + ({github-pr-url}/4[GitHub #4^]). + +== Changes in Boost 1.57.0 + +* Fix the `pointer` typedef in iterators ({svn-ticket-url}/10672[#10672^]). +* Fix Coverity warning + ({github-pr-url}/2[GitHub #2^]). + +== Changes in Boost 1.56.0 + +* Fix some shadowed variable warnings ({svn-ticket-url}/9377[#9377^]). +* Fix allocator use in documentation ({svn-ticket-url}/9719[#9719^]). +* Always use prime number of buckets for integers. Fixes performance + regression when inserting consecutive integers, although makes other + uses slower ({svn-ticket-url}/9282[#9282^]). +* Only construct elements using allocators, as specified in {cpp}11 standard. + +== Changes in Boost 1.55.0 + +* Avoid some warnings ({svn-ticket-url}/8851[#8851^], {svn-ticket-url}/8874[#8874^]). +* Avoid exposing some detail functions via. ADL on the iterators. +* Follow the standard by only using the allocators' construct and destroy + methods to construct and destroy stored elements. Don't use them for internal + data like pointers. + +== Changes in Boost 1.54.0 + +* Mark methods specified in standard as `noexpect`. More to come in the next + release. +* If the hash function and equality predicate are known to both have nothrow + move assignment or construction then use them. + +== Changes in Boost 1.53.0 + +* Remove support for the old pre-standard variadic pair constructors, and + equality implementation. Both have been deprecated since Boost 1.48. +* Remove use of deprecated config macros. +* More internal implementation changes, including a much simpler + implementation of `erase`. + +== Changes in Boost 1.52.0 + +* Faster assign, which assigns to existing nodes where possible, rather than + creating entirely new nodes and copy constructing. +* Fixed bug in `erase_range` ({svn-ticket-url}/7471[#7471^]). +* Reverted some of the internal changes to how nodes are created, especially + for {cpp}11 compilers. 'construct' and 'destroy' should work a little better + for {cpp}11 allocators. +* Simplified the implementation a bit. Hopefully more robust. + +== Changes in Boost 1.51.0 + +* Fix construction/destruction issue when using a {cpp}11 compiler with a + {cpp}03 allocator ({svn-ticket-url}/7100[#7100^]). +* Remove a `try..catch` to support compiling without exceptions. +* Adjust SFINAE use to try to support g++ 3.4 ({svn-ticket-url}/7175[#7175^]). +* Updated to use the new config macros. + +== Changes in Boost 1.50.0 + +* Fix equality for `unordered_multiset` and `unordered_multimap`. +* {svn-ticket-url}/6857[Ticket 6857^]: + Implement `reserve`. +* {svn-ticket-url}/6771[Ticket 6771^]: + Avoid gcc's `-Wfloat-equal` warning. +* {svn-ticket-url}/6784[Ticket 6784^]: + Fix some Sun specific code. +* {svn-ticket-url}/6190[Ticket 6190^]: + Avoid gcc's `-Wshadow` warning. +* {svn-ticket-url}/6905[Ticket 6905^]: + Make namespaces in macros compatible with `bcp` custom namespaces. + Fixed by Luke Elliott. +* Remove some of the smaller prime number of buckets, as they may make + collisions quite probable (e.g. multiples of 5 are very common because + we used base 10). +* On old versions of Visual {cpp}, use the container library's implementation + of `allocator_traits`, as it's more likely to work. +* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas + Wang's hash function to pick which one to use. As modulus is very slow + for 64 bit values. +* Some internal changes. + +== Changes in Boost 1.49.0 + +* Fix warning due to accidental odd assignment. +* Slightly better error messages. + +== Changes in Boost 1.48.0 - Major update + +This is major change which has been converted to use Boost.Move's move +emulation, and be more compliant with the {cpp}11 standard. See the +xref:unordered.adoc#compliance[compliance section] for details. + +The container now meets {cpp}11's complexity requirements, but to do so +uses a little more memory. This means that `quick_erase` and +`erase_return_void` are no longer required, they'll be removed in a +future version. + +{cpp}11 support has resulted in some breaking changes: + +* Equality comparison has been changed to the {cpp}11 specification. + In a container with equivalent keys, elements in a group with equal + keys used to have to be in the same order to be considered equal, + now they can be a permutation of each other. To use the old + behavior define the macro `BOOST_UNORDERED_DEPRECATED_EQUALITY`. + +* The behaviour of swap is different when the two containers to be + swapped has unequal allocators. It used to allocate new nodes using + the appropriate allocators, it now swaps the allocators if + the allocator has a member structure `propagate_on_container_swap`, + such that `propagate_on_container_swap::value` is true. + +* Allocator's `construct` and `destroy` functions are called with raw + pointers, rather than the allocator's `pointer` type. + +* `emplace` used to emulate the variadic pair constructors that + appeared in early {cpp}0x drafts. Since they were removed it no + longer does so. It does emulate the new `piecewise_construct` + pair constructors - only you need to use + `boost::piecewise_construct`. To use the old emulation of + the variadic constructors define + `BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`. + +== Changes in Boost 1.45.0 + +* Fix a bug when inserting into an `unordered_map` or `unordered_set` using + iterators which returns `value_type` by copy. + +== Changes in Boost 1.43.0 + +* {svn-ticket-url}/3966[Ticket 3966^]: + `erase_return_void` is now `quick_erase`, which is the + http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579[ + current forerunner for resolving the slow erase by iterator^], although + there's a strong possibility that this may change in the future. The old + method name remains for backwards compatibility but is considered deprecated + and will be removed in a future release. +* Use Boost.Exception. +* Stop using deprecated `BOOST_HAS_*` macros. + +== Changes in Boost 1.42.0 + +* Support instantiating the containers with incomplete value types. +* Reduced the number of warnings (mostly in tests). +* Improved codegear compatibility. +* {svn-ticket-url}/3693[Ticket 3693^]: + Add `erase_return_void` as a temporary workaround for the current + `erase` which can be inefficient because it has to find the next + element to return an iterator. +* Add templated find overload for compatible keys. +* {svn-ticket-url}/3773[Ticket 3773^]: + Add missing `std` qualifier to `ptrdiff_t`. +* Some code formatting changes to fit almost all lines into 80 characters. + +== Changes in Boost 1.41.0 - Major update + +* The original version made heavy use of macros to sidestep some of the older + compilers' poor template support. But since I no longer support those + compilers and the macro use was starting to become a maintenance burden it + has been rewritten to use templates instead of macros for the implementation + classes. + +* The container object is now smaller thanks to using `boost::compressed_pair` + for EBO and a slightly different function buffer - now using a bool instead + of a member pointer. + +* Buckets are allocated lazily which means that constructing an empty container + will not allocate any memory. + +== Changes in Boost 1.40.0 + +* {svn-ticket-url}/2975[Ticket 2975^]: + Store the prime list as a preprocessor sequence - so that it will always get + the length right if it changes again in the future. +* {svn-ticket-url}/1978[Ticket 1978^]: + Implement `emplace` for all compilers. +* {svn-ticket-url}/2908[Ticket 2908^], + {svn-ticket-url}/3096[Ticket 3096^]: + Some workarounds for old versions of borland, including adding explicit + destructors to all containers. +* {svn-ticket-url}/3082[Ticket 3082^]: + Disable incorrect Visual {cpp} warnings. +* Better configuration for {cpp}0x features when the headers aren't available. +* Create less buckets by default. + +== Changes in Boost 1.39.0 + +* {svn-ticket-url}/2756[Ticket 2756^]: Avoid a warning + on Visual {cpp} 2009. +* Some other minor internal changes to the implementation, tests and + documentation. +* Avoid an unnecessary copy in `operator[]`. +* {svn-ticket-url}/2975[Ticket 2975^]: Fix length of + prime number list. + +== Changes in Boost 1.38.0 + +* Use link:../../../core/swap.html[`boost::swap`^]. +* {svn-ticket-url}/2237[Ticket 2237^]: + Document that the equality and inequality operators are undefined for two + objects if their equality predicates aren't equivalent. Thanks to Daniel + Krügler. +* {svn-ticket-url}/1710[Ticket 1710^]: + Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé + Brönnimann. +* Use + link:../../../type_traits/index.html[aligned storage^] to store the types. + This changes the way the allocator is used to construct nodes. It used to + construct the node with two calls to the allocator's `construct` + method - once for the pointers and once for the value. It now constructs + the node with a single call to construct and then constructs the value using + in place construction. +* Add support for {cpp}0x initializer lists where they're available (currently + only g++ 4.4 in {cpp}0x mode). + +== Changes in Boost 1.37.0 + +* Rename overload of `emplace` with hint, to `emplace_hint` as specified in + http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2691.pdf[n2691^]. +* Provide forwarding headers at `` and + ``. +* Move all the implementation inside `boost/unordered`, to assist + modularization and hopefully make it easier to track Changes in Boost subversion. + +== Changes in Boost 1.36.0 + +First official release. + +* Rearrange the internals. +* Move semantics - full support when rvalue references are available, emulated + using a cut down version of the Adobe move library when they are not. +* Emplace support when rvalue references and variadic template are available. +* More efficient node allocation when rvalue references and variadic template + are available. +* Added equality operators. + +== Boost 1.35.0 Add-on - 31st March 2008 + +Unofficial release uploaded to vault, to be used with Boost 1.35.0. Incorporated +many of the suggestions from the review. + +* Improved portability thanks to Boost regression testing. +* Fix lots of typos, and clearer text in the documentation. +* Fix floating point to `std::size_t` conversion when calculating sizes from + the max load factor, and use `double` in the calculation for greater accuracy. +* Fix some errors in the examples. + +== Review Version + +Initial review version, for the review conducted from 7th December 2007 to +16th December 2007. + + diff --git a/doc/unordered/comparison.adoc b/doc/unordered/comparison.adoc new file mode 100644 index 00000000..73ff38f9 --- /dev/null +++ b/doc/unordered/comparison.adoc @@ -0,0 +1,112 @@ +[#comparison] + +:idprefix: comparison_ + += Comparison with Associative Containers + +[caption=, title='Table {counter:table-counter} Interface differences'] +[cols="1,1", frame=all, grid=rows] +|=== +|Associative Containers |Unordered Associative Containers + +|Parameterized by an ordering relation `Compare` +|Parameterized by a function object `Hash` and an equivalence relation `Pred` + +|Keys can be compared using `key_compare` which is accessed by member function `key_comp()`, values can be compared using `value_compare` which is accessed by member function `value_comp()`. +|Keys can be hashed using `hasher` which is accessed by member function `hash_function()`, and checked for equality using `key_equal` which is accessed by member function `key_eq()`. There is no function object for compared or hashing values. + +|Constructors have optional extra parameters for the comparison object. +|Constructors have optional extra parameters for the initial minimum number of buckets, a hash function and an equality object. + +|Keys `k1`, `k2` are considered equivalent if `!Compare(k1, k2) && !Compare(k2, k1)`. +|Keys `k1`, `k2` are considered equivalent if `Pred(k1, k2)` + +|Member function `lower_bound(k)` and `upper_bound(k)` +|No equivalent. Since the elements aren't ordered `lower_bound` and `upper_bound` would be meaningless. + +|`equal_range(k)` returns an empty range at the position that `k` would be inserted if `k` isn't present in the container. +|`equal_range(k)` returns a range at the end of the container if `k` isn't present in the container. It can't return a positioned range as `k` could be inserted into multiple place. To find out the bucket that `k` would be inserted into use `bucket(k)`. But remember that an insert can cause the container to rehash - meaning that the element can be inserted into a different bucket. + +|`iterator`, `const_iterator` are of the bidirectional category. +|`iterator`, `const_iterator` are of at least the forward category. + +|Iterators, pointers and references to the container's elements are never invalidated. +|<>. Pointers and references to the container's elements are never invalidated. + +|Iterators iterate through the container in the order defined by the comparison object. +|Iterators iterate through the container in an arbitrary order, that can change as elements are inserted, although equivalent elements are always adjacent. + +|No equivalent +|Local iterators can be used to iterate through individual buckets. (The order of local iterators and iterators aren't required to have any correspondence.) + +|Can be compared using the `==`, `!=`, `<`, `\<=`, `>`, `>=` operators. +|Can be compared using the `==` and `!=` operators. + +| +|When inserting with a hint, implementations are permitted to ignore the hint. + +|`erase` never throws an exception +|The containers' hash or predicate function can throw exceptions from `erase`. + +|=== + +--- + +[caption=, title='Table {counter:table-counter} Complexity Guarantees'] +[cols="1,1,1", frame=all, grid=rows] +|=== +|Operation |Associative Containers |Unordered Associative Containers + +|Construction of empty container +|constant +|O(_n_) where _n_ is the minimum number of buckets. + +|Construction of container from a range of _N_ elements +|O(_N log N_), O(_N_) if the range is sorted with `value_comp()` +|Average case O(_N_), worst case O(_N^2^_) + +|Insert a single element +|logarithmic +|Average case constant, worst case linear + +|Insert a single element with a hint +|Amortized constant if `t` elements inserted right after hint, logarithmic otherwise +|Average case constant, worst case linear (ie. the same as a normal insert). + +|Inserting a range of _N_ elements +|_N_ log(`size()` + _N_) +|Average case O(_N_), worst case O(_N_ * `size()`) + +|Erase by key, `k` +|O(log(`size()`) + `count(k)`) +|Average case: O(`count(k)`), Worst case: O(`size()`) + +|Erase a single element by iterator +|Amortized constant +|Average case: O(1), Worst case: O(`size()`) + +|Erase a range of _N_ elements +|O(log(`size()`) + _N_) +|Average case: O(_N_), Worst case: O(`size()`) + +|Clearing the container +|O(`size()`) +|O(`size()`) + +|Find +|logarithmic +|Average case: O(1), Worst case: O(`size()`) + +|Count +|O(log(`size()`) + `count(k)`) +|Average case: O(1), Worst case: O(`size()`) + +|`equal_range(k)` +|logarithmic +|Average case: O(`count(k)`), Worst case: O(`size()`) + +|`lower_bound`,`upper_bound` +|logarithmic +|n/a + +|=== diff --git a/doc/unordered/compliance.adoc b/doc/unordered/compliance.adoc new file mode 100644 index 00000000..411a1ecf --- /dev/null +++ b/doc/unordered/compliance.adoc @@ -0,0 +1,116 @@ +[#compliance] += Standard Compliance + +:idprefix: compliance_ + +:cpp: C++ + +The intent of Boost.Unordered is to implement a close (but imperfect) +implementation of the {cpp}17 standard, that will work with {cpp}98 upwards. +The wide compatibility does mean some comprimises have to be made. +With a compiler and library that fully support {cpp}11, the differences should +be minor. + +== Move emulation + +Support for move semantics is implemented using Boost.Move. If rvalue +references are available it will use them, but if not it uses a close, +but imperfect emulation. On such compilers: + +* Non-copyable objects can be stored in the containers. + They can be constructed in place using `emplace`, or if they support + Boost.Move, moved into place. +* The containers themselves are not movable. +* Argument forwarding is not perfect. + +== Use of allocators + +{cpp}11 introduced a new allocator system. It's backwards compatible due to +the lax requirements for allocators in the old standard, but might need +some changes for allocators which worked with the old versions of the +unordered containers. +It uses a traits class, `allocator_traits` to handle the allocator +adding extra functionality, and making some methods and types optional. +During development a stable release of +`allocator_traits` wasn't available so an internal partial implementation +is always used in this version. Hopefully a future version will use the +standard implementation where available. + +The member functions `construct`, `destroy` and `max_size` are now +optional, if they're not available a fallback is used. +A full implementation of `allocator_traits` requires sophisticated +member function detection so that the fallback is used whenever the +member function call is not well formed. +This requires support for SFINAE expressions, which are available on +GCC from version 4.4 and Clang. + +On other compilers, there's just a test to see if the allocator has +a member, but no check that it can be called. So rather than using a +fallback there will just be a compile error. + +`propagate_on_container_copy_assignment`, +`propagate_on_container_move_assignment`, +`propagate_on_container_swap` and +`select_on_container_copy_construction` are also supported. +Due to imperfect move emulation, some assignments might check +`propagate_on_container_copy_assignment` on some compilers and +`propagate_on_container_move_assignment` on others. + +== Construction/Destruction using allocators + +The following support is required for full use of {cpp}11 style +construction/destruction: + +* Variadic templates. +* Piecewise construction of `std::pair`. +* Either `std::allocator_traits` or expression SFINAE. + +This is detected using Boost.Config. The macro +`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0 +otherwise. + +When this is the case `allocator_traits::construct` and +`allocator_traits::destroy` will always be used, apart from when piecewise +constructing a `std::pair` using `boost::tuple` (see <>), but that should be easily avoided. + +When support is not available `allocator_traits::construct` and +`allocator_traits::destroy` are never called. + +== Pointer Traits + +`pointer_traits` aren't used. Instead, pointer types are obtained from +rebound allocators, this can cause problems if the allocator can't be +used with incomplete types. If `const_pointer` is not defined in the +allocator, `boost::pointer_to_other::type` +is used to obtain a const pointer. + +== Pairs + +Since the containers use `std::pair` they're limited to the version +from the current standard library. But since {cpp}11 ``std::pair``'s +`piecewise_construct` based constructor is very useful, `emplace` +emulates it with a `piecewise_construct` in the `boost::unordered` +namespace. So for example, the following will work: + +[source,c++] +---- +boost::unordered_multimap x; + +x.emplace( + boost::unordered::piecewise_construct, + boost::make_tuple("key"), boost::make_tuple(1, 2)); +---- + +Older drafts of the standard also supported variadic constructors +for `std::pair`, where the first argument would be used for the +first part of the pair, and the remaining for the second part. + +== Miscellaneous + +When swapping, `Pred` and `Hash` are not currently swapped by calling +`swap`, their copy constructors are used. As a consequence when swapping +an exception may be thrown from their copy constructor. + +Variadic constructor arguments for `emplace` are only used when both +rvalue references and variadic template parameters are available. +Otherwise `emplace` can only take up to 10 constructors arguments. diff --git a/doc/unordered/copyright.adoc b/doc/unordered/copyright.adoc new file mode 100644 index 00000000..64490bfb --- /dev/null +++ b/doc/unordered/copyright.adoc @@ -0,0 +1,12 @@ +[#copyright] += Copyright and License + +:idprefix: copyright_ + +*Daniel James* + +Copyright (C) 2003, 2004 Jeremy B. Maitin-Shepard + +Copyright (C) 2005-2008 Daniel James + +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) diff --git a/doc/unordered/hash_equality.adoc b/doc/unordered/hash_equality.adoc new file mode 100644 index 00000000..5d2bdd76 --- /dev/null +++ b/doc/unordered/hash_equality.adoc @@ -0,0 +1,149 @@ +[#hash_equality] + +:idprefix: hash_equality_ + += Equality Predicates and Hash Functions + +While the associative containers use an ordering relation to specify how the +elements are stored, the unordered associative containers use an equality +predicate and a hash function. For example, <> +is declared as: + +``` +template < + class Key, class Mapped, + class Hash = boost::hash, + class Pred = std::equal_to, + class Alloc = std::allocator > > +class unordered_map; +``` + +The hash function comes first as you might want to change the hash function +but not the equality predicate. For example, if you wanted to use the +http://www.isthe.com/chongo/tech/comp/fnv/[FNV-1 hash^] you could write: + +``` +boost::unordered_map + dictionary; +``` + +There is an link:../../examples/fnv1.hpp[implementation of FNV-1^] in the examples directory. + +If you wish to use a different equality function, you will also need to use a matching hash function. For example, to implement a case insensitive dictionary you need to define a case insensitive equality predicate and hash function: + +``` +struct iequal_to +{ + bool operator()(std::string const& x, + std::string const& y) const + { + return boost::algorithm::iequals(x, y, std::locale()); + } +}; + +struct ihash +{ + std::size_t operator()(std::string const& x) const + { + std::size_t seed = 0; + std::locale locale; + + for(std::string::const_iterator it = x.begin(); + it != x.end(); ++it) + { + boost::hash_combine(seed, std::toupper(*it, locale)); + } + + return seed; + } +}; +``` + +Which you can then use in a case insensitive dictionary: +``` +boost::unordered_map + idictionary; +``` + +This is a simplified version of the example at +link:../../examples/case_insensitive.hpp[/libs/unordered/examples/case_insensitive.hpp^] which supports other locales and string types. + +CAUTION: Be careful when using the equality (`==`) operator with custom equality +predicates, especially if you're using a function pointer. If you compare two +containers with different equality predicates then the result is undefined. +For most stateless function objects this is impossible - since you can only +compare objects with the same equality predicate you know the equality +predicates must be equal. But if you're using function pointers or a stateful +equality predicate (e.g. `boost::function`) then you can get into trouble. + +== Custom Types + +Similarly, a custom hash function can be used for custom types: + +``` +struct point { + int x; + int y; +}; + +bool operator==(point const& p1, point const& p2) +{ + return p1.x == p2.x && p1.y == p2.y; +} + +struct point_hash +{ + std::size_t operator()(point const& p) const + { + std::size_t seed = 0; + boost::hash_combine(seed, p.x); + boost::hash_combine(seed, p.y); + return seed; + } +}; + +boost::unordered_multiset points; +``` + +Since the default hash function is link:../../../container_hash/index.html[Boost.Hash^], +we can extend it to support the type so that the hash function doesn't need to be explicitly given: + +``` +struct point { + int x; + int y; +}; + +bool operator==(point const& p1, point const& p2) +{ + return p1.x == p2.x && p1.y == p2.y; +} + +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; +} + +// Now the default function objects work. +boost::unordered_multiset points; +``` + +See the link:../../../container_hash/index.html[Boost.Hash documentation^] for more detail on how to +do this. Remember that it relies on extensions to the draft standard - so it +won't work for other implementations of the unordered associative containers, +you'll need to explicitly use Boost.Hash. + +[caption=, title='Table {counter:table-counter} Methods for accessing the hash and equality functions'] +[cols="1,.^1", frame=all, grid=rows] +|=== +|Method |Description + +|`hasher hash_function() const` +|Returns the container's hash function. + +|`key_equal key_eq() const` +|Returns the container's key equality function.. + +|=== diff --git a/doc/unordered/intro.adoc b/doc/unordered/intro.adoc new file mode 100644 index 00000000..c82021fe --- /dev/null +++ b/doc/unordered/intro.adoc @@ -0,0 +1,116 @@ +[#intro] += Introduction + +:idprefix: intro_ +:cpp: C++ + +For accessing data based on key lookup, the {cpp} standard library offers `std::set`, +`std::map`, `std::multiset` and `std::multimap`. These are generally +implemented using balanced binary trees so that lookup time has +logarithmic complexity. That is generally okay, but in many cases a +link:https://en.wikipedia.org/wiki/Hash_table[hash table^] can perform better, as accessing data has constant complexity, +on average. The worst case complexity is linear, but that occurs rarely and +with some care, can be avoided. + +Also, the existing containers require a 'less than' comparison object +to order their elements. For some data types this is impossible to implement +or isn't practical. In contrast, a hash table only needs an equality function +and a hash function for the key. + +With this in mind, unordered associative containers were added to the {cpp} +standard. This is an implementation of the containers described in {cpp}11, +with some <> in +order to work with non-{cpp}11 compilers and libraries. + +`unordered_set` and `unordered_multiset` are defined in the header +`` +[source,c++] +---- +namespace boost { + template < + class Key, + class Hash = boost::hash, + class Pred = std::equal_to, + class Alloc = std::allocator > + class unordered_set; + + template< + class Key, + class Hash = boost::hash, + class Pred = std::equal_to, + class Alloc = std::allocator > + class unordered_multiset; +} +---- + +`unordered_map` and `unordered_multimap` are defined in the header +`` + +[source,c++] +---- +namespace boost { + template < + class Key, class Mapped, + class Hash = boost::hash, + class Pred = std::equal_to, + class Alloc = std::allocator > > + class unordered_map; + + template< + class Key, class Mapped, + class Hash = boost::hash, + class Pred = std::equal_to, + class Alloc = std::allocator > > + class unordered_multimap; +} +---- + +When using Boost.TR1, these classes are included from `` and +``, with the classes added to the `std::tr1` namespace. + +The containers are used in a similar manner to the normal associative +containers: + +[source,cpp] +---- +typedef boost::unordered_map map; +map x; +x["one"] = 1; +x["two"] = 2; +x["three"] = 3; + +assert(x.at("one") == 1); +assert(x.find("missing") == x.end()); +---- + +But since the elements aren't ordered, the output of: + +[source,c++] +---- +BOOST_FOREACH(map::value_type i, x) { + std::cout<> section +for more details. + +There are other differences, which are listed in the +<> section. diff --git a/doc/unordered/rationale.adoc b/doc/unordered/rationale.adoc new file mode 100644 index 00000000..7b8af730 --- /dev/null +++ b/doc/unordered/rationale.adoc @@ -0,0 +1,52 @@ +[#rationale] + +:idprefix: rationale_ + += Implementation Rationale + +The intent of this library is to implement the unordered +containers in the draft standard, so the interface was fixed. But there are +still some implementation decisions to make. The priorities are +conformance to the standard and portability. + +The http://en.wikipedia.org/wiki/Hash_table[Wikipedia article on hash tables^] +has a good summary of the implementation issues for hash tables in general. + +== Data Structure + +By specifying an interface for accessing the buckets of the container the +standard pretty much requires that the hash table uses chained addressing. + +It would be conceivable to write a hash table that uses another method. For +example, it could use open addressing, and use the lookup chain to act as a +bucket but there are some serious problems with this: + +* The draft standard requires that pointers to elements aren't invalidated, so + the elements can't be stored in one array, but will need a layer of + indirection instead - losing the efficiency and most of the memory gain, + the main advantages of open addressing. +* Local iterators would be very inefficient and may not be able to + meet the complexity requirements. +* There are also the restrictions on when iterators can be invalidated. Since + open addressing degrades badly when there are a high number of collisions the + restrictions could prevent a rehash when it's really needed. The maximum load + factor could be set to a fairly low value to work around this - but the + standard requires that it is initially set to 1.0. +* And since the standard is written with a eye towards chained + addressing, users will be surprised if the performance doesn't reflect that. + +So chained addressing is used. + +== Number of Buckets + +There are two popular methods for choosing the number of buckets in a hash table. One is to have a prime number of buckets, another is to use a power of 2. + +Using a prime number of buckets, and choosing a bucket by using the modulus of the hash function's result will usually give a good result. The downside is that the required modulus operation is fairly expensive. This is what the containers do in most cases. + +Using a power of 2 allows for much quicker selection of the bucket to use, but at the expense of losing the upper bits of the hash value. For some specially designed hash functions it is possible to do this and still get a good result but as the containers can take arbitrary hash functions this can't be relied on. + +To avoid this a transformation could be applied to the hash function, for an example see http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm[Thomas Wang's article on integer hash functions^]. Unfortunately, a transformation like Wang's requires knowledge of the number of bits in the hash value, so it isn't portable enough to use as a default. It can applicable in certain cases so the containers have a policy based implementation that can use this alternative technique. + +Currently this is only done on 64 bit architectures, where prime number modulus can be expensive. Although this varies depending on the architecture, so I probably should revisit it. + +I'm also thinking of introducing a mechanism whereby a hash function can indicate that it's safe to be used directly with power of 2 buckets, in which case a faster plain power of 2 implementation can be used. diff --git a/doc/unordered/ref.adoc b/doc/unordered/ref.adoc new file mode 100644 index 00000000..66924f81 --- /dev/null +++ b/doc/unordered/ref.adoc @@ -0,0 +1,7 @@ +[#reference] += Reference + +include::unordered_map.adoc[] +include::unordered_multimap.adoc[] +include::unordered_set.adoc[] +include::unordered_multiset.adoc[] diff --git a/doc/unordered/unordered_map.adoc b/doc/unordered/unordered_map.adoc new file mode 100644 index 00000000..1e8f61c5 --- /dev/null +++ b/doc/unordered/unordered_map.adoc @@ -0,0 +1,1424 @@ +[#unordered_map] +== Class template unordered_map + +:idprefix: unordered_map_ + +`boost::unordered_map` — An unordered associative container that associates unique keys with another value. + +=== Synopsis + +[source,c++,subs=+quotes] +----- +// #include + +template< + typename Key, + typename Mapped, + typename Hash = boost::hash, + typename Pred = std::equal_to, + typename Alloc = std::allocator> > +class unordered_map { +public: + // types + typedef Key key_type; + typedef std::pair value_type; + typedef Mapped mapped_type; + typedef Hash hasher; + typedef Pred key_equal; + typedef Alloc allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef _implementation-defined_ size_type; + typedef _implementation-defined_ difference_type; + typedef _implementation-defined_ iterator; + typedef _implementation-defined_ const_iterator; + typedef _implementation-defined_ local_iterator; + typedef _implementation-defined_ const_local_iterator; + typedef _implementation-defined_ node_type; + typedef _implementation-defined_ insert_return_type; + + // construct/copy/destruct + unordered_map(); + + explicit unordered_map(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + unordered_map(unordered_map const& other); + unordered_map(unordered_map&& other); + + explicit unordered_map(Allocator const& a); + unordered_map(unordered_map const& other, Allocator const& a); + unordered_map(unordered_map&& other, Allocator const& a); + + unordered_map(size_type n, allocator_type const& a); + unordered_map(size_type n, hasher const& hf, allocator_type const& a); + + unordered_map(initializer_list il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_map(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_map(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); + + template + unordered_map(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); + + ~unordered_map(); + + unordered_map& operator=(unordered_map const& other); + unordered_map& operator=(unordered_map&& other); + unordered_map& operator=(initializer_list il); + + // size and capacity + bool empty() const; + size_type size() const; + size_type max_size() const; + + // iterators + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + const_iterator cbegin() const; + const_iterator cend() const; + + // modifiers + template + std::pair + emplace(Args&&... args); + + template + iterator + emplace_hint(const_iterator hint, Args&&... args); + + std::pair + insert(value_type const& obj); + + std::pair + insert(value_type&& obj); + + insert_return_type insert(node_type&& nh); + + iterator insert(const_iterator hint, value_type const& obj); + iterator insert(const_iterator hint, value_type&& obj); + iterator insert(const_iterator hint, node_type&& nh); + + template + void insert(InputIterator first, InputIterator last); + + void insert(initializer_list il); + + node_type extract(const_iterator position); + node_type extract(key_type const& k); + + template + node_type extract(K&& k); + + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + size_type erase(key_type const& k); + + template + size_type erase(K&& k); + + void quick_erase(const_iterator position); + void erase_return_void(const_iterator position); + + void clear(); + void swap(unordered_map& other); + + template + void merge(unordered_map& source); + + template + void merge(unordered_map&& source); + + // observers + allocator_type get_allocator() const; + hasher hash_function() const; + key_equal key_eq() const; + + // lookup + iterator find(key_type const& k); + const_iterator find(key_type const& k) const; + + template + iterator + find(K const& k); + + template + const_iterator + find(K const& k) const; + + template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> + iterator + find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const&) eq; + + template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> + const_iterator + find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + + bool contains(key_type const& key) const; + + template + bool contains(K const& key); + + size_type count(key_type const& k) const; + + template + size_type count(K const& k) const; + + std::pair + equal_range(key_type const& k); + + std::pair + equal_range(key_type const& k) const; + + template + std::pair + equal_range(K const& k); + + template + std::pair + equal_range(K const& k) const; + + mapped_type& operator[](key_type const& k); + + Mapped& at(key_type const& k); + Mapped const& at(key_type const& k) const; + + // bucket interface + size_type bucket_count() const; + size_type max_bucket_count() const; + size_type bucket_size(size_type n) const; + size_type bucket(key_type const& k) const; + + local_iterator begin(size_type n); + const_local_iterator begin(size_type n) const; + + local_iterator end(size_type n); + const_local_iterator end(size_type n) const; + + const_local_iterator cbegin(size_type n) const; + const_local_iterator cend(size_type n) const; + + // hash policy + float load_factor() const; + float max_load_factor() const; + + void max_load_factor(float z); + + void rehash(size_type n); + void reserve(size_type n); +}; + +// Equality Comparisons +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_map const& x, + unordered_map const& y); + +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_map const& x, + unordered_map const& y); + +// swap +template +void swap(unordered_map& x, + unordered_map& y); +----- + +--- + +=== Description + +*Template Parameters* + +[cols="1,1"] +|=== + +|_Key_ +|`Key` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Mapped_ +|`Mapped` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Hash_ +|A unary function object type that acts a hash function for a `Key`. It takes a single argument of type `Key` and returns a value of type `std::size_t`. + +|_Pred_ +|A binary function object that implements an equivalence relation on values of type `Key`. A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type bool. + +|_Alloc_ +|An allocator whose value type is the same as the container's value type. + +|=== + +The elements are organized into buckets. Keys with the same hash code are stored in the same bucket. + +The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash. + +--- + +=== Typedefs + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::pointer pointer; +---- + +`value_type*` if `allocator_type::pointer` is not defined. + +--- + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::const_pointer const_pointer; +---- + +`boost::pointer_to_other::type` if `allocator_type::const_pointer` is not defined. + + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ size_type; +---- + +An unsigned integral type. + +`size_type` can represent any non-negative value of `difference_type`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ difference_type; +---- + +A signed integral type. + +Is identical to the difference type of `iterator` and `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ iterator; +---- + +An iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +Convertible to `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ local_iterator; +---- + +An iterator with the same value type, difference type and pointer and reference type as iterator. + +A `local_iterator` object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_local_iterator; +---- + +A constant iterator with the same value type, difference type and pointer and reference type as const_iterator. + +A const_local_iterator object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ node_type; +---- + +See node_handle_map for details. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ insert_return_type; +---- + +Structure returned by inserting node_type. + +--- + +=== Constructors + +==== Default Constructor +```c++ +unordered_map(); +``` + +Constructs an empty container using `hasher()` as the hash function, +`key_equal()` as the key equality predicate, `allocator_type()` as the allocator +and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor +```c++ +explicit unordered_map(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash +function, `eq` as the key equality predicate, `a` as the allocator and a maximum +load factor of `1.0`. + +Postconditions:: `size() == 0` + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Copy Constructor +```c++ +unordered_map(unordered_map const& other); +``` + +The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator. + +If `Allocator::select_on_container_copy_construction` exists and has the right signature, the allocator will be constructed from its result. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Constructor +```c++ +unordered_map(unordered_map&& other); +``` + +The move constructor. + +Notes:: This is implemented using Boost.Move. + +Requires:: `value_type` is move-constructible. On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable. +So, for example, you can't return the container from a function. + +--- + +==== Allocator Constructor +```c++ +explicit unordered_map(Allocator const& a); +``` + +Constructs an empty container, using allocator `a`. + +--- + +==== Copy Constructor with Allocator +```c++ +unordered_map(unordered_map const& other, Allocator const& a); +``` + +Constructs an container, copying ``other``'s contained elements, hash function, predicate, maximum load factor, but using allocator `a`. + +--- + +==== Move Constructor with Allocator +```c++ +unordered_map(unordered_map&& other, Allocator const& a); +``` + +Construct a container moving ``other``'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate `a`. + +Notes:: This is implemented using Boost.Move. +Requires:: `value_type` is move insertable. + +--- + +==== Bucket Count Constructor with Allocator +```c++ +unordered_map(size_type n, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default hash function and key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Hasher and Allocator +```c++ +unordered_map(size_type n, hasher const& hf, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Initializer List Constructor +[source,c++,subs="quotes,macros"] +---- +unordered_map(initializer_list++<++value_type++>++ il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `il` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_map(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Allocator +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_map(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `a` as the allocator, with the default hash function and key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `hasher`, `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +==== Iterator Range Constructor with Bucket Count and Hasher +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_map(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator, with the default key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +=== Destructor + +```c++ +~unordered_map(); +``` +Note:: The destructor is applied to every element, and all memory is deallocated + +--- + +=== Assignment + +==== Copy Assignment + +```c++ +unordered_map& operator=(unordered_map const& other); +``` + +The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator. + +If `Alloc::propagate_on_container_copy_assignment` exists and `Alloc::propagate_on_container_copy_assignment::value` is `true`, the allocator is overwritten, if not the copied elements are created using the existing allocator. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Assignment +```c++ +unordered_map& operator=(unordered_map&& other); +``` +The move assignment operator. + +If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator. + +Notes:: On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances. + +Requires:: `value_type` is move constructible. + +--- + +==== Initializer List Assignment +```c++ +unordered_map& operator=(initializer_list il); +``` + +Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] into the container and https://en.cppreference.com/w/cpp/named_req/CopyAssignable[CopyAssignable^]. + +=== Size and Capacity + +==== empty + +```c++ +bool empty() const; +``` + +Returns:: `size() == 0` + +--- + +==== size + +```c++ +size_type size() const; +``` + +Returns:: `std::distance(begin(), end())` + +--- + +==== max_size + +```c++ +size_type max_size() const; +``` + +Returns:: `size()` of the largest possible container. + +--- + +=== Iterators + +==== begin +```c++ +iterator begin(); +const_iterator begin() const; +``` + +Returns:: An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== end +```c++ +iterator end(); +const_iterator end() const; +``` + +Returns:: An iterator which refers to the past-the-end value for the container. + +--- + +==== cbegin +```c++ +const_iterator cbegin() const; +``` +Returns:: A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== cend +```c++ +const_iterator cend() const; +``` + +Returns:: A `const_iterator` which refers to the past-the-end value for the container. + +--- + +=== Modifiers + +==== emplace +```c++ +template +std::pair +emplace(Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: The bool component of the return type is true if an insert took place. + +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== emplace_hint +```c++ +template +iterator +emplace_hint(const_iterator hint, Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. +Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== Copy Insert +```c++ +std::pair +insert(value_type const& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: The bool component of the return type is true if an insert took place. If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert +```c++ +std::pair +insert(value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: The bool component of the return type is true if an insert took place. If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with `node_handle` +```c++ +insert_return_type +insert(node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh` if and only if there is no element in the container with an equivalent key. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns an `insert_return_type` with: `inserted` equal to `false`, `position` equal to `end()` and `node` empty. Otherwise if there was already an element with an equivalent key, returns an `insert_return_type` with: `inserted` equal to `false`, `position` pointing to a matching element and `node` contains the node from `nh`. Otherwise if the insertion succeeded, returns an `insert_return_type` with: `inserted` equal to `true`, `position` pointing to the newly inserted element and `node` empty. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_multimap`, but that is not supported yet. + +--- + +==== Copy Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type const& obj); +``` +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with Hint and `node_handle` +```c++ +iterator insert(const_iterator hint, node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh` if and only if there is no element in the container with an equivalent key. + +If there is already an element in the container with an equivalent key has no effect on `nh` (i.e. `nh` still contains the node.) + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty returns `end()`. If there was already an element in the container with an equivalent key returns an iterator pointing to that. Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to hasher the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_multimap`, but that is not supported yet. + +--- + +==== Insert Iterator Range +```c++ +template +void insert(InputIterator first, InputIterator last); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert Initializer List +```c++ +void insert(initializer_list il); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Extract by Iterator +```c++ +node_type extract(const_iterator position); +``` + +Removes the element pointed to by `position`. + +Returns:: A `node_type` owning the element. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. + +--- + +==== Transparent Extract by Key +```c++ +template +node_type extract(K&& k); +``` + +Removes an element with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. + +--- + +==== Extract by Key +```c++ +node_type extract(key_type const& k); +``` + +Removes an element with key equivalent to `k`. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. + +==== Erase by Position + +```c++ +iterator erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Returns:: The iterator following `position` before the erasure. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In older versions this could be inefficient because it had to search through several buckets to find the position of the returned iterator. The data structure has been changed so that this is no longer the case, and the alternative erase methods have been deprecated. + +--- + +==== Erase Range + +```c++ +iterator erase(const_iterator first, const_iterator last); +``` + +Erases the elements in the range from `first` to `last`. + +Returns:: The iterator following the erased elements - i.e. `last`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +--- + +==== Transparent Erase by Key +```c++ +template +size_type erase(K&& k); +``` + +Erase all elements with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Erase by Key +```c++ +size_type erase(key_type const& k); +``` + +Erase all elements with key equivalent to `k`. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== quick_erase +```c++ +void quick_erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== erase_return_void +```c++ +void erase_return_void(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== clear +```c++ +void clear(); +``` + +Erases all elements in the container. + +Postconditions:: `size() == 0` + +Throws:: Never throws an exception. + +--- + +==== swap +```c++ +void swap(unordered_map& other); +``` + +Swaps the contents of the container with the parameter. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + +--- + +==== merge +```c++ +template +void merge(unordered_map& source); +``` + +Notes:: Does not support merging with a compatible `unordered_multimap` yet. + +--- + +==== merge (rvalue reference) +```c++ +template +void merge(unordered_map&& source); +``` + +Notes:: Does not support merging with a compatible `unordered_multimap` yet. + +--- + +=== Observers + +==== get_allocator +``` +allocator_type get_allocator() const; +``` + +==== hash_function +``` +hasher hash_function() const; +``` + +Returns:: The container's hash function. + +--- + +``` +key_equal key_eq() const; +``` + +Returns:: The container's key equality predicate + +--- + +=== Lookup + +==== find +```c++ +iterator find(key_type const& k); +const_iterator find(key_type const& k) const; + +template +iterator +find(K const& k); + +template +const_iterator +find(K const& k) const; + +template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> +iterator +find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq); + +template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> +const_iterator +find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + +``` + +Returns:: An iterator pointing to an element with key equivalent to `k`, or `b.end()` if no such element exists. + +Notes:: The templated overloads containing `CompatibleKey`, `CompatibleHash` and `CompatiblePredicate` are non-standard extensions which allow you to use a compatible hash function and equality predicate for a key of a different type in order to avoid an expensive type cast. In general, its use is not encouraged and instead the `K` member function templates should be used. + +The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== contains +```c++ +template +bool contains(K const& key); +bool contains(key_type const& key) const; +``` + +Returns:: A boolean indicating whether or not there is an element with key equal to `key` in the container + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== count +```c++ +template +size_type count(K const& k) const; +size_type count(key_type const& k) const; +``` + +Returns:: The number of elements with key equivalent to `k`. + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== equal_range +```c++ +std::pair +equal_range(key_type const& k); + +std::pair +equal_range(key_type const& k) const; + +template +std::pair +equal_range(K const& k); + +template +std::pair +equal_range(K const& k) const; +``` + +Returns:: A range containing all elements with key equivalent to `k`. If the container doesn't contain any such elements, returns `std::make_pair(b.end(), b.end())`. + +Notes:: The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== operator++[++++]++ +```c++ +mapped_type& operator[](key_type const& k); +``` + +Effects:: If the container does not already contain an elements with a key equivalent to `k`, inserts the value `std::pair(k, mapped_type())`. + +Returns:: A reference to `x.second` where `x` is the element already in the container, or the newly inserted element with a key equivalent to `k`. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== at +```c++ +Mapped& at(key_type const& k); +Mapped const& at(key_type const& k) const; +``` + +Returns:: A reference to `x.second` where `x` is the (unique) element whose key is equivalent to `k`. + +Throws:: An exception object of type `std::out_of_range` if no such element is present. + +--- + +=== Bucket Interface + +==== bucket_count +```c++ +size_type bucket_count() const; +``` + +Returns:: The number of buckets. + +--- + +==== max_bucket_count +```c++ +size_type max_bucket_count() const; +``` + +Returns:: An upper bound on the number of buckets. + +--- + +==== bucket_size +```c++ +size_type bucket_size(size_type n) const; +``` + +Requires:: `n < bucket_count()` + +Returns:: The number of elements in bucket `n`. + +--- + +==== bucket +```c++ +size_type bucket(key_type const& k) const; +``` + +Returns:: The index of the bucket which would contain an element with key `k`. + +Postconditions:: The return value is less than `bucket_count()`. + +--- + +==== begin + +```c++ +local_iterator begin(size_type n); +const_local_iterator begin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the first element in the bucket with index `n`. + +--- + +==== end +```c++ +local_iterator end(size_type n); +const_local_iterator end(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +==== cbegin +```c++ +const_local_iterator cbegin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the first element in the bucket with index `n`. + +--- + +==== cend +```c++ +const_local_iterator cend(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +=== Hash Policy + +==== load_factor +```c++ +float load_factor() const; +``` + +Returns:: The average number of elements per bucket. + +--- + +==== max_load_factor + +```c++ +float max_load_factor() const; +``` + +Returns:: Returns the current maximum load factor. + +--- + +==== Set max_load_factor +```c++ +void max_load_factor(float z); +``` + +Effects:: Changes the container's maximum load factor, using `z` as a hint. + +--- + + +==== rehash +```c++ +void rehash(size_type n); +``` + +Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor. + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +--- + +==== reserve +```c++ +void reserve(size_type n); +``` + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +=== Equality Comparisons + +==== operator== +```c++ +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_map const& x, + unordered_map const& y); +``` + +Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +--- + +==== operator!= +```c++ +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_map const& x, + unordered_map const& y); +``` + +Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +=== Swap +```c++ +template +void swap(unordered_map& x, + unordered_map& y); +``` + +Swaps the contents of `x` and `y`. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Effects:: `x.swap(y)` + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + + diff --git a/doc/unordered/unordered_multimap.adoc b/doc/unordered/unordered_multimap.adoc new file mode 100644 index 00000000..33ce8573 --- /dev/null +++ b/doc/unordered/unordered_multimap.adoc @@ -0,0 +1,1391 @@ +[#unordered_multimap] +== Class template unordered_multimap + +:idprefix: unordered_multimap_ + +`boost::unordered_multimap` — An unordered associative container that associates keys with another value. The same key can be stored multiple times. + +=== Synopsis + +[source,c++,subs=+quotes] +----- +// #include + +template< + typename Key, + typename Mapped, + typename Hash = boost::hash, + typename Pred = std::equal_to, + typename Alloc = std::allocator> > +class unordered_multimap { +public: + // types + typedef Key key_type; + typedef std::pair value_type; + typedef Mapped mapped_type; + typedef Hash hasher; + typedef Pred key_equal; + typedef Alloc allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef _implementation-defined_ size_type; + typedef _implementation-defined_ difference_type; + typedef _implementation-defined_ iterator; + typedef _implementation-defined_ const_iterator; + typedef _implementation-defined_ local_iterator; + typedef _implementation-defined_ const_local_iterator; + typedef _implementation-defined_ node_type; + typedef _implementation-defined_ insert_return_type; + + // construct/copy/destruct + unordered_multimap(); + + explicit unordered_multimap(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + unordered_multimap(unordered_multimap const& other); + unordered_multimap(unordered_multimap&& other); + + explicit unordered_multimap(Allocator const& a); + unordered_multimap(unordered_multimap const& other, Allocator const& a); + unordered_multimap(unordered_multimap&& other, Allocator const& a); + + unordered_multimap(size_type n, allocator_type const& a); + unordered_multimap(size_type n, hasher const& hf, allocator_type const& a); + + unordered_multimap(initializer_list il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_multimap(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_multimap(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); + + template + unordered_multimap(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); + + ~unordered_multimap(); + + unordered_multimap& operator=(unordered_multimap const& other); + unordered_multimap& operator=(unordered_multimap&& other); + unordered_multimap& operator=(initializer_list il); + + // size and capacity + bool empty() const; + size_type size() const; + size_type max_size() const; + + // iterators + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + const_iterator cbegin() const; + const_iterator cend() const; + + // modifiers + template + std::pair + emplace(Args&&... args); + + template + iterator + emplace_hint(const_iterator hint, Args&&... args); + + std::pair + insert(value_type const& obj); + + std::pair + insert(value_type&& obj); + + insert_return_type insert(node_type&& nh); + + iterator insert(const_iterator hint, value_type const& obj); + iterator insert(const_iterator hint, value_type&& obj); + iterator insert(const_iterator hint, node_type&& nh); + + template + void insert(InputIterator first, InputIterator last); + + void insert(initializer_list il); + + node_type extract(const_iterator position); + node_type extract(key_type const& k); + + template + node_type extract(K&& k); + + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + size_type erase(key_type const& k); + + template + size_type erase(K&& k); + + void quick_erase(const_iterator position); + void erase_return_void(const_iterator position); + + void clear(); + void swap(unordered_multimap& other); + + template + void merge(unordered_multimap& source); + + template + void merge(unordered_multimap&& source); + + // observers + allocator_type get_allocator() const; + hasher hash_function() const; + key_equal key_eq() const; + + // lookup + iterator find(key_type const& k); + const_iterator find(key_type const& k) const; + + template + iterator + find(K const& k); + + template + const_iterator + find(K const& k) const; + + template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> + iterator + find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const&) eq; + + template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> + const_iterator + find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + + bool contains(key_type const& key) const; + + template + bool contains(K const& key); + + size_type count(key_type const& k) const; + + template + size_type count(K const& k) const; + + std::pair + equal_range(key_type const& k); + + std::pair + equal_range(key_type const& k) const; + + template + std::pair + equal_range(K const& k); + + template + std::pair + equal_range(K const& k) const; + + // bucket interface + size_type bucket_count() const; + size_type max_bucket_count() const; + size_type bucket_size(size_type n) const; + size_type bucket(key_type const& k) const; + + local_iterator begin(size_type n); + const_local_iterator begin(size_type n) const; + + local_iterator end(size_type n); + const_local_iterator end(size_type n) const; + + const_local_iterator cbegin(size_type n) const; + const_local_iterator cend(size_type n) const; + + // hash policy + float load_factor() const; + float max_load_factor() const; + + void max_load_factor(float z); + + void rehash(size_type n); + void reserve(size_type n); +}; + +// Equality Comparisons +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_multimap const& x, + unordered_multimap const& y); + +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_multimap const& x, + unordered_multimap const& y); + +// swap +template +void swap(unordered_multimap& x, + unordered_multimap& y); +----- + +--- + +=== Description + +*Template Parameters* + +[cols="1,1"] +|=== + +|_Key_ +|`Key` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Mapped_ +|`Mapped` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Hash_ +|A unary function object type that acts a hash function for a `Key`. It takes a single argument of type `Key` and returns a value of type `std::size_t`. + +|_Pred_ +|A binary function object that implements an equivalence relation on values of type `Key`. A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type bool. + +|_Alloc_ +|An allocator whose value type is the same as the container's value type. + +|=== + +The elements are organized into buckets. Keys with the same hash code are stored in the same bucket. + +The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash. + +=== Typedefs + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::pointer pointer; +---- + +`value_type*` if `allocator_type::pointer` is not defined. + +--- + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::const_pointer const_pointer; +---- + +`boost::pointer_to_other::type` if `allocator_type::const_pointer` is not defined. + + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ size_type; +---- + +An unsigned integral type. + +`size_type` can represent any non-negative value of `difference_type`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ difference_type; +---- + +A signed integral type. + +Is identical to the difference type of `iterator` and `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ iterator; +---- + +An iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +Convertible to `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ local_iterator; +---- + +An iterator with the same value type, difference type and pointer and reference type as iterator. + +A `local_iterator` object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_local_iterator; +---- + +A constant iterator with the same value type, difference type and pointer and reference type as const_iterator. + +A const_local_iterator object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ node_type; +---- + +See node_handle_map for details. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ insert_return_type; +---- + +Structure returned by inserting node_type. + +--- + +=== Constructors + +==== Default Constructor +```c++ +unordered_multimap(); +``` + +Constructs an empty container using `hasher()` as the hash function, +`key_equal()` as the key equality predicate, `allocator_type()` as the allocator +and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor +```c++ +explicit unordered_multimap(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash +function, `eq` as the key equality predicate, `a` as the allocator and a maximum +load factor of `1.0`. + +Postconditions:: `size() == 0` + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Copy Constructor +```c++ +unordered_multimap(unordered_multimap const& other); +``` + +The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator. + +If `Allocator::select_on_container_copy_construction` exists and has the right signature, the allocator will be constructed from its result. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Constructor +```c++ +unordered_multimap(unordered_multimap&& other); +``` + +The move constructor. + +Notes:: This is implemented using Boost.Move. + +Requires:: `value_type` is move-constructible. On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable. +So, for example, you can't return the container from a function. + +--- + +==== Allocator Constructor +```c++ +explicit unordered_multimap(Allocator const& a); +``` + +Constructs an empty container, using allocator `a`. + +--- + +==== Copy Constructor with Allocator +```c++ +unordered_multimap(unordered_multimap const& other, Allocator const& a); +``` + +Constructs an container, copying ``other``'s contained elements, hash function, predicate, maximum load factor, but using allocator `a`. + +--- + +==== Move Constructor with Allocator +```c++ +unordered_multimap(unordered_multimap&& other, Allocator const& a); +``` + +Construct a container moving ``other``'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate `a`. + +Notes:: This is implemented using Boost.Move. +Requires:: `value_type` is move insertable. + +--- + +==== Bucket Count Constructor with Allocator +```c++ +unordered_multimap(size_type n, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default hash function and key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Hasher and Allocator +```c++ +unordered_multimap(size_type n, hasher const& hf, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Initializer List Constructor +[source,c++,subs="quotes,macros"] +---- +unordered_multimap(initializer_list++<++value_type++>++ il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `il` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multimap(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Allocator +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multimap(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `a` as the allocator, with the default hash function and key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `hasher`, `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +==== Iterator Range Constructor with Bucket Count and Hasher +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multimap(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator, with the default key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +=== Destructor + +```c++ +~unordered_multimap(); +``` +Note:: The destructor is applied to every element, and all memory is deallocated + +--- + +=== Assignment + +==== Copy Assignment + +```c++ +unordered_multimap& operator=(unordered_multimap const& other); +``` + +The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator. + +If `Alloc::propagate_on_container_copy_assignment` exists and `Alloc::propagate_on_container_copy_assignment::value` is `true`, the allocator is overwritten, if not the copied elements are created using the existing allocator. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Assignment +```c++ +unordered_multimap& operator=(unordered_multimap&& other); +``` +The move assignment operator. + +If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator. + +Notes:: On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances. + +Requires:: `value_type` is move constructible. + +--- + +==== Initializer List Assignment +```c++ +unordered_multimap& operator=(initializer_list il); +``` + +Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] into the container and https://en.cppreference.com/w/cpp/named_req/CopyAssignable[CopyAssignable^]. + +=== Size and Capacity + +==== empty + +```c++ +bool empty() const; +``` + +Returns:: `size() == 0` + +--- + +==== size + +```c++ +size_type size() const; +``` + +Returns:: `std::distance(begin(), end())` + +--- + +==== max_size + +```c++ +size_type max_size() const; +``` + +Returns:: `size()` of the largest possible container. + +--- + +=== Iterators + +==== begin +```c++ +iterator begin(); +const_iterator begin() const; +``` + +Returns:: An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== end +```c++ +iterator end(); +const_iterator end() const; +``` + +Returns:: An iterator which refers to the past-the-end value for the container. + +--- + +==== cbegin +```c++ +const_iterator cbegin() const; +``` +Returns:: A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== cend +```c++ +const_iterator cend() const; +``` + +Returns:: A `const_iterator` which refers to the past-the-end value for the container. + +--- + +=== Modifiers + +==== emplace +```c++ +template +std::pair +emplace(Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== emplace_hint +```c++ +template +iterator +emplace_hint(const_iterator hint, Args&&... args); +``` + +Inserts an object, constructed with the arguments args, in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. +Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== Copy Insert +```c++ +std::pair +insert(value_type const& obj); +``` + +Inserts `obj` in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert +```c++ +std::pair +insert(value_type&& obj); +``` + +Inserts `obj` in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with `node_handle` +```c++ +insert_return_type +insert(node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh`. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns `end()`. Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_map`, but that is not supported yet. + +--- + +==== Copy Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type const& obj); +``` +Inserts `obj` in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type&& obj); +``` + +Inserts `obj` in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with Hint and `node_handle` +```c++ +iterator insert(const_iterator hint, node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh`. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns `end()`. + ++ +Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to hasher the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_map`, but that is not supported yet. + +--- + +==== Insert Iterator Range +```c++ +template +void insert(InputIterator first, InputIterator last); +``` + +Inserts a range of elements into the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert Initializer List +```c++ +void insert(initializer_list il); +``` + +Inserts a range of elements into the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Extract by Iterator +```c++ +node_type extract(const_iterator position); +``` + +Removes the element pointed to by `position`. + +Returns:: A `node_type` owning the element. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. + +--- + +==== Transparent Extract by Key +```c++ +template +node_type extract(K&& k); +``` + +Removes an element with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. + +--- + +==== Extract by Key +```c++ +node_type extract(key_type const& k); +``` + +Removes an element with key equivalent to `k`. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. + +==== Erase by Position + +```c++ +iterator erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Returns:: The iterator following `position` before the erasure. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In older versions this could be inefficient because it had to search through several buckets to find the position of the returned iterator. The data structure has been changed so that this is no longer the case, and the alternative erase methods have been deprecated. + +--- + +==== Erase Range + +```c++ +iterator erase(const_iterator first, const_iterator last); +``` + +Erases the elements in the range from `first` to `last`. + +Returns:: The iterator following the erased elements - i.e. `last`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +--- + +==== Transparent Erase by Key +```c++ +template +size_type erase(K&& k); +``` + +Erase all elements with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Erase by Key +```c++ +size_type erase(key_type const& k); +``` + +Erase all elements with key equivalent to `k`. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== quick_erase +```c++ +void quick_erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== erase_return_void +```c++ +void erase_return_void(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== clear +```c++ +void clear(); +``` + +Erases all elements in the container. + +Postconditions:: `size() == 0` + +Throws:: Never throws an exception. + +--- + +==== swap +```c++ +void swap(unordered_multimap& other); +``` + +Swaps the contents of the container with the parameter. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + +--- + +==== merge +```c++ +template +void merge(unordered_multimap& source); +``` + +Notes:: Does not support merging with a compatible `unordered_map` yet. + +--- + +==== merge (rvalue reference) +```c++ +template +void merge(unordered_multimap&& source); +``` + +Notes:: Does not support merging with a compatible `unordered_map` yet. + +--- + +=== Observers + +==== get_allocator +``` +allocator_type get_allocator() const; +``` + +--- + +==== hash_function +``` +hasher hash_function() const; +``` + +Returns:: The container's hash function. + +--- + +``` +key_equal key_eq() const; +``` + +Returns:: The container's key equality predicate + +--- + +=== Lookup + +==== find +```c++ +iterator find(key_type const& k); +const_iterator find(key_type const& k) const; + +template +iterator +find(K const& k); + +template +const_iterator +find(K const& k) const; + +template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> +iterator +find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq); + +template< + typename CompatibleKey, + typename CompatibleHash, + typename CompatiblePredicate> +const_iterator +find(CompatibleKey const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + +``` + +Returns:: An iterator pointing to an element with key equivalent to `k`, or `b.end()` if no such element exists. + +Notes:: The templated overloads containing `CompatibleKey`, `CompatibleHash` and `CompatiblePredicate` are non-standard extensions which allow you to use a compatible hash function and equality predicate for a key of a different type in order to avoid an expensive type cast. In general, its use is not encouraged and instead the `K` member function templates should be used. + +The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== contains +```c++ +template +bool contains(K const& key); +bool contains(key_type const& key) const; +``` + +Returns:: A boolean indicating whether or not there is an element with key equal to `key` in the container + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== count +```c++ +template +size_type count(K const& k) const; +size_type count(key_type const& k) const; +``` + +Returns:: The number of elements with key equivalent to `k`. + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== equal_range +```c++ +std::pair +equal_range(key_type const& k); + +std::pair +equal_range(key_type const& k) const; + +template +std::pair +equal_range(K const& k); + +template +std::pair +equal_range(K const& k) const; +``` + +Returns:: A range containing all elements with key equivalent to `k`. If the container doesn't contain any such elements, returns `std::make_pair(b.end(), b.end())`. + +Notes:: The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +=== Bucket Interface + +==== bucket_count +```c++ +size_type bucket_count() const; +``` + +Returns:: The number of buckets. + +--- + +==== max_bucket_count +```c++ +size_type max_bucket_count() const; +``` + +Returns:: An upper bound on the number of buckets. + +--- + +==== bucket_size +```c++ +size_type bucket_size(size_type n) const; +``` + +Requires:: `n < bucket_count()` + +Returns:: The number of elements in bucket `n`. + +--- + +==== bucket +```c++ +size_type bucket(key_type const& k) const; +``` + +Returns:: The index of the bucket which would contain an element with key `k`. + +Postconditions:: The return value is less than `bucket_count()`. + +--- + +==== begin + +```c++ +local_iterator begin(size_type n); +const_local_iterator begin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the first element in the bucket with index `n`. + +--- + +==== end +```c++ +local_iterator end(size_type n); +const_local_iterator end(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +==== cbegin +```c++ +const_local_iterator cbegin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the first element in the bucket with index `n`. + +--- + +==== cend +```c++ +const_local_iterator cend(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +=== Hash Policy + +==== load_factor +```c++ +float load_factor() const; +``` + +Returns:: The average number of elements per bucket. + +--- + +==== max_load_factor + +```c++ +float max_load_factor() const; +``` + +Returns:: Returns the current maximum load factor. + +--- + +==== Set max_load_factor +```c++ +void max_load_factor(float z); +``` + +Effects:: Changes the container's maximum load factor, using `z` as a hint. + +--- + + +==== rehash +```c++ +void rehash(size_type n); +``` + +Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor. + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +--- + +==== reserve +```c++ +void reserve(size_type n); +``` + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +=== Equality Comparisons + +==== operator== +```c++ +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_multimap const& x, + unordered_multimap const& y); +``` + +Return `true` if `x.size() == y.size()` and for every equivalent key group in `x`, there is a group in `y` for the same key, which is a permutation (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +--- + +==== operator!= +```c++ +template< + typename Key, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_multimap const& x, + unordered_multimap const& y); +``` + +Return `false` if `x.size() == y.size()` and for every equivalent key group in `x`, there is a group in `y` for the same key, which is a permutation (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +=== Swap +```c++ +template +void swap(unordered_multimap& x, + unordered_multimap& y); +``` + +Swaps the contents of `x` and `y`. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Effects:: `x.swap(y)` + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + + diff --git a/doc/unordered/unordered_multiset.adoc b/doc/unordered/unordered_multiset.adoc new file mode 100644 index 00000000..849f3fdd --- /dev/null +++ b/doc/unordered/unordered_multiset.adoc @@ -0,0 +1,1386 @@ +[#unordered_multiset] +== Class template unordered_multiset + +:idprefix: unordered_multiset_ + +`boost::unordered_multiset` — An unordered associative container that stores values. The same key can be stored multiple times. + +=== Synopsis + +[source,c++,subs=+quotes] +----- +// #include + +template< + typename Value, + typename Hash = boost::hash, + typename Pred = std::equal_to, + typename Alloc = std::allocator> > +class unordered_multiset { +public: + // types + typedef Value key_type; + typedef Value value_type; + typedef Hash hasher; + typedef Pred key_equal; + typedef Alloc allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef _implementation-defined_ size_type; + typedef _implementation-defined_ difference_type; + typedef _implementation-defined_ iterator; + typedef _implementation-defined_ const_iterator; + typedef _implementation-defined_ local_iterator; + typedef _implementation-defined_ const_local_iterator; + typedef _implementation-defined_ node_type; + typedef _implementation-defined_ insert_return_type; + + // construct/copy/destruct + unordered_multiset(); + + explicit unordered_multiset(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + unordered_multiset(unordered_multiset const& other); + unordered_multiset(unordered_multiset&& other); + + explicit unordered_multiset(Allocator const& a); + unordered_multiset(unordered_multiset const& other, Allocator const& a); + unordered_multiset(unordered_multiset&& other, Allocator const& a); + + unordered_multiset(size_type n, allocator_type const& a); + unordered_multiset(size_type n, hasher const& hf, allocator_type const& a); + + unordered_multiset(initializer_list il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_multiset(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_multiset(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); + + template + unordered_multiset(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); + + ~unordered_multiset(); + + unordered_multiset& operator=(unordered_multiset const& other); + unordered_multiset& operator=(unordered_multiset&& other); + unordered_multiset& operator=(initializer_list il); + + // size and capacity + bool empty() const; + size_type size() const; + size_type max_size() const; + + // iterators + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + const_iterator cbegin() const; + const_iterator cend() const; + + // modifiers + template + std::pair + emplace(Args&&... args); + + template + iterator + emplace_hint(const_iterator hint, Args&&... args); + + std::pair + insert(value_type const& obj); + + std::pair + insert(value_type&& obj); + + insert_return_type insert(node_type&& nh); + + iterator insert(const_iterator hint, value_type const& obj); + iterator insert(const_iterator hint, value_type&& obj); + iterator insert(const_iterator hint, node_type&& nh); + + template + void insert(InputIterator first, InputIterator last); + + void insert(initializer_list il); + + node_type extract(const_iterator position); + node_type extract(key_type const& k); + + template + node_type extract(K&& k); + + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + size_type erase(key_type const& k); + + template + size_type erase(K&& k); + + void quick_erase(const_iterator position); + void erase_return_void(const_iterator position); + + void clear(); + void swap(unordered_multiset& other); + + template + void merge(unordered_multiset& source); + + template + void merge(unordered_multiset&& source); + + // observers + allocator_type get_allocator() const; + hasher hash_function() const; + key_equal key_eq() const; + + // lookup + iterator find(key_type const& k); + const_iterator find(key_type const& k) const; + + template + iterator + find(K const& k); + + template + const_iterator + find(K const& k) const; + + template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> + iterator + find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const&) eq; + + template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> + const_iterator + find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + + bool contains(key_type const& key) const; + + template + bool contains(K const& key); + + size_type count(key_type const& k) const; + + template + size_type count(K const& k) const; + + std::pair + equal_range(key_type const& k); + + std::pair + equal_range(key_type const& k) const; + + template + std::pair + equal_range(K const& k); + + template + std::pair + equal_range(K const& k) const; + + // bucket interface + size_type bucket_count() const; + size_type max_bucket_count() const; + size_type bucket_size(size_type n) const; + size_type bucket(key_type const& k) const; + + local_iterator begin(size_type n); + const_local_iterator begin(size_type n) const; + + local_iterator end(size_type n); + const_local_iterator end(size_type n) const; + + const_local_iterator cbegin(size_type n) const; + const_local_iterator cend(size_type n) const; + + // hash policy + float load_factor() const; + float max_load_factor() const; + + void max_load_factor(float z); + + void rehash(size_type n); + void reserve(size_type n); +}; + +// Equality Comparisons +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_multiset const& x, + unordered_multiset const& y); + +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_multiset const& x, + unordered_multiset const& y); + +// swap +template +void swap(unordered_multiset& x, + unordered_multiset& y); +----- + +--- + +=== Description + +*Template Parameters* + +[cols="1,1"] +|=== + +|_Value_ +|`Value` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Hash_ +|A unary function object type that acts a hash function for a `Value`. It takes a single argument of type `Value` and returns a value of type `std::size_t`. + +|_Pred_ +|A binary function object that implements an equivalence relation on values of type `Value`. A binary function object that induces an equivalence relation on values of type `Value`. It takes two arguments of type `Value` and returns a value of type bool. + +|_Alloc_ +|An allocator whose value type is the same as the container's value type. + +|=== + +The elements are organized into buckets. Keys with the same hash code are stored in the same bucket. + +The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash. + +--- + +=== Typedefs + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::pointer pointer; +---- + +`value_type*` if `allocator_type::pointer` is not defined. + +--- + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::const_pointer const_pointer; +---- + +`boost::pointer_to_other::type` if `allocator_type::const_pointer` is not defined. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ size_type; +---- + +An unsigned integral type. + +`size_type` can represent any non-negative value of `difference_type`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ difference_type; +---- + +A signed integral type. + +Is identical to the difference type of `iterator` and `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ iterator; +---- + +An iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +Convertible to `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ local_iterator; +---- + +An iterator with the same value type, difference type and pointer and reference type as iterator. + +A `local_iterator` object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_local_iterator; +---- + +A constant iterator with the same value type, difference type and pointer and reference type as const_iterator. + +A const_local_iterator object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ node_type; +---- + +See node_handle_set for details. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ insert_return_type; +---- + +Structure returned by inserting node_type. + +--- + +=== Constructors + +==== Default Constructor +```c++ +unordered_multiset(); +``` + +Constructs an empty container using `hasher()` as the hash function, +`key_equal()` as the key equality predicate, `allocator_type()` as the allocator +and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor +```c++ +explicit unordered_multiset(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash +function, `eq` as the key equality predicate, `a` as the allocator and a maximum +load factor of `1.0`. + +Postconditions:: `size() == 0` + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Copy Constructor +```c++ +unordered_multiset(unordered_multiset const& other); +``` + +The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator. + +If `Allocator::select_on_container_copy_construction` exists and has the right signature, the allocator will be constructed from its result. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Constructor +```c++ +unordered_multiset(unordered_multiset&& other); +``` + +The move constructor. + +Notes:: This is implemented using Boost.Move. + +Requires:: `value_type` is move-constructible. On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable. +So, for example, you can't return the container from a function. + +--- + +==== Allocator Constructor +```c++ +explicit unordered_multiset(Allocator const& a); +``` + +Constructs an empty container, using allocator `a`. + +--- + +==== Copy Constructor with Allocator +```c++ +unordered_multiset(unordered_multiset const& other, Allocator const& a); +``` + +Constructs an container, copying ``other``'s contained elements, hash function, predicate, maximum load factor, but using allocator `a`. + +--- + +==== Move Constructor with Allocator +```c++ +unordered_multiset(unordered_multiset&& other, Allocator const& a); +``` + +Construct a container moving ``other``'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate `a`. + +Notes:: This is implemented using Boost.Move. +Requires:: `value_type` is move insertable. + +--- + +==== Bucket Count Constructor with Allocator +```c++ +unordered_multiset(size_type n, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default hash function and key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Hasher and Allocator +```c++ +unordered_multiset(size_type n, hasher const& hf, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Initializer List Constructor +[source,c++,subs="quotes,macros"] +---- +unordered_multiset(initializer_list++<++value_type++>++ il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `il` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multiset(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Allocator +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multiset(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `a` as the allocator, with the default hash function and key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `hasher`, `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +==== Iterator Range Constructor with Bucket Count and Hasher +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_multiset(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator, with the default key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +=== Destructor + +```c++ +~unordered_multiset(); +``` +Note:: The destructor is applied to every element, and all memory is deallocated + +--- + +=== Assignment + +==== Copy Assignment + +```c++ +unordered_multiset& operator=(unordered_multiset const& other); +``` + +The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator. + +If `Alloc::propagate_on_container_copy_assignment` exists and `Alloc::propagate_on_container_copy_assignment::value` is `true`, the allocator is overwritten, if not the copied elements are created using the existing allocator. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Assignment +```c++ +unordered_multiset& operator=(unordered_multiset&& other); +``` +The move assignment operator. + +If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator. + +Notes:: On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances. + +Requires:: `value_type` is move constructible. + +--- + +==== Initializer List Assignment +```c++ +unordered_multiset& operator=(initializer_list il); +``` + +Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] into the container and https://en.cppreference.com/w/cpp/named_req/CopyAssignable[CopyAssignable^]. + +=== Size and Capacity + +==== empty + +```c++ +bool empty() const; +``` + +Returns:: `size() == 0` + +--- + +==== size + +```c++ +size_type size() const; +``` + +Returns:: `std::distance(begin(), end())` + +--- + +==== max_size + +```c++ +size_type max_size() const; +``` + +Returns:: `size()` of the largest possible container. + +--- + +=== Iterators + +==== begin +```c++ +iterator begin(); +const_iterator begin() const; +``` + +Returns:: An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== end +```c++ +iterator end(); +const_iterator end() const; +``` + +Returns:: An iterator which refers to the past-the-end value for the container. + +--- + +==== cbegin +```c++ +const_iterator cbegin() const; +``` +Returns:: A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== cend +```c++ +const_iterator cend() const; +``` + +Returns:: A `const_iterator` which refers to the past-the-end value for the container. + +--- + +=== Modifiers + +==== emplace +```c++ +template +std::pair +emplace(Args&&... args); +``` + +Inserts an object, constructed with the arguments args, in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== emplace_hint +```c++ +template +iterator +emplace_hint(const_iterator hint, Args&&... args); +``` + +Inserts an object, constructed with the arguments args, in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. +Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== Copy Insert +```c++ +std::pair +insert(value_type const& obj); +``` + +Inserts `obj` in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert +```c++ +std::pair +insert(value_type&& obj); +``` + +Inserts `obj` in the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with `node_handle` +```c++ +insert_return_type +insert(node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh`. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns `end()`. Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_set`, but that is not supported yet. + +--- + +==== Copy Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type const& obj); +``` + +Inserts `obj` in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type&& obj); +``` + +Inserts `obj` in the container. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: An iterator pointing to the inserted element. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with Hint and `node_handle` +```c++ +iterator insert(const_iterator hint, node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh`. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns `end()`. + +Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to hasher the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_set`, but that is not supported yet. + +--- + +==== Insert Iterator Range +```c++ +template +void insert(InputIterator first, InputIterator last); +``` + +Inserts a range of elements into the container. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert Initializer List +```c++ +void insert(initializer_list il); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Extract by Iterator +```c++ +node_type extract(const_iterator position); +``` + +Removes the element pointed to by `position`. + +Returns:: A `node_type` owning the element. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. + +--- + +==== Transparent Extract by Value +```c++ +template +node_type extract(K&& k); +``` + +Removes an element with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. + +--- + +==== Extract by Value +```c++ +node_type extract(key_type const& k); +``` + +Removes an element with key equivalent to `k`. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. + +==== Erase by Position + +```c++ +iterator erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Returns:: The iterator following `position` before the erasure. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In older versions this could be inefficient because it had to search through several buckets to find the position of the returned iterator. The data structure has been changed so that this is no longer the case, and the alternative erase methods have been deprecated. + +--- + +==== Erase Range + +```c++ +iterator erase(const_iterator first, const_iterator last); +``` + +Erases the elements in the range from `first` to `last`. + +Returns:: The iterator following the erased elements - i.e. `last`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +--- + +==== Transparent Erase by Value +```c++ +template +size_type erase(K&& k); +``` + +Erase all elements with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Erase by Value +```c++ +size_type erase(key_type const& k); +``` + +Erase all elements with key equivalent to `k`. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== quick_erase +```c++ +void quick_erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== erase_return_void +```c++ +void erase_return_void(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== clear +```c++ +void clear(); +``` + +Erases all elements in the container. + +Postconditions:: `size() == 0` + +Throws:: Never throws an exception. + +--- + +==== swap +```c++ +void swap(unordered_multiset& other); +``` + +Swaps the contents of the container with the parameter. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + +--- + +==== merge +```c++ +template +void merge(unordered_multiset& source); +``` + +Notes:: Does not support merging with a compatible `unordered_set` yet. + +--- + +==== merge (rvalue reference) +```c++ +template +void merge(unordered_multiset&& source); +``` + +Notes:: Does not support merging with a compatible `unordered_set` yet. + +--- + +=== Observers + +==== get_allocator +``` +allocator_type get_allocator() const; +``` + +==== hash_function +``` +hasher hash_function() const; +``` + +Returns:: The container's hash function. + +--- + +``` +key_equal key_eq() const; +``` + +Returns:: The container's key equality predicate + +--- + +=== Lookup + +==== find +```c++ +iterator find(key_type const& k); +const_iterator find(key_type const& k) const; + +template +iterator +find(K const& k); + +template +const_iterator +find(K const& k) const; + +template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> +iterator +find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq); + +template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> +const_iterator +find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + +``` + +Returns:: An iterator pointing to an element with key equivalent to `k`, or `b.end()` if no such element exists. + +Notes:: The templated overloads containing `CompatibleValue`, `CompatibleHash` and `CompatiblePredicate` are non-standard extensions which allow you to use a compatible hash function and equality predicate for a key of a different type in order to avoid an expensive type cast. In general, its use is not encouraged and instead the `K` member function templates should be used. + +The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== contains +```c++ +template +bool contains(K const& key); +bool contains(key_type const& key) const; +``` + +Returns:: A boolean indicating whether or not there is an element with key equal to `key` in the container + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== count +```c++ +template +size_type count(K const& k) const; +size_type count(key_type const& k) const; +``` + +Returns:: The number of elements with key equivalent to `k`. + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== equal_range +```c++ +std::pair +equal_range(key_type const& k); + +std::pair +equal_range(key_type const& k) const; + +template +std::pair +equal_range(K const& k); + +template +std::pair +equal_range(K const& k) const; +``` + +Returns:: A range containing all elements with key equivalent to `k`. If the container doesn't contain any such elements, returns `std::make_pair(b.end(), b.end())`. + +Notes:: The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +=== Bucket Interface + +==== bucket_count +```c++ +size_type bucket_count() const; +``` + +Returns:: The number of buckets. + +--- + +==== max_bucket_count +```c++ +size_type max_bucket_count() const; +``` + +Returns:: An upper bound on the number of buckets. + +--- + +==== bucket_size +```c++ +size_type bucket_size(size_type n) const; +``` + +Requires:: `n < bucket_count()` + +Returns:: The number of elements in bucket `n`. + +--- + +==== bucket +```c++ +size_type bucket(key_type const& k) const; +``` + +Returns:: The index of the bucket which would contain an element with key `k`. + +Postconditions:: The return value is less than `bucket_count()`. + +--- + +==== begin + +```c++ +local_iterator begin(size_type n); +const_local_iterator begin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the first element in the bucket with index `n`. + +--- + +==== end +```c++ +local_iterator end(size_type n); +const_local_iterator end(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +==== cbegin +```c++ +const_local_iterator cbegin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the first element in the bucket with index `n`. + +--- + +==== cend +```c++ +const_local_iterator cend(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +=== Hash Policy + +==== load_factor +```c++ +float load_factor() const; +``` + +Returns:: The average number of elements per bucket. + +--- + +==== max_load_factor + +```c++ +float max_load_factor() const; +``` + +Returns:: Returns the current maximum load factor. + +--- + +==== Set max_load_factor +```c++ +void max_load_factor(float z); +``` + +Effects:: Changes the container's maximum load factor, using `z` as a hint. + +--- + + +==== rehash +```c++ +void rehash(size_type n); +``` + +Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor. + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +--- + +==== reserve +```c++ +void reserve(size_type n); +``` + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +=== Equality Comparisons + +==== operator== +```c++ +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_multiset const& x, + unordered_multiset const& y); +``` + +Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +--- + +==== operator!= +```c++ +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_multiset const& x, + unordered_multiset const& y); +``` + +Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +=== Swap +```c++ +template +void swap(unordered_multiset& x, + unordered_multiset& y); +``` + +Swaps the contents of `x` and `y`. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Effects:: `x.swap(y)` + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + + diff --git a/doc/unordered/unordered_set.adoc b/doc/unordered/unordered_set.adoc new file mode 100644 index 00000000..d453eb7d --- /dev/null +++ b/doc/unordered/unordered_set.adoc @@ -0,0 +1,1387 @@ +[#unordered_set] +== Class template unordered_set + +:idprefix: unordered_set_ + +`boost::unordered_set` — An unordered associative container that stores unique values. + +=== Synopsis + +[source,c++,subs=+quotes] +----- +// #include + +template< + typename Value, + typename Hash = boost::hash, + typename Pred = std::equal_to, + typename Alloc = std::allocator> > +class unordered_set { +public: + // types + typedef Value key_type; + typedef Value value_type; + typedef Hash hasher; + typedef Pred key_equal; + typedef Alloc allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef _implementation-defined_ size_type; + typedef _implementation-defined_ difference_type; + typedef _implementation-defined_ iterator; + typedef _implementation-defined_ const_iterator; + typedef _implementation-defined_ local_iterator; + typedef _implementation-defined_ const_local_iterator; + typedef _implementation-defined_ node_type; + typedef _implementation-defined_ insert_return_type; + + // construct/copy/destruct + unordered_set(); + + explicit unordered_set(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + unordered_set(unordered_set const& other); + unordered_set(unordered_set&& other); + + explicit unordered_set(Allocator const& a); + unordered_set(unordered_set const& other, Allocator const& a); + unordered_set(unordered_set&& other, Allocator const& a); + + unordered_set(size_type n, allocator_type const& a); + unordered_set(size_type n, hasher const& hf, allocator_type const& a); + + unordered_set(initializer_list il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_set(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); + + template + unordered_set(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); + + template + unordered_set(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); + + ~unordered_set(); + + unordered_set& operator=(unordered_set const& other); + unordered_set& operator=(unordered_set&& other); + unordered_set& operator=(initializer_list il); + + // size and capacity + bool empty() const; + size_type size() const; + size_type max_size() const; + + // iterators + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + const_iterator cbegin() const; + const_iterator cend() const; + + // modifiers + template + std::pair + emplace(Args&&... args); + + template + iterator + emplace_hint(const_iterator hint, Args&&... args); + + std::pair + insert(value_type const& obj); + + std::pair + insert(value_type&& obj); + + insert_return_type insert(node_type&& nh); + + iterator insert(const_iterator hint, value_type const& obj); + iterator insert(const_iterator hint, value_type&& obj); + iterator insert(const_iterator hint, node_type&& nh); + + template + void insert(InputIterator first, InputIterator last); + + void insert(initializer_list il); + + node_type extract(const_iterator position); + node_type extract(key_type const& k); + + template + node_type extract(K&& k); + + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + size_type erase(key_type const& k); + + template + size_type erase(K&& k); + + void quick_erase(const_iterator position); + void erase_return_void(const_iterator position); + + void clear(); + void swap(unordered_set& other); + + template + void merge(unordered_set& source); + + template + void merge(unordered_set&& source); + + // observers + allocator_type get_allocator() const; + hasher hash_function() const; + key_equal key_eq() const; + + // lookup + iterator find(key_type const& k); + const_iterator find(key_type const& k) const; + + template + iterator + find(K const& k); + + template + const_iterator + find(K const& k) const; + + template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> + iterator + find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const&) eq; + + template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> + const_iterator + find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + + bool contains(key_type const& key) const; + + template + bool contains(K const& key); + + size_type count(key_type const& k) const; + + template + size_type count(K const& k) const; + + std::pair + equal_range(key_type const& k); + + std::pair + equal_range(key_type const& k) const; + + template + std::pair + equal_range(K const& k); + + template + std::pair + equal_range(K const& k) const; + + // bucket interface + size_type bucket_count() const; + size_type max_bucket_count() const; + size_type bucket_size(size_type n) const; + size_type bucket(key_type const& k) const; + + local_iterator begin(size_type n); + const_local_iterator begin(size_type n) const; + + local_iterator end(size_type n); + const_local_iterator end(size_type n) const; + + const_local_iterator cbegin(size_type n) const; + const_local_iterator cend(size_type n) const; + + // hash policy + float load_factor() const; + float max_load_factor() const; + + void max_load_factor(float z); + + void rehash(size_type n); + void reserve(size_type n); +}; + +// Equality Comparisons +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_set const& x, + unordered_set const& y); + +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_set const& x, + unordered_set const& y); + +// swap +template +void swap(unordered_set& x, + unordered_set& y); +----- + +--- + +=== Description + +*Template Parameters* + +[cols="1,1"] +|=== + +|_Value_ +|`Value` must be https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container (i.e. `allocator_traits` can destroy it). + +|_Hash_ +|A unary function object type that acts a hash function for a `Value`. It takes a single argument of type `Value` and returns a value of type `std::size_t`. + +|_Pred_ +|A binary function object that implements an equivalence relation on values of type `Value`. A binary function object that induces an equivalence relation on values of type `Value`. It takes two arguments of type `Value` and returns a value of type bool. + +|_Alloc_ +|An allocator whose value type is the same as the container's value type. + +|=== + +The elements are organized into buckets. Keys with the same hash code are stored in the same bucket. + +The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash. + +--- + +=== Typedefs + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::pointer pointer; +---- + +`value_type*` if `allocator_type::pointer` is not defined. + +--- + +[source,c++,subs=+quotes] +---- +typedef typename allocator_type::const_pointer const_pointer; +---- + +`boost::pointer_to_other::type` if `allocator_type::const_pointer` is not defined. + + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ size_type; +---- + +An unsigned integral type. + +`size_type` can represent any non-negative value of `difference_type`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ difference_type; +---- + +A signed integral type. + +Is identical to the difference type of `iterator` and `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ iterator; +---- + +An iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +Convertible to `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ local_iterator; +---- + +An iterator with the same value type, difference type and pointer and reference type as iterator. + +A `local_iterator` object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_local_iterator; +---- + +A constant iterator with the same value type, difference type and pointer and reference type as const_iterator. + +A const_local_iterator object can be used to iterate through a single bucket. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ node_type; +---- + +See node_handle_set for details. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ insert_return_type; +---- + +Structure returned by inserting node_type. + +--- + +=== Constructors + +==== Default Constructor +```c++ +unordered_set(); +``` + +Constructs an empty container using `hasher()` as the hash function, +`key_equal()` as the key equality predicate, `allocator_type()` as the allocator +and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor +```c++ +explicit unordered_set(size_type n, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash +function, `eq` as the key equality predicate, `a` as the allocator and a maximum +load factor of `1.0`. + +Postconditions:: `size() == 0` + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Copy Constructor +```c++ +unordered_set(unordered_set const& other); +``` + +The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator. + +If `Allocator::select_on_container_copy_construction` exists and has the right signature, the allocator will be constructed from its result. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Constructor +```c++ +unordered_set(unordered_set&& other); +``` + +The move constructor. + +Notes:: This is implemented using Boost.Move. + +Requires:: `value_type` is move-constructible. On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable. +So, for example, you can't return the container from a function. + +--- + +==== Allocator Constructor +```c++ +explicit unordered_set(Allocator const& a); +``` + +Constructs an empty container, using allocator `a`. + +--- + +==== Copy Constructor with Allocator +```c++ +unordered_set(unordered_set const& other, Allocator const& a); +``` + +Constructs an container, copying ``other``'s contained elements, hash function, predicate, maximum load factor, but using allocator `a`. + +--- + +==== Move Constructor with Allocator +```c++ +unordered_set(unordered_set&& other, Allocator const& a); +``` + +Construct a container moving ``other``'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate `a`. + +Notes:: This is implemented using Boost.Move. +Requires:: `value_type` is move insertable. + +--- + +==== Bucket Count Constructor with Allocator +```c++ +unordered_set(size_type n, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default hash function and key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Hasher and Allocator +```c++ +unordered_set(size_type n, hasher const& hf, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default key equality predicate, `a` as the allocator and a maximum load factor of `1.0`. + +Postconditions:: `size() == 0` +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Initializer List Constructor +[source,c++,subs="quotes,macros"] +---- +unordered_set(initializer_list++<++value_type++>++ il, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `il` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_set(InputIterator f, + InputIterator l, + size_type n = _implementation-defined_, + hasher const& hf = hasher(), + key_equal const& eq = key_equal(), + allocator_type const& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eq` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Allocator +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_set(InputIterator f, + InputIterator l, + size_type n, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `a` as the allocator, with the default hash function and key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `hasher`, `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +==== Iterator Range Constructor with Bucket Count and Hasher +[source,c++,subs="quotes,macros"] +---- +template++<++typename InputIterator++>++ +unordered_set(InputIterator f, + InputIterator l, + size_type n, + hasher const& hf, + allocator_type const& a); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator, with the default key equality predicate and a maximum load factor of `1.0` and inserts the elements from `[f, l)` into it. + +Requires:: `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +=== Destructor + +```c++ +~unordered_set(); +``` +Note:: The destructor is applied to every element, and all memory is deallocated + +--- + +=== Assignment + +==== Copy Assignment + +```c++ +unordered_set& operator=(unordered_set const& other); +``` + +The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator. + +If `Alloc::propagate_on_container_copy_assignment` exists and `Alloc::propagate_on_container_copy_assignment::value` is `true`, the allocator is overwritten, if not the copied elements are created using the existing allocator. + +Requires:: `value_type` is copy constructible + +--- + +==== Move Assignment +```c++ +unordered_set& operator=(unordered_set&& other); +``` +The move assignment operator. + +If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator. + +Notes:: On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances. + +Requires:: `value_type` is move constructible. + +--- + +==== Initializer List Assignment +```c++ +unordered_set& operator=(initializer_list il); +``` + +Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] into the container and https://en.cppreference.com/w/cpp/named_req/CopyAssignable[CopyAssignable^]. + +=== Size and Capacity + +==== empty + +```c++ +bool empty() const; +``` + +Returns:: `size() == 0` + +--- + +==== size + +```c++ +size_type size() const; +``` + +Returns:: `std::distance(begin(), end())` + +--- + +==== max_size + +```c++ +size_type max_size() const; +``` + +Returns:: `size()` of the largest possible container. + +--- + +=== Iterators + +==== begin +```c++ +iterator begin(); +const_iterator begin() const; +``` + +Returns:: An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== end +```c++ +iterator end(); +const_iterator end() const; +``` + +Returns:: An iterator which refers to the past-the-end value for the container. + +--- + +==== cbegin +```c++ +const_iterator cbegin() const; +``` +Returns:: A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. + +--- + +==== cend +```c++ +const_iterator cend() const; +``` + +Returns:: A `const_iterator` which refers to the past-the-end value for the container. + +--- + +=== Modifiers + +==== emplace +```c++ +template +std::pair +emplace(Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent value. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: The bool component of the return type is true if an insert took place. + +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== emplace_hint +```c++ +template +iterator +emplace_hint(const_iterator hint, Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent value. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `args`. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. +Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +Pointers and references to elements are never invalidated. +If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`. + +--- + +==== Copy Insert +```c++ +std::pair +insert(value_type const& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: The bool component of the return type is true if an insert took place. If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert +```c++ +std::pair +insert(value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: The bool component of the return type is true if an insert took place. If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with `node_handle` +```c++ +insert_return_type +insert(node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh` if and only if there is no element in the container with an equivalent key. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty, returns an `insert_return_type` with: `inserted` equal to `false`, `position` equal to `end()` and `node` empty. Otherwise if there was already an element with an equivalent key, returns an `insert_return_type` with: `inserted` equal to `false`, `position` pointing to a matching element and `node` contains the node from `nh`. Otherwise if the insertion succeeded, returns an `insert_return_type` with: `inserted` equal to `true`, `position` pointing to the newly inserted element and `node` empty. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_multiset`, but that is not supported yet. + +--- + +==== Copy Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type const& obj); +``` +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Move Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. + +Returns:: If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. + +Throws:: If an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert with Hint and `node_handle` +```c++ +iterator insert(const_iterator hint, node_type&& nh); +``` + +If `nh` is empty, has no effect. + +Otherwise inserts the element owned by `nh` if and only if there is no element in the container with an equivalent key. + +If there is already an element in the container with an equivalent key has no effect on `nh` (i.e. `nh` still contains the node.) + +`hint` is a suggestion to where the element should be inserted. + +Requires:: `nh` is empty or `nh.get_allocator()` is equal to the container's allocator. + +Returns:: If `nh` was empty returns `end()`. If there was already an element in the container with an equivalent key returns an iterator pointing to that. Otherwise returns an iterator pointing to the newly inserted element. + +Throws:: If an exception is thrown by an operation other than a call to hasher the function has no effect. + +Notes:: The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_multiset`, but that is not supported yet. + +--- + +==== Insert Iterator Range +```c++ +template +void insert(InputIterator first, InputIterator last); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Insert Initializer List +```c++ +void insert(initializer_list il); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +Requires:: `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into `X` from `*first`. + +Throws:: When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. + +Notes:: Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. Pointers and references to elements are never invalidated. + +--- + +==== Extract by Iterator +```c++ +node_type extract(const_iterator position); +``` + +Removes the element pointed to by `position`. + +Returns:: A `node_type` owning the element. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multiset`, but that is not supported yet. + +--- + +==== Transparent Extract by Value +```c++ +template +node_type extract(K&& k); +``` + +Removes an element with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multiset`, but that is not supported yet. + +--- + +==== Extract by Value +```c++ +node_type extract(key_type const& k); +``` + +Removes an element with key equivalent to `k`. + +Returns:: A `node_type` owning the element if found, otherwise an empty `node_type`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In C++17 a node extracted using this method can be inserted into a compatible `unordered_multiset`, but that is not supported yet. + +==== Erase by Position + +```c++ +iterator erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Returns:: The iterator following `position` before the erasure. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +Notes:: In older versions this could be inefficient because it had to search through several buckets to find the position of the returned iterator. The data structure has been changed so that this is no longer the case, and the alternative erase methods have been deprecated. + +--- + +==== Erase Range + +```c++ +iterator erase(const_iterator first, const_iterator last); +``` + +Erases the elements in the range from `first` to `last`. + +Returns:: The iterator following the erased elements - i.e. `last`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +--- + +==== Transparent Erase by Value +```c++ +template +size_type erase(K&& k); +``` + +Erase all elements with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Erase by Value +```c++ +size_type erase(key_type const& k); +``` + +Erase all elements with key equivalent to `k`. + +Returns:: The number of elements erased. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== quick_erase +```c++ +void quick_erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== erase_return_void +```c++ +void erase_return_void(const_iterator position); +``` + +Erase the element pointed to by `position`. + +Throws:: Only throws an exception if it is thrown by `hasher` or `key_equal`. In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations. + +Notes:: This method was implemented because returning an iterator to the next element from erase was expensive, but the container has been redesigned so that is no longer the case. So this method is now deprecated. + +--- + +==== clear +```c++ +void clear(); +``` + +Erases all elements in the container. + +Postconditions:: `size() == 0` + +Throws:: Never throws an exception. + +--- + +==== swap +```c++ +void swap(unordered_set& other); +``` + +Swaps the contents of the container with the parameter. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + +--- + +==== merge +```c++ +template +void merge(unordered_set& source); +``` + +Notes:: Does not support merging with a compatible `unordered_multiset` yet. + +--- + +==== merge (rvalue reference) +```c++ +template +void merge(unordered_set&& source); +``` + +Notes:: Does not support merging with a compatible `unordered_multiset` yet. + +--- + +=== Observers + +==== get_allocator +``` +allocator_type get_allocator() const; +``` + +==== hash_function +``` +hasher hash_function() const; +``` + +Returns:: The container's hash function. + +--- + +``` +key_equal key_eq() const; +``` + +Returns:: The container's key equality predicate + +--- + +=== Lookup + +==== find +```c++ +iterator find(key_type const& k); +const_iterator find(key_type const& k) const; + +template +iterator +find(K const& k); + +template +const_iterator +find(K const& k) const; + +template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> +iterator +find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq); + +template< + typename CompatibleValue, + typename CompatibleHash, + typename CompatiblePredicate> +const_iterator +find(CompatibleValue const& k, + CompatibleHash const& hash, + CompatiblePredicate const& eq) const; + +``` + +Returns:: An iterator pointing to an element with key equivalent to `k`, or `b.end()` if no such element exists. + +Notes:: The templated overloads containing `CompatibleValue`, `CompatibleHash` and `CompatiblePredicate` are non-standard extensions which allow you to use a compatible hash function and equality predicate for a key of a different type in order to avoid an expensive type cast. In general, its use is not encouraged and instead the `K` member function templates should be used. + +The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== contains +```c++ +template +bool contains(K const& key); +bool contains(key_type const& key) const; +``` + +Returns:: A boolean indicating whether or not there is an element with key equal to `key` in the container + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== count +```c++ +template +size_type count(K const& k) const; +size_type count(key_type const& k) const; +``` + +Returns:: The number of elements with key equivalent to `k`. + +Notes:: The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +==== equal_range +```c++ +std::pair +equal_range(key_type const& k); + +std::pair +equal_range(key_type const& k) const; + +template +std::pair +equal_range(K const& k); + +template +std::pair +equal_range(K const& k) const; +``` + +Returns:: A range containing all elements with key equivalent to `k`. If the container doesn't contain any such elements, returns `std::make_pair(b.end(), b.end())`. + +Notes:: The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Value` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Value` type. + +--- + +=== Bucket Interface + +==== bucket_count +```c++ +size_type bucket_count() const; +``` + +Returns:: The number of buckets. + +--- + +==== max_bucket_count +```c++ +size_type max_bucket_count() const; +``` + +Returns:: An upper bound on the number of buckets. + +--- + +==== bucket_size +```c++ +size_type bucket_size(size_type n) const; +``` + +Requires:: `n < bucket_count()` + +Returns:: The number of elements in bucket `n`. + +--- + +==== bucket +```c++ +size_type bucket(key_type const& k) const; +``` + +Returns:: The index of the bucket which would contain an element with key `k`. + +Postconditions:: The return value is less than `bucket_count()`. + +--- + +==== begin + +```c++ +local_iterator begin(size_type n); +const_local_iterator begin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the first element in the bucket with index `n`. + +--- + +==== end +```c++ +local_iterator end(size_type n); +const_local_iterator end(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +==== cbegin +```c++ +const_local_iterator cbegin(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the first element in the bucket with index `n`. + +--- + +==== cend +```c++ +const_local_iterator cend(size_type n) const; +``` + +Requires:: `n` shall be in the range `[0, bucket_count())`. + +Returns:: A constant local iterator pointing the 'one past the end' element in the bucket with index `n`. + +--- + +=== Hash Policy + +==== load_factor +```c++ +float load_factor() const; +``` + +Returns:: The average number of elements per bucket. + +--- + +==== max_load_factor + +```c++ +float max_load_factor() const; +``` + +Returns:: Returns the current maximum load factor. + +--- + +==== Set max_load_factor +```c++ +void max_load_factor(float z); +``` + +Effects:: Changes the container's maximum load factor, using `z` as a hint. + +--- + + +==== rehash +```c++ +void rehash(size_type n); +``` + +Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor. + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +--- + +==== reserve +```c++ +void reserve(size_type n); +``` + +Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + +Throws:: The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +=== Equality Comparisons + +==== operator== +```c++ +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator==(unordered_set const& x, + unordered_set const& y); +``` + +Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +--- + +==== operator!= +```c++ +template< + typename Value, + typename Mapped, + typename Hash, + typename Pred, + typename Alloc> +bool operator!=(unordered_set const& x, + unordered_set const& y); +``` + +Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +Notes:: The behavior of this function was changed to match the C++11 standard in Boost 1.48. Behavior is undefined if the two containers don't have equivalent equality predicates. + +=== Swap +```c++ +template +void swap(unordered_set& x, + unordered_set& y); +``` + +Swaps the contents of `x` and `y`. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +Effects:: `x.swap(y)` + +Throws:: Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`. + +Notes:: The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors. + +