mirror of
https://github.com/boostorg/unordered.git
synced 2025-06-25 11:51:33 +02:00
Compare commits
42 Commits
svn-trunk
...
boost-1.41
Author | SHA1 | Date | |
---|---|---|---|
c97ad81672 | |||
a3e57838ed | |||
2221c8334e | |||
584eaad67a | |||
14e09a5456 | |||
06b0b1d31c | |||
3529bc00dc | |||
1e7fe6a2d0 | |||
df1dad5cb6 | |||
1bc3ae3d9d | |||
60ecf12779 | |||
241316e0d9 | |||
9c43533655 | |||
ae09b0dd24 | |||
b018f8b173 | |||
0b4241833d | |||
e911a8011b | |||
f02cc7775d | |||
4e6b5de196 | |||
fb71e0618d | |||
694398f0e1 | |||
ab62d33495 | |||
b475ba05c0 | |||
60e3e96b48 | |||
c0e472755e | |||
6f45d36d97 | |||
2e9cf20cd0 | |||
f7c664a359 | |||
0921f8076d | |||
b8e8ffa242 | |||
07e715fceb | |||
89ab17cce5 | |||
517e39fc23 | |||
93141c26b9 | |||
dd2a994874 | |||
6571648bac | |||
f20f72bade | |||
4e4f99d51f | |||
56b9e0da1a | |||
4f27a146ef | |||
c8d0cb88ad | |||
5a898f2419 |
@ -8,11 +8,11 @@ path-constant admonishment_location : ../../../../doc/src/images ;
|
||||
|
||||
xml unordered : unordered.qbk ;
|
||||
boostbook standalone : unordered :
|
||||
<xsl:param>admon.graphics.path=images/
|
||||
<xsl:param>navig.graphics.path=images/
|
||||
<xsl:param>html.stylesheet=boostbook.css
|
||||
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
|
||||
<xsl:param>boost.root=../../../..
|
||||
<xsl:param>boost.libraries=../../../libraries.htm
|
||||
<xsl:param>navig.graphics=1
|
||||
|
||||
<xsl:param>chunk.first.sections=1
|
||||
<xsl:param>chunk.section.depth=2
|
||||
<xsl:param>generate.section.toc.level=2
|
||||
@ -23,9 +23,6 @@ boostbook standalone : unordered :
|
||||
<xsl:param>boost.compact.function=0
|
||||
<xsl:param>boost.compact.enum=0
|
||||
|
||||
<dependency>css
|
||||
<dependency>images
|
||||
|
||||
# PDF Options:
|
||||
# TOC Generation: this is needed for FOP-0.9 and later:
|
||||
<xsl:param>fop1.extensions=0
|
||||
@ -51,11 +48,6 @@ boostbook standalone : unordered :
|
||||
<format>pdf:<xsl:param>img.src.path=$(images_location)/
|
||||
#<format>pdf:<xsl:param>admon.graphics.path=$(admonishment_location)
|
||||
<format>pdf:<xsl:param>draft.mode="no"
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
|
||||
;
|
||||
|
||||
install css : [ glob $(BOOST_ROOT)/doc/src/*.css ]
|
||||
: <location>html ;
|
||||
install images : [ glob $(BOOST_ROOT)/doc/src/images/*.png ]
|
||||
: <location>html/images ;
|
||||
explicit css ;
|
||||
explicit images ;
|
||||
|
@ -1,3 +1,8 @@
|
||||
<!--
|
||||
Copyright Daniel James 2008-2009
|
||||
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)
|
||||
-->
|
||||
<section id="unordered.bibliography">
|
||||
<title>Bibliography</title>
|
||||
<bibliography>
|
||||
|
@ -115,6 +115,15 @@ or close to the hint - unless your hint is unreasonably small or large.
|
||||
[table Methods for Controlling Bucket Size
|
||||
[[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.]
|
||||
|
@ -10,7 +10,7 @@
|
||||
Initial review version, for the review conducted from 7th December 2007 to
|
||||
16th December 2007.
|
||||
|
||||
[h2 1.35.0 Add-on - 31st Match 2008]
|
||||
[h2 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.
|
||||
@ -31,7 +31,76 @@ First official release.
|
||||
* 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 and hash functions
|
||||
([@http://svn.boost.org/trac/boost/ticket/1557 Ticket 1557]).
|
||||
* Added equality operators.
|
||||
|
||||
[h2 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 `<boost/unordered/unordered_map_fwd.hpp>` and
|
||||
`<boost/unordered/unordered_set_fwd.hpp>`.
|
||||
* Move all the implementation inside `boost/unordered`, to assist
|
||||
modularization and hopefully make it easier to track changes in subversion.
|
||||
|
||||
[h2 Boost 1.38.0]
|
||||
|
||||
* Use [@boost:/libs/utility/swap.html `boost::swap`].
|
||||
* [@https://svn.boost.org/trac/boost/ticket/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.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
|
||||
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
|
||||
Brönnimann.
|
||||
* Use
|
||||
[@boost:/libs/type_traits/doc/html/boost_typetraits/category/alignment.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 C++0x initializer lists where they're available (currently
|
||||
only g++ 4.4 in C++0x mode).
|
||||
|
||||
[h2 Boost 1.39.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2756 Ticket 2756]: Avoid a warning
|
||||
on Visual C++ 2009.
|
||||
* Some other minor internal changes to the implementation, tests and
|
||||
documentation.
|
||||
* Avoid an unnecessary copy in `operator[]`.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]: Fix length of
|
||||
prime number list.
|
||||
|
||||
[h2 Boost 1.40.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/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.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/1978 Ticket 1978]:
|
||||
Implement `emplace` for all compilers.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2908 Ticket 2908],
|
||||
[@https://svn.boost.org/trac/boost/ticket/3096 Ticket 3096]:
|
||||
Some workarounds for old versions of borland, including adding explicit
|
||||
destructors to all containers.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/3082 Ticket 3082]:
|
||||
Disable incorrect Visual C++ warnings.
|
||||
* Better configuration for C++0x features when the headers aren't available.
|
||||
* Create less buckets by default.
|
||||
|
||||
[h2 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 objcet 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.
|
||||
|
||||
[endsect]
|
||||
|
@ -72,7 +72,7 @@
|
||||
[
|
||||
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
|
||||
[No comparison operators are defined in the standard, although
|
||||
[link unordered.rationale.equality_operator
|
||||
[link unordered.rationale.equality_operators
|
||||
implementations might extend the containers to support `==` and
|
||||
`!=`].]
|
||||
]
|
||||
|
@ -13,7 +13,7 @@ is declared as:
|
||||
class Key, class Mapped,
|
||||
class Hash = ``[classref boost::hash]``<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<Key> >
|
||||
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
|
||||
class ``[classref boost::unordered_map unordered_map]``;
|
||||
|
||||
The hash function comes first as you might want to change the hash function
|
||||
@ -23,8 +23,8 @@ but not the equality predicate. For example, if you wanted to use the
|
||||
[import src_code/dictionary.cpp]
|
||||
[case_sensitive_dictionary_fnv]
|
||||
|
||||
An example implementation of FNV-1, and some other hash functions are supplied
|
||||
in the examples directory.
|
||||
There is an [@boost:/libs/unordered/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
|
||||
@ -38,9 +38,19 @@ Which you can then use in a case insensitive dictionary:
|
||||
[case_insensitive_dictionary]
|
||||
|
||||
This is a simplified version of the example at
|
||||
[@../../libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
|
||||
[@boost:/libs/unordered/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.
|
||||
]
|
||||
|
||||
[h2 Custom Types]
|
||||
|
||||
Similarly, a custom hash function can be used for custom types:
|
||||
|
@ -9,7 +9,7 @@
|
||||
[@http://www.boost.org/doc/html/boost_tr1.html
|
||||
Boost.TR1]]
|
||||
[def __draft__
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2461.pdf
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
|
||||
Working Draft of the C++ Standard]]
|
||||
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
|
||||
hash table]]
|
||||
@ -36,9 +36,7 @@ which are implemented using hash tables, and they have now been added to the
|
||||
__draft__.
|
||||
|
||||
This library supplies an almost complete implementation of the specification in
|
||||
the __draft__, (it doesn't support `emplace` yet, see the [link
|
||||
unordered.rationale.future_developments Implementation Rationale] section for more
|
||||
details). If accepted the containers should also be added to __boost-tr1__.
|
||||
the __draft__.
|
||||
|
||||
`unordered_set` and `unordered_multiset` are defined in the header
|
||||
<[headerref boost/unordered_set.hpp]>
|
||||
|
@ -5,12 +5,6 @@
|
||||
[def __wang__
|
||||
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
Thomas Wang's article on integer hash functions]]
|
||||
[def __n2345__
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2345.pdf
|
||||
N2345, 'Placement Insert for Containers']]
|
||||
[def __n2369__
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2369.pdf
|
||||
the August 2007 version of the working draft standard]]
|
||||
|
||||
[section:rationale Implementation Rationale]
|
||||
|
||||
@ -96,117 +90,52 @@ efficiency advantage of power of 2 hash tables.
|
||||
|
||||
So, this implementation uses a prime number for the hash table size.
|
||||
|
||||
[h2 Equality operators]
|
||||
|
||||
`operator==` and `operator!=` are not included in the standard, but I've
|
||||
added them as I think they could be useful and can be implemented
|
||||
fairly efficiently. They are specified differently to the other standard
|
||||
containers, comparing keys using the equality predicate rather than
|
||||
`operator==`.
|
||||
|
||||
It's also different to the proposal
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2944.pdf n2944].
|
||||
which uses the equality operators for the whole of `value_type`. This
|
||||
implementation just uses the key equality function for the key,
|
||||
and `mapped_type`'s equality operator in `unordered_map` and
|
||||
`unordered_multimap` for the mapped part of the element.
|
||||
|
||||
Also, in `unordered_multimap`, the mapped values for a group of elements with
|
||||
equivalent keys are only considered equal if they are in the same order,
|
||||
in n2944 they just need to be a permutation of each other. Since the
|
||||
order of elements with equal keys is now defined to be stable, it seems to me
|
||||
that their order can be considered part of the container's value.
|
||||
|
||||
[h2 Active Issues and Proposals]
|
||||
|
||||
[h3 Removing unused allocator functions]
|
||||
[h3 C++0x allocators]
|
||||
|
||||
In
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2257.html
|
||||
N2257, removing unused allocator functions],
|
||||
Matt Austern suggests removing the `construct`, `destroy` and `address` member
|
||||
functions - all of which Boost.Unordered calls. Changing this will simplify the
|
||||
implementation, as well as make supporting `emplace` easier, but means that the
|
||||
containers won't support allocators which require these methods to be called.
|
||||
Detlef Vollmann opposed this change in
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2339.htm N2339].
|
||||
Recent drafts have included an overhaul of the allocators, but this was
|
||||
dependent on concepts which are no longer in the standard.
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946]
|
||||
attempts to respecify them without concepts. I'll try to implement this (or
|
||||
an appropriate later version) in a future version of boost, possibly changed
|
||||
a little to accomodate non-C++0x compilers.
|
||||
|
||||
[h3 Swapping containers with unequal allocators]
|
||||
|
||||
It isn't clear how to swap containers when their allocators aren't equal.
|
||||
This is
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431
|
||||
Issue 431: Swapping containers with unequal allocators].
|
||||
|
||||
Howard Hinnant wrote about this in
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1599.html N1599]
|
||||
and suggested swapping both the allocators and the containers' contents.
|
||||
But the committee have now decided that `swap` should do a fast swap if the
|
||||
allocator is Swappable and a slow swap using copy construction otherwise. To
|
||||
make this distinction requires concepts.
|
||||
|
||||
In
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2387.pdf
|
||||
N2387, Omnibus Allocator Fix-up Proposals],
|
||||
Pablo Halpern suggests that there are actually two distinct allocator models,
|
||||
"Moves with Value" and "Scoped" which behave differently:
|
||||
|
||||
[:
|
||||
When allocators are allowed to have state, it is necessary to have a model for
|
||||
determining from where an object obtains its allocator. We’ve identified two such
|
||||
models: the “Moves with Value” allocator model and the “Scoped” allocator model.
|
||||
|
||||
In the “Moves with Value” allocator model, the copy constructor of an allocator-aware
|
||||
class will copy both the value and the allocator from its argument. This is the model
|
||||
specified in the C++03 standard. With this model, inserting an object into a container
|
||||
usually causes the new container item to copy the allocator from the object that was
|
||||
inserted. This model can be useful in special circumstances, e.g., if the items within a
|
||||
container use an allocator that is specially tuned to the item’s type.
|
||||
|
||||
In the “Scoped” allocator model, the allocator used to construct an object is determined
|
||||
by the context of that object, much like a storage class. With this model, inserting an
|
||||
object into a container causes the new container item to use the same allocator as the
|
||||
container. To avoid allocators being used in the wrong context, the allocator is never
|
||||
copied during copy or move construction. Thus, it is possible using this model to use
|
||||
allocators based on short-lived resources without fear that an object will transfer its
|
||||
allocator to a copy that might outlive the (shared) allocator resource. This model is
|
||||
reasonably safe and generally useful on a large scale. There was strong support in the
|
||||
2005 Tremblant meeting for pursuing an allocator model that propagates allocators
|
||||
from container to contained objects.
|
||||
]
|
||||
|
||||
With these models the choice becomes clearer:
|
||||
|
||||
[:
|
||||
I introduced the “Moves with Value” allocator model and the
|
||||
“Scoped” allocator model. In the former case, the allocator is copied when the container
|
||||
is copy-constructed. In the latter case it is not. Swapping the allocators is the right thing
|
||||
to do if the containers conform to the “Moves with Value” allocator model and
|
||||
absolutely the wrong thing to do if the containers conform to the “Scoped” allocator
|
||||
model. With the two allocator models well-defined, the desired behavior becomes clear.
|
||||
]
|
||||
|
||||
The proposal is that allocators are swapped if the allocator follows the
|
||||
"Moves with Value" model and the allocator is swappable. Otherwise a slow swap
|
||||
is used. Since containers currently only support the "Moves with Value" model
|
||||
this is consistent with the committee's current recommendation (although it
|
||||
suggests using a trait to detect if the allocator is swappable rather than a
|
||||
concept).
|
||||
|
||||
Since there is currently neither have a swappable trait or concept for
|
||||
allocators this implementation always performs a slow swap.
|
||||
Issue 431: Swapping containers with unequal allocators]. This has been resolved
|
||||
with the new allocator specification, so this should be fixed when
|
||||
support is added.
|
||||
|
||||
[h3 Are insert and erase stable for unordered_multiset and unordered_multimap?]
|
||||
|
||||
It is not specified if `unordered_multiset` and `unordered_multimap` preserve the order
|
||||
It wan't specified if `unordered_multiset` and `unordered_multimap` preserve the order
|
||||
of elements with equivalent keys (i.e. if they're stable under `insert` and `erase`).
|
||||
This is [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#518 issue 581].
|
||||
The current proposal is that insert, erase and rehash are stable - so they are here.
|
||||
|
||||
[h3 const_local_iterator cbegin, cend missing from TR1]
|
||||
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2482.html#691
|
||||
Issue 691] is that `cbegin` and `cend` are missing for local iterators.
|
||||
The current resolution is that they'll be added, so I've added them.
|
||||
|
||||
[h2 Future Developments]
|
||||
|
||||
[h3 Support for `emplace`]
|
||||
|
||||
In __n2369__ a new member function, `emplace` was added to the containers to
|
||||
allow placement insert, as described in __n2345__. To fully implement this
|
||||
`std::forward` is required, along with new functions in `std::allocator` and
|
||||
new constructors in `std::pair`. But partial support is possible - especially
|
||||
if I don't use the `construct` member of allocators.
|
||||
|
||||
[h3 Equality operator]
|
||||
|
||||
While `operator==` and `operator!=` are not included in the standard, it's
|
||||
possible to implement them for all the containers - this is helped by having
|
||||
stable order of elements with equivalent keys. They will need to be specified
|
||||
differently to the standard associative containers, probably comparing keys
|
||||
using the equality predicate rather than `operator==`. This is inconsistent
|
||||
with the other containers but it is probably closer to user's expectations.
|
||||
|
||||
If these are added then a `hash_value` free function should also be added.
|
||||
Since [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
|
||||
n2691] it's been specified that they do and this implementation follows that.
|
||||
|
||||
[endsect]
|
||||
|
448
doc/ref.xml
448
doc/ref.xml
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright Daniel James 2006-2008
|
||||
Copyright Daniel James 2006-2009
|
||||
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)
|
||||
--><library-reference>
|
||||
@ -19,12 +19,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<default><type>std::allocator<Value></type></default>
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<purpose>
|
||||
<purpose><simpara>
|
||||
An unordered associative container that stores unique values.
|
||||
</purpose>
|
||||
</simpara></purpose>
|
||||
<description>
|
||||
<para>For the normative reference see chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf">the working draft of the C++ standard [n2461].</ulink></para>
|
||||
<para>Based on chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
|
||||
But without the updated rules for allocators.
|
||||
</para>
|
||||
<para><emphasis role="bold">Template Parameters</emphasis>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
@ -69,11 +71,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<purpose>lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<purpose>const lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
@ -93,7 +95,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
<para>Convertible to <type>const_iterator</type>.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
@ -101,7 +103,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="local_iterator">
|
||||
@ -180,8 +182,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter>
|
||||
<paramtype>unordered_set &&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>The move constructor.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is emulated on compilers without rvalue references.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
@ -201,6 +223,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
</notes>
|
||||
</destructor>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
@ -210,6 +235,38 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_set)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>unordered_set &&</paramtype>
|
||||
</parameter>
|
||||
<type>unordered_set&</type>
|
||||
<description>
|
||||
<para>The move assignment operator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_set)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
@ -284,9 +341,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace">
|
||||
<method name="emplace_hint">
|
||||
<template>
|
||||
<template-type-parameter name="Args" pack="1">
|
||||
</template-type-parameter>
|
||||
@ -312,6 +372,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>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 value. </para>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -636,10 +699,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<parameter name="z">
|
||||
<paramtype>float</paramtype>
|
||||
</parameter>
|
||||
<type>float</type>
|
||||
<returns>
|
||||
<type>void</type>
|
||||
<effects>
|
||||
<para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
|
||||
</returns>
|
||||
</effects>
|
||||
</method>
|
||||
<method name="rehash">
|
||||
<parameter name="n">
|
||||
@ -676,6 +739,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="operator!=">
|
||||
@ -698,25 +763,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="hash_value">
|
||||
<template>
|
||||
<template-type-parameter name="Value">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Hash">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Pred">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Alloc">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="x">
|
||||
<paramtype>unordered_set<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>std::size_t</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -766,12 +814,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<default><type>std::allocator<Value></type></default>
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<purpose>
|
||||
<purpose><simpara>
|
||||
An unordered associative container that stores values. The same key can be stored multiple times.
|
||||
</purpose>
|
||||
</simpara></purpose>
|
||||
<description>
|
||||
<para>For the normative reference see chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf">the working draft of the C++ standard [n2461].</ulink></para>
|
||||
<para>Based on chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
|
||||
But without the updated rules for allocators.
|
||||
</para>
|
||||
<para><emphasis role="bold">Template Parameters</emphasis>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
@ -816,11 +866,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<purpose>lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<purpose>const lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
@ -840,7 +890,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
<para>Convertible to <type>const_iterator</type>.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
@ -848,7 +898,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="local_iterator">
|
||||
@ -927,8 +977,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter>
|
||||
<paramtype>unordered_multiset &&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>The move constructor.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is emulated on compilers without rvalue references.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
@ -948,6 +1018,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
</notes>
|
||||
</destructor>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
@ -957,6 +1030,38 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_multiset)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>unordered_multiset &&</paramtype>
|
||||
</parameter>
|
||||
<type>unordered_multiset&</type>
|
||||
<description>
|
||||
<para>The move assignment operator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_multiset)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
@ -1030,9 +1135,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace">
|
||||
<method name="emplace_hint">
|
||||
<template>
|
||||
<template-type-parameter name="Args" pack="1">
|
||||
</template-type-parameter>
|
||||
@ -1058,6 +1166,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>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 value. </para>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -1381,10 +1492,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<parameter name="z">
|
||||
<paramtype>float</paramtype>
|
||||
</parameter>
|
||||
<type>float</type>
|
||||
<returns>
|
||||
<type>void</type>
|
||||
<effects>
|
||||
<para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
|
||||
</returns>
|
||||
</effects>
|
||||
</method>
|
||||
<method name="rehash">
|
||||
<parameter name="n">
|
||||
@ -1421,6 +1532,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="operator!=">
|
||||
@ -1443,25 +1556,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="hash_value">
|
||||
<template>
|
||||
<template-type-parameter name="Value">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Hash">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Pred">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Alloc">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="x">
|
||||
<paramtype>unordered_multiset<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>std::size_t</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -1517,12 +1613,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<default><type>std::allocator<std::pair<Key const, Mapped> ></type></default>
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<purpose>
|
||||
<purpose><simpara>
|
||||
An unordered associative container that associates unique keys with another value.
|
||||
</purpose>
|
||||
</simpara></purpose>
|
||||
<description>
|
||||
<para>For the normative reference see chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf">the working draft of the C++ standard [n2461].</ulink></para>
|
||||
<para>Based on chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
|
||||
But without the updated rules for allocators.
|
||||
</para>
|
||||
<para><emphasis role="bold">Template Parameters</emphasis>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
@ -1573,11 +1671,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<purpose>lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<purpose>const lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
@ -1597,7 +1695,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
<para>Convertible to <type>const_iterator</type>.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
@ -1605,7 +1703,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="local_iterator">
|
||||
@ -1684,8 +1782,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter>
|
||||
<paramtype>unordered_map &&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>The move constructor.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is emulated on compilers without rvalue references.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
@ -1705,6 +1823,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
</notes>
|
||||
</destructor>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
@ -1714,6 +1835,38 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_map)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>unordered_map &&</paramtype>
|
||||
</parameter>
|
||||
<type>unordered_map&</type>
|
||||
<description>
|
||||
<para>The move assignment operator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_map)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
@ -1788,9 +1941,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace">
|
||||
<method name="emplace_hint">
|
||||
<template>
|
||||
<template-type-parameter name="Args" pack="1">
|
||||
</template-type-parameter>
|
||||
@ -1816,6 +1972,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>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. </para>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -2175,10 +2334,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<parameter name="z">
|
||||
<paramtype>float</paramtype>
|
||||
</parameter>
|
||||
<type>float</type>
|
||||
<returns>
|
||||
<type>void</type>
|
||||
<effects>
|
||||
<para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
|
||||
</returns>
|
||||
</effects>
|
||||
</method>
|
||||
<method name="rehash">
|
||||
<parameter name="n">
|
||||
@ -2217,6 +2376,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="operator!=">
|
||||
@ -2241,27 +2402,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="hash_value">
|
||||
<template>
|
||||
<template-type-parameter name="Key">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Mapped">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Hash">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Pred">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Alloc">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="x">
|
||||
<paramtype>unordered_map<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>std::size_t</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -2315,12 +2457,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<default><type>std::allocator<std::pair<Key const, Mapped> ></type></default>
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<purpose>
|
||||
<purpose><simpara>
|
||||
An unordered associative container that associates keys with another value. The same key can be stored multiple times.
|
||||
</purpose>
|
||||
</simpara></purpose>
|
||||
<description>
|
||||
<para>For the normative reference see chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf">the working draft of the C++ standard [n2461].</ulink></para>
|
||||
<para>Based on chapter 23 of
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
|
||||
But without the updated rules for allocators.
|
||||
</para>
|
||||
<para><emphasis role="bold">Template Parameters</emphasis>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
@ -2371,11 +2515,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<purpose>lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<purpose>const lvalue of <type>value_type</type>.</purpose>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
@ -2395,7 +2539,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
<para>Convertible to <type>const_iterator</type>.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
@ -2403,7 +2547,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
<description>
|
||||
<para>A constant iterator whose value type is <type>value_type</type>. </para>
|
||||
<para>Any iterator category except output iterator.</para>
|
||||
<para>The iterator category is at least a forward iterator.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="local_iterator">
|
||||
@ -2482,8 +2626,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter>
|
||||
<paramtype>unordered_multimap &&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>The move constructor.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is emulated on compilers without rvalue references.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
@ -2503,6 +2667,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
</notes>
|
||||
</destructor>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
@ -2512,6 +2679,38 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<description>
|
||||
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_multimap)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para><code>value_type</code> is copy constructible</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>unordered_multimap &&</paramtype>
|
||||
</parameter>
|
||||
<type>unordered_multimap&</type>
|
||||
<description>
|
||||
<para>The move assignment operator.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, there is a single assignment
|
||||
operator with the signature <code>operator=(unordered_multimap)</code>
|
||||
in order to emulate move semantics.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move constructible.
|
||||
(TODO: This is not actually required in this implementation).
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
@ -2585,9 +2784,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace">
|
||||
<method name="emplace_hint">
|
||||
<template>
|
||||
<template-type-parameter name="Args" pack="1">
|
||||
</template-type-parameter>
|
||||
@ -2613,6 +2815,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>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. </para>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
<para>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.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -2936,10 +3141,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<parameter name="z">
|
||||
<paramtype>float</paramtype>
|
||||
</parameter>
|
||||
<type>float</type>
|
||||
<returns>
|
||||
<type>void</type>
|
||||
<effects>
|
||||
<para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
|
||||
</returns>
|
||||
</effects>
|
||||
</method>
|
||||
<method name="rehash">
|
||||
<parameter name="n">
|
||||
@ -2978,6 +3183,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="operator!=">
|
||||
@ -3002,27 +3209,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<type>bool</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
</notes>
|
||||
</function>
|
||||
<function name="hash_value">
|
||||
<template>
|
||||
<template-type-parameter name="Key">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Mapped">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Hash">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Pred">
|
||||
</template-type-parameter>
|
||||
<template-type-parameter name="Alloc">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="x">
|
||||
<paramtype>unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>std::size_t</type>
|
||||
<notes>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -3062,4 +3250,4 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</library-reference>
|
||||
</library-reference>
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "../../examples/hash_functions/fnv-1.hpp"
|
||||
#include "../../examples/fnv1.hpp"
|
||||
|
||||
//[case_insensitive_functions
|
||||
struct iequal_to
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
66
examples/fnv1.hpp
Normal file
66
examples/fnv1.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
// Copyright 2008-2009 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)
|
||||
|
||||
// This code is also released into the public domain.
|
||||
|
||||
// Algorithm from: http://www.isthe.com/chongo/tech/comp/fnv/
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace hash
|
||||
{
|
||||
template <std::size_t FnvPrime, std::size_t OffsetBasis>
|
||||
struct basic_fnv_1
|
||||
{
|
||||
std::size_t operator()(std::string const& text) const
|
||||
{
|
||||
std::size_t hash = OffsetBasis;
|
||||
for(std::string::const_iterator it = text.begin(), end = text.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
hash *= FnvPrime;
|
||||
hash ^= *it;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t FnvPrime, std::size_t OffsetBasis>
|
||||
struct basic_fnv_1a
|
||||
{
|
||||
std::size_t operator()(std::string const& text) const
|
||||
{
|
||||
std::size_t hash = OffsetBasis;
|
||||
for(std::string::const_iterator it = text.begin(), end = text.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
hash ^= *it;
|
||||
hash *= FnvPrime;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
// For 32 bit machines:
|
||||
const std::size_t fnv_prime = 16777619u;
|
||||
const std::size_t fnv_offset_basis = 2166136261u;
|
||||
|
||||
// For 64 bit machines:
|
||||
// const std::size_t fnv_prime = 1099511628211u;
|
||||
// const std::size_t fnv_offset_basis = 14695981039346656037u;
|
||||
|
||||
// For 128 bit machines:
|
||||
// const std::size_t fnv_prime = 309485009821345068724781401u;
|
||||
// const std::size_t fnv_offset_basis = 275519064689413815358837431229664493455u;
|
||||
|
||||
// For 256 bit machines:
|
||||
// const std::size_t fnv_prime = 374144419156711147060143317175368453031918731002211u;
|
||||
// const std::size_t fnv_offset_basis = 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
|
||||
|
||||
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
|
||||
typedef basic_fnv_1a<fnv_prime, fnv_offset_basis> fnv_1a;
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
// See: http://www.isthe.com/chongo/tech/comp/fnv/
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace hash
|
||||
{
|
||||
template <std::size_t FnvPrime, std::size_t OffsetBias>
|
||||
struct basic_fnv_1
|
||||
{
|
||||
std::size_t operator()(std::string const& text) const
|
||||
{
|
||||
std::size_t hash = OffsetBias;
|
||||
for(std::string::const_iterator it = text.begin(), end = text.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
hash *= FnvPrime;
|
||||
hash ^= *it;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t FnvPrime, std::size_t OffsetBias>
|
||||
struct basic_fnv_1a
|
||||
{
|
||||
std::size_t operator()(std::string const& text) const
|
||||
{
|
||||
std::size_t hash = OffsetBias;
|
||||
for(std::string::const_iterator it = text.begin(), end = text.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
hash ^= *it;
|
||||
hash *= FnvPrime;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Select Bias & Prime base on the size of std::size_t.
|
||||
//
|
||||
// 32 bit FNV_prime = 16777619
|
||||
// 64 bit FNV_prime = 1099511628211
|
||||
// 128 bit FNV_prime = 309485009821345068724781401
|
||||
// 256 bit FNV_prime = 374144419156711147060143317175368453031918731002211
|
||||
//
|
||||
// 32 bit offset_basis = 2166136261
|
||||
// 64 bit offset_basis = 14695981039346656037
|
||||
// 128 bit offset_basis = 275519064689413815358837431229664493455
|
||||
// 256 bit offset_basis = 100029257958052580907070968620625704837092796014241193945225284501741471925557
|
||||
|
||||
const std::size_t fnv_prime = 16777619;
|
||||
// 64 bit FNV_prime = 1099511628211
|
||||
// 128 bit FNV_prime = 309485009821345068724781401
|
||||
// 256 bit FNV_prime = 374144419156711147060143317175368453031918731002211
|
||||
|
||||
const std::size_t fnv_offset_bias = 2166136261u;
|
||||
// 64 bit offset_basis = 14695981039346656037
|
||||
// 128 bit offset_basis = 275519064689413815358837431229664493455
|
||||
// 256 bit offset_basis = 100029257958052580907070968620625704837092796014241193945225284501741471925557
|
||||
|
||||
typedef basic_fnv_1<fnv_prime, fnv_offset_bias> fnv_1;
|
||||
typedef basic_fnv_1a<fnv_prime, fnv_offset_bias> fnv_1a;
|
||||
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
// A couple of templates to make using allocators easier.
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
|
||||
|
||||
@ -21,214 +23,86 @@
|
||||
# include <boost/detail/allocator_utilities.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/aux_/config/eti.hpp>
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
namespace boost {
|
||||
namespace unordered_detail {
|
||||
// rebind_wrap
|
||||
//
|
||||
// Rebind allocators. For some problematic libraries, use rebind_to
|
||||
// from <boost/detail/allocator_utilities.hpp>.
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
template <class Alloc, class T>
|
||||
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
|
||||
template <class Alloc, class T>
|
||||
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
|
||||
#else
|
||||
template <class Alloc, class T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
|
||||
type;
|
||||
};
|
||||
template <class Alloc, class T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
|
||||
type;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
template <class T>
|
||||
inline void reset(T& x) { x = T(); }
|
||||
// allocator_array_constructor
|
||||
//
|
||||
// Allocate and construct an array in an exception safe manner, and
|
||||
// clean up if an exception is thrown before the container takes charge
|
||||
// of it.
|
||||
|
||||
template <class Ptr>
|
||||
inline Ptr null_ptr() { return Ptr(); }
|
||||
#else
|
||||
template <class T>
|
||||
inline void reset_impl(T& x, ...) { x = T(); }
|
||||
template <class T>
|
||||
inline void reset_impl(T*& x, int) { x = 0; }
|
||||
template <class T>
|
||||
inline void reset(T& x) { reset_impl(x); }
|
||||
template <class Allocator>
|
||||
struct allocator_array_constructor
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
|
||||
|
||||
template <class Ptr>
|
||||
inline Ptr null_ptr() { Ptr x; reset(x); return x; }
|
||||
#endif
|
||||
Allocator& alloc_;
|
||||
pointer ptr_;
|
||||
pointer constructed_;
|
||||
std::size_t length_;
|
||||
|
||||
// Work around for Microsoft's ETI bug.
|
||||
|
||||
template <class Allocator> struct allocator_value_type
|
||||
allocator_array_constructor(Allocator& a)
|
||||
: alloc_(a), ptr_(), constructed_(), length_(0)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::value_type type;
|
||||
};
|
||||
constructed_ = pointer();
|
||||
ptr_ = pointer();
|
||||
}
|
||||
|
||||
template <class Allocator> struct allocator_pointer
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer type;
|
||||
};
|
||||
|
||||
template <class Allocator> struct allocator_const_pointer
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::const_pointer type;
|
||||
};
|
||||
|
||||
template <class Allocator> struct allocator_reference
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::reference type;
|
||||
};
|
||||
|
||||
template <class Allocator> struct allocator_const_reference
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::const_reference type;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
|
||||
~allocator_array_constructor() {
|
||||
if (ptr_) {
|
||||
for(pointer p = ptr_; p != constructed_; ++p)
|
||||
alloc_.destroy(p);
|
||||
|
||||
template <>
|
||||
struct allocator_value_type<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct allocator_pointer<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct allocator_const_pointer<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct allocator_reference<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct allocator_const_reference<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class Allocator>
|
||||
struct allocator_constructor
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Allocator>::type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
|
||||
|
||||
Allocator& alloc_;
|
||||
pointer ptr_;
|
||||
bool constructed_;
|
||||
|
||||
allocator_constructor(Allocator& a)
|
||||
: alloc_(a), ptr_(), constructed_(false)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
unordered_detail::reset(ptr_);
|
||||
#endif
|
||||
alloc_.deallocate(ptr_, length_);
|
||||
}
|
||||
}
|
||||
|
||||
~allocator_constructor() {
|
||||
if(ptr_) {
|
||||
if(constructed_) alloc_.destroy(ptr_);
|
||||
alloc_.deallocate(ptr_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <class V>
|
||||
void construct(V const& v) {
|
||||
BOOST_ASSERT(!ptr_ && !constructed_);
|
||||
ptr_ = alloc_.allocate(1);
|
||||
alloc_.construct(ptr_, value_type(v));
|
||||
constructed_ = true;
|
||||
}
|
||||
|
||||
void construct(value_type const& v) {
|
||||
BOOST_ASSERT(!ptr_ && !constructed_);
|
||||
ptr_ = alloc_.allocate(1);
|
||||
alloc_.construct(ptr_, v);
|
||||
constructed_ = true;
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
// no throw
|
||||
pointer release()
|
||||
{
|
||||
pointer p = ptr_;
|
||||
constructed_ = false;
|
||||
unordered_detail::reset(ptr_);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct allocator_array_constructor
|
||||
template <class V>
|
||||
void construct(V const& v, std::size_t l)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
|
||||
BOOST_ASSERT(!ptr_);
|
||||
length_ = l;
|
||||
ptr_ = alloc_.allocate(length_);
|
||||
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
|
||||
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
|
||||
alloc_.construct(constructed_, v);
|
||||
}
|
||||
|
||||
Allocator& alloc_;
|
||||
pointer ptr_;
|
||||
pointer constructed_;
|
||||
std::size_t length_;
|
||||
pointer get() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
allocator_array_constructor(Allocator& a)
|
||||
: alloc_(a), ptr_(), constructed_(), length_(0)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
unordered_detail::reset(constructed_);
|
||||
unordered_detail::reset(ptr_);
|
||||
#endif
|
||||
}
|
||||
|
||||
~allocator_array_constructor() {
|
||||
if (ptr_) {
|
||||
for(pointer p = ptr_; p != constructed_; ++p)
|
||||
alloc_.destroy(p);
|
||||
|
||||
alloc_.deallocate(ptr_, length_);
|
||||
}
|
||||
}
|
||||
|
||||
template <class V>
|
||||
void construct(V const& v, std::size_t l)
|
||||
{
|
||||
BOOST_ASSERT(!ptr_);
|
||||
length_ = l;
|
||||
ptr_ = alloc_.allocate(length_);
|
||||
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
|
||||
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
|
||||
alloc_.construct(constructed_, v);
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
pointer release()
|
||||
{
|
||||
pointer p(ptr_);
|
||||
unordered_detail::reset(ptr_);
|
||||
return p;
|
||||
}
|
||||
private:
|
||||
allocator_array_constructor(allocator_array_constructor const&);
|
||||
allocator_array_constructor& operator=(allocator_array_constructor const&);
|
||||
};
|
||||
}
|
||||
}
|
||||
pointer release()
|
||||
{
|
||||
pointer p(ptr_);
|
||||
ptr_ = pointer();
|
||||
return p;
|
||||
}
|
||||
private:
|
||||
allocator_array_constructor(allocator_array_constructor const&);
|
||||
allocator_array_constructor& operator=(
|
||||
allocator_array_constructor const&);
|
||||
};
|
||||
}}
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
|
||||
|
183
include/boost/unordered/detail/buckets.hpp
Normal file
183
include/boost/unordered/detail/buckets.hpp
Normal file
@ -0,0 +1,183 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/unordered/detail/node.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Buckets
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::max_bucket_count() const {
|
||||
// -1 to account for the sentinel.
|
||||
return prev_prime(this->bucket_alloc().max_size() - 1);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::get_bucket(std::size_t num) const
|
||||
{
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(num);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
|
||||
{
|
||||
return get_bucket(hashed % bucket_count_);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
|
||||
{
|
||||
if(!buckets_) return 0;
|
||||
bucket_ptr ptr = get_bucket(index)->next_;
|
||||
std::size_t count = 0;
|
||||
while(ptr) {
|
||||
++count;
|
||||
ptr = ptr->next_;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
|
||||
hash_buckets<A, G>::bucket_begin(std::size_t num) const
|
||||
{
|
||||
return buckets_ ? get_bucket(num)->next_ : node_ptr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Delete
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_node(node_ptr b)
|
||||
{
|
||||
node* raw_ptr = static_cast<node*>(&*b);
|
||||
boost::unordered_detail::destroy(&raw_ptr->value());
|
||||
real_node_ptr n(node_alloc().address(*raw_ptr));
|
||||
node_alloc().destroy(n);
|
||||
node_alloc().deallocate(n, 1);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
|
||||
{
|
||||
node_ptr node_it = b->next_;
|
||||
b->next_ = node_ptr();
|
||||
|
||||
while(node_it) {
|
||||
node_ptr node_to_delete = node_it;
|
||||
node_it = node_it->next_;
|
||||
delete_node(node_to_delete);
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_buckets()
|
||||
{
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
|
||||
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
|
||||
clear_bucket(begin);
|
||||
}
|
||||
|
||||
// Destroy the buckets (including the sentinel bucket).
|
||||
++end;
|
||||
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
|
||||
bucket_alloc().destroy(begin);
|
||||
}
|
||||
|
||||
bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
|
||||
|
||||
this->buckets_ = bucket_ptr();
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::delete_nodes(
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
while(begin != end) {
|
||||
node_ptr n = begin;
|
||||
begin = begin->next_;
|
||||
delete_node(n);
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors and Destructors
|
||||
|
||||
template <class A, class G>
|
||||
inline hash_buckets<A, G>::hash_buckets(
|
||||
node_allocator const& a, std::size_t bucket_count)
|
||||
: buckets_(),
|
||||
bucket_count_(bucket_count),
|
||||
allocators_(a,a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline hash_buckets<A, G>::~hash_buckets()
|
||||
{
|
||||
if(this->buckets_) { this->delete_buckets(); }
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::create_buckets()
|
||||
{
|
||||
// The array constructor will clean up in the event of an
|
||||
// exception.
|
||||
allocator_array_constructor<bucket_allocator>
|
||||
constructor(bucket_alloc());
|
||||
|
||||
// Creates an extra bucket to act as a sentinel.
|
||||
constructor.construct(bucket(), this->bucket_count_ + 1);
|
||||
|
||||
// Set up the sentinel (node_ptr cast)
|
||||
bucket_ptr sentinel = constructor.get() +
|
||||
static_cast<ptrdiff_t>(this->bucket_count_);
|
||||
sentinel->next_ = sentinel;
|
||||
|
||||
// Only release the buckets once everything is successfully
|
||||
// done.
|
||||
this->buckets_ = constructor.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors and Destructors
|
||||
|
||||
// no throw
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::move(hash_buckets& other)
|
||||
{
|
||||
BOOST_ASSERT(node_alloc() == other.node_alloc());
|
||||
if(this->buckets_) { this->delete_buckets(); }
|
||||
this->buckets_ = other.buckets_;
|
||||
this->bucket_count_ = other.bucket_count_;
|
||||
other.buckets_ = bucket_ptr();
|
||||
other.bucket_count_ = 0;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
|
||||
{
|
||||
BOOST_ASSERT(node_alloc() == other.node_alloc());
|
||||
std::swap(buckets_, other.buckets_);
|
||||
std::swap(bucket_count_, other.bucket_count_);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
@ -1,22 +0,0 @@
|
||||
|
||||
// Copyright 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)
|
||||
|
||||
#if !defined(BOOST_UNORDERED_DETAIL_CONFIG_HEADER)
|
||||
#define BOOST_UNORDERED_DETAIL_CONFIG_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_NO_SFINAE)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif defined(__GNUC__) && \
|
||||
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
|
||||
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
|
||||
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#endif
|
||||
|
||||
#endif
|
209
include/boost/unordered/detail/equivalent.hpp
Normal file
209
include/boost/unordered/detail/equivalent.hpp
Normal file
@ -0,0 +1,209 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Equality
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_equivalent_table<H, P, A, K>
|
||||
::equals(hash_equivalent_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
|
||||
{
|
||||
node_ptr it1 = i->next_;
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
|
||||
{
|
||||
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
|
||||
|
||||
node_ptr end1 = node::next_group(it1);
|
||||
node_ptr end2 = node::next_group(it2);
|
||||
|
||||
do {
|
||||
if(!extractor::compare_mapped(
|
||||
node::get_value(it1), node::get_value(it2)))
|
||||
return false;
|
||||
it1 = it1->next_;
|
||||
it2 = it2->next_;
|
||||
} while(it1 != end1 && it2 != end2);
|
||||
if(it1 != end1 || it2 != end2) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// A convenience method for adding nodes.
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::node_ptr
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
node::add_after_node(n, pos);
|
||||
}
|
||||
else {
|
||||
node::add_to_bucket(n, *bucket);
|
||||
if(bucket < this->cached_begin_bucket_)
|
||||
this->cached_begin_bucket_ = bucket;
|
||||
}
|
||||
++this->size_;
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME
|
||||
hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>::emplace_impl(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
|
||||
if(!this->size_) {
|
||||
return this->emplace_empty_impl_with_node(a, 1);
|
||||
}
|
||||
else {
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr position = this->find_iterator(bucket, k);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
return iterator_base(bucket, add_node(a, bucket, position));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::emplace_impl_no_rehash(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
add_node(a, bucket, this->find_iterator(bucket, k));
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (equivalent key containers)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace(Args&&... args)
|
||||
{
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
return emplace_impl(a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
|
||||
hash_equivalent_table<H, P, A, K> \
|
||||
::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
return emplace_impl(a); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::insert_for_range(I i, I j, forward_traversal_tag)
|
||||
{
|
||||
if(i == j) return;
|
||||
std::size_t distance = unordered_detail::distance(i, j);
|
||||
if(distance == 1) {
|
||||
emplace(*i);
|
||||
}
|
||||
else {
|
||||
node_constructor a(*this);
|
||||
|
||||
// Only require basic exception safety here
|
||||
if(this->size_) {
|
||||
this->reserve_for_insert(this->size_ + distance);
|
||||
}
|
||||
else {
|
||||
a.construct(*i++);
|
||||
this->emplace_empty_impl_with_node(a, distance);
|
||||
}
|
||||
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl_no_rehash(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::insert_for_range(I i, I j, boost::incrementable_traversal_tag)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl(a);
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
void hash_equivalent_table<H, P, A, K>::insert_range(I i, I j)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
|
||||
iterator_traversal_tag;
|
||||
insert_for_range(i, j, iterator_traversal_tag);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
156
include/boost/unordered/detail/extract_key.hpp
Normal file
156
include/boost/unordered/detail/extract_key.hpp
Normal file
@ -0,0 +1,156 @@
|
||||
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace unordered_detail {
|
||||
|
||||
// key extractors
|
||||
//
|
||||
// no throw
|
||||
//
|
||||
// 'extract_key' is called with the emplace parameters to return a
|
||||
// key if available or 'no_key' is one isn't and will need to be
|
||||
// constructed. This could be done by overloading the emplace implementation
|
||||
// for the different cases, but that's a bit tricky on compilers without
|
||||
// variadic templates.
|
||||
|
||||
struct no_key {
|
||||
no_key() {}
|
||||
template <class T> no_key(T const&) {}
|
||||
};
|
||||
|
||||
struct set_extractor
|
||||
{
|
||||
template <class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
typedef ValueType key_type;
|
||||
|
||||
static key_type const& extract(key_type const& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static no_key extract()
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#else
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&, Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const&, value_type const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct map_extractor
|
||||
{
|
||||
template <class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
remove_const<BOOST_DEDUCED_TYPENAME ValueType::first_type>::type
|
||||
key_type;
|
||||
|
||||
static key_type const& extract(value_type const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
|
||||
static key_type const& extract(key_type const& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(
|
||||
std::pair<key_type const, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class Arg1, class... Args>
|
||||
static key_type const& extract(key_type const& k,
|
||||
Arg1 const&, Args const&...)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
template <class Arg1>
|
||||
static key_type const& extract(key_type const& k, Arg1 const&)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
static no_key extract()
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg, class Arg1>
|
||||
static no_key extract(Arg const&, Arg1 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const& x, value_type const& y)
|
||||
{
|
||||
return x.second == y.second;
|
||||
}
|
||||
};
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
974
include/boost/unordered/detail/fwd.hpp
Normal file
974
include/boost/unordered/detail/fwd.hpp
Normal file
@ -0,0 +1,974 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
// This contains the basic data structure, apart from the actual values. There's
|
||||
// no construction or deconstruction here. So this only depends on the pointer
|
||||
// type.
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/compressed_pair.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// This header defines most of the classes used to implement the unordered
|
||||
// containers. It doesn't include the insert methods as they require a lot
|
||||
// of preprocessor metaprogramming - they are in insert.hpp
|
||||
|
||||
// Template parameters:
|
||||
//
|
||||
// H = Hash Function
|
||||
// P = Predicate
|
||||
// A = Value Allocator
|
||||
// G = Grouped/Ungrouped
|
||||
// K = Key Extractor
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
// STLport doesn't have std::forward.
|
||||
# else
|
||||
# define BOOST_UNORDERED_STD_FORWARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_EMPLACE_LIMIT)
|
||||
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
||||
#define BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, class Arg)
|
||||
#define BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, num_params, Arg, const& arg)
|
||||
#define BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, arg)
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
static const float minimum_max_load_factor = 1e-3f;
|
||||
static const std::size_t default_bucket_count = 11;
|
||||
struct move_tag {};
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
class hash_node_constructor;
|
||||
struct set_extractor;
|
||||
struct map_extractor;
|
||||
struct no_key;
|
||||
|
||||
// Explicitly call a destructor
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// hash_bucket
|
||||
|
||||
template <class A>
|
||||
class hash_bucket
|
||||
{
|
||||
hash_bucket& operator=(hash_bucket const&);
|
||||
public:
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<A, bucket>::type
|
||||
bucket_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket_allocator::pointer bucket_ptr;
|
||||
typedef bucket_ptr node_ptr;
|
||||
|
||||
node_ptr next_;
|
||||
|
||||
hash_bucket() : next_() {}
|
||||
|
||||
// Only copy construct when allocating.
|
||||
hash_bucket(hash_bucket const& x)
|
||||
: next_()
|
||||
{
|
||||
BOOST_ASSERT(!x.next_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
struct ungrouped_node_base : hash_bucket<A> {
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
ungrouped_node_base() : bucket() {}
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr n);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
};
|
||||
|
||||
template <class A>
|
||||
struct grouped_node_base : hash_bucket<A>
|
||||
{
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
node_ptr group_prev_;
|
||||
|
||||
grouped_node_base() : bucket(), group_prev_() {}
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline node_ptr first_in_group(node_ptr n);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr n);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
|
||||
private:
|
||||
static inline node_ptr split_group(node_ptr split);
|
||||
static inline grouped_node_base& get(node_ptr ptr) {
|
||||
return static_cast<grouped_node_base&>(*ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct ungrouped
|
||||
{
|
||||
template <class A>
|
||||
struct base {
|
||||
typedef ungrouped_node_base<A> type;
|
||||
};
|
||||
};
|
||||
|
||||
struct grouped
|
||||
{
|
||||
template <class A>
|
||||
struct base {
|
||||
typedef grouped_node_base<A> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct value_base
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(value_type),
|
||||
::boost::alignment_of<value_type>::value>::type data_;
|
||||
|
||||
void* address() {
|
||||
return this;
|
||||
}
|
||||
value_type& value() {
|
||||
return *(ValueType*) this;
|
||||
}
|
||||
};
|
||||
|
||||
// Node
|
||||
|
||||
template <class A, class G>
|
||||
class hash_node :
|
||||
public G::BOOST_NESTED_TEMPLATE base<A>::type,
|
||||
public value_base<BOOST_DEDUCED_TYPENAME A::value_type>
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME hash_bucket<A>::node_ptr node_ptr;
|
||||
|
||||
static value_type& get_value(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterator Base
|
||||
|
||||
template <class A, class G>
|
||||
class hash_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef A value_allocator;
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef hash_node<A, G> node;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
|
||||
|
||||
bucket_ptr bucket_;
|
||||
node_ptr node_;
|
||||
|
||||
hash_iterator_base() : bucket_(), node_() {}
|
||||
explicit hash_iterator_base(bucket_ptr b)
|
||||
: bucket_(b),
|
||||
node_(b ? b->next_ : node_ptr()) {}
|
||||
hash_iterator_base(bucket_ptr b, node_ptr n)
|
||||
: bucket_(b),
|
||||
node_(n) {}
|
||||
|
||||
bool operator==(hash_iterator_base const& x) const {
|
||||
return node_ == x.node_; }
|
||||
bool operator!=(hash_iterator_base const& x) const {
|
||||
return node_ != x.node_; }
|
||||
value_type& operator*() const {
|
||||
return node::get_value(node_);
|
||||
}
|
||||
|
||||
void increment_bucket(node_ptr n) {
|
||||
while(!n) {
|
||||
++bucket_;
|
||||
n = bucket_->next_;
|
||||
}
|
||||
node_ = bucket_ == n ? node_ptr() : n;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
increment_bucket(node_->next_);
|
||||
}
|
||||
};
|
||||
|
||||
// hash_buckets
|
||||
//
|
||||
// This is responsible for allocating and deallocating buckets and nodes.
|
||||
//
|
||||
// Notes:
|
||||
// 1. For the sake exception safety the allocators themselves don't allocate
|
||||
// anything.
|
||||
// 2. It's the callers responsibility to allocate the buckets before calling
|
||||
// any of the methods (other than getters and setters).
|
||||
|
||||
template <class A, class G>
|
||||
class hash_buckets
|
||||
{
|
||||
hash_buckets(hash_buckets const&);
|
||||
hash_buckets& operator=(hash_buckets const&);
|
||||
public:
|
||||
// Types
|
||||
|
||||
typedef A value_allocator;
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef hash_iterator_base<A, G> iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME iterator_base::node node;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_allocator bucket_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
|
||||
node_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
|
||||
|
||||
// Members
|
||||
|
||||
bucket_ptr buckets_;
|
||||
std::size_t bucket_count_;
|
||||
boost::compressed_pair<bucket_allocator, node_allocator> allocators_;
|
||||
|
||||
// Data access
|
||||
|
||||
bucket_allocator const& bucket_alloc() const {
|
||||
return allocators_.first(); }
|
||||
node_allocator const& node_alloc() const {
|
||||
return allocators_.second(); }
|
||||
bucket_allocator& bucket_alloc() {
|
||||
return allocators_.first(); }
|
||||
node_allocator& node_alloc() {
|
||||
return allocators_.second(); }
|
||||
std::size_t max_bucket_count() const;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_buckets(node_allocator const& a, std::size_t n);
|
||||
void create_buckets();
|
||||
~hash_buckets();
|
||||
|
||||
// no throw
|
||||
void swap(hash_buckets& other);
|
||||
void move(hash_buckets& other);
|
||||
|
||||
// For the remaining functions, buckets_ must not be null.
|
||||
|
||||
bucket_ptr get_bucket(std::size_t n) const;
|
||||
bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
|
||||
std::size_t bucket_size(std::size_t index) const;
|
||||
node_ptr bucket_begin(std::size_t n) const;
|
||||
|
||||
// Alloc/Dealloc
|
||||
|
||||
void delete_node(node_ptr);
|
||||
|
||||
//
|
||||
void delete_buckets();
|
||||
void clear_bucket(bucket_ptr);
|
||||
std::size_t delete_nodes(node_ptr begin, node_ptr end);
|
||||
std::size_t delete_to_bucket_end(node_ptr begin);
|
||||
};
|
||||
|
||||
template <class H, class P> class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
class hash_buffered_functions
|
||||
{
|
||||
friend class set_hash_functions<H, P>;
|
||||
hash_buffered_functions& operator=(hash_buffered_functions const&);
|
||||
|
||||
typedef boost::compressed_pair<H, P> function_pair;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(function_pair),
|
||||
::boost::alignment_of<function_pair>::value>::type aligned_function;
|
||||
|
||||
bool current_; // The currently active functions.
|
||||
aligned_function funcs_[2];
|
||||
|
||||
function_pair const& current() const {
|
||||
return *static_cast<function_pair const*>(
|
||||
static_cast<void const*>(&funcs_[current_]));
|
||||
}
|
||||
|
||||
void construct(bool which, H const& hf, P const& eq)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(hf, eq);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair const& f)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f);
|
||||
}
|
||||
|
||||
void destroy(bool which)
|
||||
{
|
||||
boost::unordered_detail::destroy((function_pair*)(&funcs_[which]));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
hash_buffered_functions(H const& hf, P const& eq)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, hf, eq);
|
||||
}
|
||||
|
||||
hash_buffered_functions(hash_buffered_functions const& bf)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current());
|
||||
}
|
||||
|
||||
~hash_buffered_functions() {
|
||||
destroy(current_);
|
||||
}
|
||||
|
||||
H const& hash_function() const {
|
||||
return current().first();
|
||||
}
|
||||
|
||||
P const& key_eq() const {
|
||||
return current().second();
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef hash_buffered_functions<H, P> buffered_functions;
|
||||
buffered_functions& buffered_functions_;
|
||||
bool tmp_functions_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(buffered_functions& f, H const& h, P const& p)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, h, p);
|
||||
}
|
||||
|
||||
set_hash_functions(buffered_functions& f,
|
||||
buffered_functions const& other)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, other.current());
|
||||
}
|
||||
|
||||
~set_hash_functions()
|
||||
{
|
||||
buffered_functions_.destroy(tmp_functions_);
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
buffered_functions_.current_ = tmp_functions_;
|
||||
tmp_functions_ = !tmp_functions_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
class hash_table :
|
||||
public hash_buckets<A, G>,
|
||||
public hash_buffered_functions<H, P>
|
||||
{
|
||||
hash_table(hash_table const&);
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
typedef hash_buffered_functions<H, P> base;
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE
|
||||
apply<value_type> extractor;
|
||||
typedef BOOST_DEDUCED_TYPENAME extractor::key_type key_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
|
||||
typedef hash_node_constructor<A, G> node_constructor;
|
||||
typedef std::pair<iterator_base, iterator_base> iterator_pair;
|
||||
|
||||
// Members
|
||||
|
||||
std::size_t size_;
|
||||
float mlf_;
|
||||
// Cached data - invalid if !this->buckets_
|
||||
bucket_ptr cached_begin_bucket_;
|
||||
std::size_t max_load_;
|
||||
|
||||
// Helper methods
|
||||
|
||||
key_type const& get_key(value_type const& v) const {
|
||||
return extractor::extract(v);
|
||||
}
|
||||
key_type const& get_key_from_ptr(node_ptr n) const {
|
||||
return extractor::extract(node::get_value(n));
|
||||
}
|
||||
bool equal(key_type const& k, value_type const& v) const;
|
||||
node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
|
||||
node_ptr find_iterator(key_type const& k) const;
|
||||
node_ptr* find_for_erase(bucket_ptr bucket, key_type const& k) const;
|
||||
|
||||
// Load methods
|
||||
|
||||
std::size_t max_size() const;
|
||||
std::size_t bucket_index(key_type const& k) const;
|
||||
void max_load_factor(float z);
|
||||
std::size_t min_buckets_for_size(std::size_t n) const;
|
||||
std::size_t calculate_max_load();
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_table(std::size_t n, hasher const& hf, key_equal const& eq,
|
||||
node_allocator const& a);
|
||||
hash_table(hash_table const& x, node_allocator const& a);
|
||||
hash_table(hash_table& x, move_tag m);
|
||||
hash_table(hash_table& x, node_allocator const& a, move_tag m);
|
||||
~hash_table() {}
|
||||
hash_table& operator=(hash_table const&);
|
||||
|
||||
// Iterators
|
||||
|
||||
iterator_base begin() const {
|
||||
return this->size_ ?
|
||||
iterator_base(this->cached_begin_bucket_) :
|
||||
iterator_base();
|
||||
}
|
||||
iterator_base end() const {
|
||||
return iterator_base();
|
||||
}
|
||||
|
||||
// Swap & Move
|
||||
|
||||
void swap(hash_table& x);
|
||||
void fast_swap(hash_table& other);
|
||||
void slow_swap(hash_table& other);
|
||||
void partial_swap(hash_table& other);
|
||||
void move(hash_table& x);
|
||||
|
||||
// Reserve and rehash
|
||||
|
||||
void create_for_insert(std::size_t n);
|
||||
bool reserve_for_insert(std::size_t n);
|
||||
void rehash(std::size_t n);
|
||||
void rehash_impl(std::size_t n);
|
||||
|
||||
// Move/copy buckets
|
||||
|
||||
void move_buckets_to(buckets& dst);
|
||||
void copy_buckets_to(buckets& dst) const;
|
||||
|
||||
// Misc. key methods
|
||||
|
||||
std::size_t count(key_type const& k) const;
|
||||
iterator_base find(key_type const& k) const;
|
||||
value_type& at(key_type const& k) const;
|
||||
iterator_pair equal_range(key_type const& k) const;
|
||||
|
||||
// Erase
|
||||
//
|
||||
// no throw
|
||||
|
||||
void clear();
|
||||
std::size_t erase_key(key_type const& k);
|
||||
iterator_base erase(iterator_base r);
|
||||
std::size_t erase_group(node_ptr* it, bucket_ptr bucket);
|
||||
iterator_base erase_range(iterator_base r1, iterator_base r2);
|
||||
|
||||
// recompute_begin_bucket
|
||||
|
||||
void init_buckets();
|
||||
|
||||
// After an erase cached_begin_bucket_ might be left pointing to
|
||||
// an empty bucket, so this is called to update it
|
||||
//
|
||||
// no throw
|
||||
|
||||
void recompute_begin_bucket(bucket_ptr b);
|
||||
|
||||
// This is called when a range has been erased
|
||||
//
|
||||
// no throw
|
||||
|
||||
void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2);
|
||||
|
||||
// no throw
|
||||
float load_factor() const;
|
||||
|
||||
iterator_base emplace_empty_impl_with_node(
|
||||
node_constructor&, std::size_t);
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_unique_table :
|
||||
public hash_table<H, P, A, ungrouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, ungrouped, K> table;
|
||||
typedef hash_node_constructor<A, ungrouped> node_constructor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
typedef std::pair<iterator_base, bool> emplace_return;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
|
||||
value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_unique_table(hash_unique_table const& x)
|
||||
: table(x, x.node_alloc()) {}
|
||||
hash_unique_table(hash_unique_table const& x, value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_unique_table(hash_unique_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_unique_table(hash_unique_table& x, value_allocator const& a,
|
||||
move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_unique_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
emplace_return emplace_impl_with_node(node_constructor& a);
|
||||
value_type& operator[](key_type const& k);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_unique_table const&) const;
|
||||
|
||||
node_ptr add_node(node_constructor& a, bucket_ptr bucket);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template<class... Args>
|
||||
emplace_return emplace(Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_impl(key_type const& k, Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_impl(no_key, Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_empty_impl(Args&&... args);
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_impl(key_type const& k, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_impl(no_key, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_empty_impl( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception
|
||||
// safety strong otherwise
|
||||
template <class InputIt>
|
||||
void insert_range(InputIt i, InputIt j);
|
||||
template <class InputIt>
|
||||
void insert_range_impl(key_type const&, InputIt i, InputIt j);
|
||||
template <class InputIt>
|
||||
void insert_range_impl(no_key, InputIt i, InputIt j);
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_equivalent_table :
|
||||
public hash_table<H, P, A, grouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, grouped, K> table;
|
||||
typedef hash_node_constructor<A, grouped> node_constructor;
|
||||
typedef hash_iterator_base<A, grouped> iterator_base;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_equivalent_table(std::size_t n,
|
||||
hasher const& hf, key_equal const& eq, value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x)
|
||||
: table(x, x.node_alloc()) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x,
|
||||
value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x,
|
||||
value_allocator const& a, move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_equivalent_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
iterator_base emplace_impl(node_constructor& a);
|
||||
void emplace_impl_no_rehash(node_constructor& a);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_equivalent_table const&) const;
|
||||
|
||||
inline node_ptr add_node(node_constructor& a,
|
||||
bucket_ptr bucket, node_ptr pos);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class... Args>
|
||||
iterator_base emplace(Args&&... args);
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#endif
|
||||
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j, forward_traversal_tag);
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j, boost::incrementable_traversal_tag);
|
||||
template <class I>
|
||||
void insert_range(I i, I j);
|
||||
};
|
||||
|
||||
// Iterator Access
|
||||
|
||||
class iterator_access
|
||||
{
|
||||
public:
|
||||
template <class Iterator>
|
||||
static BOOST_DEDUCED_TYPENAME Iterator::base const&
|
||||
get(Iterator const& it)
|
||||
{
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
|
||||
// Iterators
|
||||
|
||||
template <class A, class G> class hash_iterator;
|
||||
template <class A, class G> class hash_const_iterator;
|
||||
template <class A, class G> class hash_local_iterator;
|
||||
template <class A, class G> class hash_const_local_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <class A, class G>
|
||||
class hash_local_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::reference>
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef hash_const_local_iterator<A, G> const_local_iterator;
|
||||
|
||||
friend class hash_const_local_iterator<A, G>;
|
||||
node_ptr ptr_;
|
||||
|
||||
public:
|
||||
hash_local_iterator() : ptr_() {}
|
||||
explicit hash_local_iterator(node_ptr x) : ptr_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
}
|
||||
hash_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_local_iterator operator++(int) {
|
||||
hash_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp; }
|
||||
bool operator==(hash_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
class hash_const_local_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::const_pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef hash_local_iterator<A, G> local_iterator;
|
||||
friend class hash_local_iterator<A, G>;
|
||||
ptr ptr_;
|
||||
|
||||
public:
|
||||
hash_const_local_iterator() : ptr_() {}
|
||||
explicit hash_const_local_iterator(ptr x) : ptr_(x) {}
|
||||
hash_const_local_iterator(local_iterator x) : ptr_(x.ptr_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference
|
||||
operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
}
|
||||
hash_const_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_const_local_iterator operator++(int) {
|
||||
hash_const_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp;
|
||||
}
|
||||
bool operator==(local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(hash_const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
// iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
|
||||
template <class A, class G>
|
||||
class hash_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
|
||||
typedef hash_const_iterator<A, G> const_iterator;
|
||||
friend class hash_const_iterator<A, G>;
|
||||
base base_;
|
||||
|
||||
public:
|
||||
|
||||
hash_iterator() : base_() {}
|
||||
explicit hash_iterator(base const& x) : base_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_iterator operator++(int) {
|
||||
hash_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(hash_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(hash_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
class hash_const_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::const_pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
|
||||
typedef hash_iterator<A, G> iterator;
|
||||
friend class hash_iterator<A, G>;
|
||||
friend class iterator_access;
|
||||
base base_;
|
||||
|
||||
public:
|
||||
|
||||
hash_const_iterator() : base_() {}
|
||||
explicit hash_const_iterator(base const& x) : base_(x) {}
|
||||
hash_const_iterator(iterator const& x) : base_(x.base_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_const_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_const_iterator operator++(int) {
|
||||
hash_const_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(hash_const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(hash_const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
@ -1,307 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/mpl/aux_/config/eti.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582)
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
|
||||
#else
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
#define BOOST_UNORDERED_MSVC_RESET_PTR(x) unordered_detail::reset(x)
|
||||
#else
|
||||
#define BOOST_UNORDERED_MSVC_RESET_PTR(x)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace unordered_detail {
|
||||
template <class T> struct type_wrapper {};
|
||||
|
||||
static const std::size_t default_initial_bucket_count = 50;
|
||||
static const float minimum_max_load_factor = 1e-3f;
|
||||
|
||||
template <class T>
|
||||
inline void hash_swap(T& x, T& y)
|
||||
{
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
std::swap(x,y);
|
||||
#else
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline std::size_t double_to_size_t(double f)
|
||||
{
|
||||
return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
|
||||
(std::numeric_limits<std::size_t>::max)() :
|
||||
static_cast<std::size_t>(f);
|
||||
}
|
||||
|
||||
// prime number list, accessor
|
||||
|
||||
template<typename T> struct prime_list_template
|
||||
{
|
||||
static std::size_t const value[];
|
||||
static std::ptrdiff_t const length;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::size_t const prime_list_template<T>::value[] = {
|
||||
53ul, 97ul, 193ul, 389ul, 769ul,
|
||||
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
|
||||
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
|
||||
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
|
||||
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
|
||||
1610612741ul, 3221225473ul, 4294967291ul };
|
||||
|
||||
template<typename T>
|
||||
std::ptrdiff_t const prime_list_template<T>::length = 28;
|
||||
|
||||
typedef prime_list_template<std::size_t> prime_list;
|
||||
|
||||
// no throw
|
||||
inline std::size_t next_prime(std::size_t n) {
|
||||
std::size_t const* const prime_list_begin = prime_list::value;
|
||||
std::size_t const* const prime_list_end = prime_list_begin +
|
||||
prime_list::length;
|
||||
std::size_t const* bound =
|
||||
std::lower_bound(prime_list_begin, prime_list_end, n);
|
||||
if(bound == prime_list_end)
|
||||
bound--;
|
||||
return *bound;
|
||||
}
|
||||
|
||||
// no throw
|
||||
inline std::size_t prev_prime(std::size_t n) {
|
||||
std::size_t const* const prime_list_begin = prime_list::value;
|
||||
std::size_t const* const prime_list_end = prime_list_begin +
|
||||
prime_list::length;
|
||||
std::size_t const* bound =
|
||||
std::upper_bound(prime_list_begin,prime_list_end, n);
|
||||
if(bound != prime_list_begin)
|
||||
bound--;
|
||||
return *bound;
|
||||
}
|
||||
|
||||
// Controls how many buckets are allocated and which buckets hash
|
||||
// values map to. Does not contain the buckets themselves, or ever
|
||||
// deal with them directly.
|
||||
|
||||
struct bucket_manager {
|
||||
std::size_t bucket_count_;
|
||||
|
||||
bucket_manager()
|
||||
: bucket_count_(0) {}
|
||||
|
||||
explicit bucket_manager(std::size_t n)
|
||||
: bucket_count_(next_prime(n)) {}
|
||||
|
||||
std::size_t bucket_count() const {
|
||||
return bucket_count_;
|
||||
}
|
||||
|
||||
std::size_t bucket_from_hash(std::size_t hashed) const {
|
||||
return hashed % bucket_count_;
|
||||
}
|
||||
|
||||
std::size_t max_bucket_count(std::size_t max_size) const {
|
||||
return prev_prime(max_size);
|
||||
}
|
||||
};
|
||||
|
||||
// pair_cast - used to convert between pair types.
|
||||
|
||||
template <class Dst1, class Dst2, class Src1, class Src2>
|
||||
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
|
||||
{
|
||||
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_STD_DISTANCE)
|
||||
using ::std::distance;
|
||||
#else
|
||||
template <class ForwardIterator>
|
||||
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
|
||||
std::size_t x;
|
||||
std::distance(i, j, x);
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct move_tag {};
|
||||
|
||||
// Both hasher and key_equal's copy/assign can throw so double
|
||||
// buffering is used to copy them.
|
||||
|
||||
template <typename Hash, typename Pred>
|
||||
struct buffered_functions
|
||||
{
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
|
||||
class functions
|
||||
{
|
||||
std::pair<hasher, key_equal> functions_;
|
||||
|
||||
public:
|
||||
|
||||
functions(hasher const& h, key_equal const& k)
|
||||
: functions_(h, k) {}
|
||||
|
||||
hasher const& hash_function() const
|
||||
{
|
||||
return functions_.first;
|
||||
}
|
||||
|
||||
key_equal const& key_eq() const
|
||||
{
|
||||
return functions_.second;
|
||||
}
|
||||
};
|
||||
|
||||
typedef functions buffered_functions::*functions_ptr;
|
||||
|
||||
buffered_functions(hasher const& h, key_equal const& k)
|
||||
: func1_(h, k), func2_(h, k), func_(&buffered_functions::func1_) {}
|
||||
|
||||
// This copies the given function objects into the currently unused
|
||||
// function objects and returns a pointer, that func_ can later be
|
||||
// set to, to commit the change.
|
||||
//
|
||||
// Strong exception safety (since only usued function objects are
|
||||
// changed).
|
||||
functions_ptr buffer(buffered_functions const& x) {
|
||||
functions_ptr ptr = func_ == &buffered_functions::func1_
|
||||
? &buffered_functions::func2_ : &buffered_functions::func1_;
|
||||
this->*ptr = x.current();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void set(functions_ptr ptr) {
|
||||
BOOST_ASSERT(ptr != func_);
|
||||
func_ = ptr;
|
||||
}
|
||||
|
||||
functions const& current() const {
|
||||
return this->*func_;
|
||||
}
|
||||
|
||||
private:
|
||||
functions func1_;
|
||||
functions func2_;
|
||||
functions_ptr func_; // The currently active functions.
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EQUIVALENT_KEYS 1
|
||||
#include <boost/unordered/detail/hash_table_impl.hpp>
|
||||
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
|
||||
|
||||
#define BOOST_UNORDERED_EQUIVALENT_KEYS 0
|
||||
#include <boost/unordered/detail/hash_table_impl.hpp>
|
||||
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
|
||||
|
||||
namespace boost {
|
||||
namespace unordered_detail {
|
||||
class iterator_access
|
||||
{
|
||||
public:
|
||||
template <class Iterator>
|
||||
static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType, class KeyType,
|
||||
class Hash, class Pred, class Alloc>
|
||||
class hash_types_unique_keys
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
|
||||
value_allocator;
|
||||
|
||||
typedef hash_table_unique_keys<ValueType, KeyType, Hash, Pred,
|
||||
value_allocator> hash_table;
|
||||
typedef hash_table_data_unique_keys<value_allocator> data;
|
||||
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
|
||||
|
||||
typedef hash_const_local_iterator_unique_keys<value_allocator> const_local_iterator;
|
||||
typedef hash_local_iterator_unique_keys<value_allocator> local_iterator;
|
||||
typedef hash_const_iterator_unique_keys<value_allocator> const_iterator;
|
||||
typedef hash_iterator_unique_keys<value_allocator> iterator;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
};
|
||||
|
||||
template <class ValueType, class KeyType,
|
||||
class Hash, class Pred, class Alloc>
|
||||
class hash_types_equivalent_keys
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
|
||||
value_allocator;
|
||||
|
||||
typedef hash_table_equivalent_keys<ValueType, KeyType, Hash, Pred,
|
||||
value_allocator> hash_table;
|
||||
typedef hash_table_data_equivalent_keys<value_allocator> data;
|
||||
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
|
||||
|
||||
typedef hash_const_local_iterator_equivalent_keys<value_allocator> const_local_iterator;
|
||||
typedef hash_local_iterator_equivalent_keys<value_allocator> local_iterator;
|
||||
typedef hash_const_iterator_equivalent_keys<value_allocator> const_iterator;
|
||||
typedef hash_iterator_equivalent_keys<value_allocator> iterator;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
};
|
||||
} // namespace boost::unordered_detail
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_UNORDERED_BORLAND_BOOL
|
||||
#undef BOOST_UNORDERED_MSVC_RESET_PTR
|
||||
|
||||
#endif // BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER
|
||||
#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
@ -20,7 +20,20 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/unordered/detail/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#if defined(BOOST_NO_SFINAE)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif defined(__GNUC__) && \
|
||||
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
|
||||
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
|
||||
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
@ -96,6 +109,8 @@ struct move_from
|
||||
{
|
||||
explicit move_from(T& x) : source(x) { }
|
||||
T& source;
|
||||
private:
|
||||
move_from& operator=(move_from const&);
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
226
include/boost/unordered/detail/node.hpp
Normal file
226
include/boost/unordered/detail/node.hpp
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
// This contains the basic data structure, apart from the actual values. There's
|
||||
// no construction or deconstruction here. So this only depends on the pointer
|
||||
// type.
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
|
||||
#else
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// ungrouped node implementation
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
|
||||
ungrouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return ptr->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline std::size_t ungrouped_node_base<A>::group_count(node_ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
n->next_ = b.next_;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
|
||||
node_ptr position)
|
||||
{
|
||||
n->next_ = position->next_;
|
||||
position->next_ = position;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &b.next_;
|
||||
while(*pos != begin) pos = &(*pos)->next_;
|
||||
*pos = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
|
||||
{
|
||||
b.next_ = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
|
||||
{
|
||||
unlink_nodes(b, n, n->next_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// grouped node implementation
|
||||
|
||||
// If ptr is the first element in a group, return pointer to next group.
|
||||
// Otherwise returns a pointer to ptr.
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
|
||||
grouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return get(ptr).group_prev_->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::first_in_group(node_ptr ptr)
|
||||
{
|
||||
while(next_group(ptr) == ptr)
|
||||
ptr = get(ptr).group_prev_;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline std::size_t grouped_node_base<A>::group_count(node_ptr ptr)
|
||||
{
|
||||
node_ptr start = ptr;
|
||||
std::size_t size = 0;
|
||||
do {
|
||||
++size;
|
||||
ptr = get(ptr).group_prev_;
|
||||
} while(ptr != start);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
n->next_ = b.next_;
|
||||
get(n).group_prev_ = n;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
|
||||
{
|
||||
n->next_ = next_group(pos);
|
||||
get(n).group_prev_ = get(pos).group_prev_;
|
||||
next_group(pos) = n;
|
||||
get(pos).group_prev_ = n;
|
||||
}
|
||||
|
||||
// Break a ciruclar list into two, with split as the beginning
|
||||
// of the second group (if split is at the beginning then don't
|
||||
// split).
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::split_group(node_ptr split)
|
||||
{
|
||||
node_ptr first = first_in_group(split);
|
||||
if(first == split) return split;
|
||||
|
||||
node_ptr last = get(first).group_prev_;
|
||||
get(first).group_prev_ = get(split).group_prev_;
|
||||
get(split).group_prev_ = last;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
|
||||
{
|
||||
node_ptr next = n->next_;
|
||||
node_ptr* pos = &next_group(n);
|
||||
|
||||
if(*pos != n) {
|
||||
// The node is at the beginning of a group.
|
||||
|
||||
// Find the previous node pointer:
|
||||
pos = &b.next_;
|
||||
while(*pos != n) pos = &next_group(*pos);
|
||||
|
||||
// Remove from group
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == n)
|
||||
{
|
||||
get(next).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
}
|
||||
else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == n)
|
||||
{
|
||||
// The deleted node is not at the end of the group, so
|
||||
// change the link from the next node.
|
||||
get(next).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
else {
|
||||
// The deleted node is at the end of the group, so the
|
||||
// first node in the group is pointing to it.
|
||||
// Find that to change its pointer.
|
||||
node_ptr x = get(n).group_prev_;
|
||||
while(get(x).group_prev_ != n) {
|
||||
x = get(x).group_prev_;
|
||||
}
|
||||
get(x).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
*pos = next;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &next_group(begin);
|
||||
|
||||
if(*pos != begin) {
|
||||
// The node is at the beginning of a group.
|
||||
|
||||
// Find the previous node pointer:
|
||||
pos = &b.next_;
|
||||
while(*pos != begin) pos = &next_group(*pos);
|
||||
|
||||
// Remove from group
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
|
||||
}
|
||||
else {
|
||||
node_ptr group1 = split_group(begin);
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
|
||||
node_ptr group2 = split_group(end);
|
||||
|
||||
if(begin == group2) {
|
||||
node_ptr end1 = get(group1).group_prev_;
|
||||
node_ptr end2 = get(group2).group_prev_;
|
||||
get(group1).group_prev_ = end2;
|
||||
get(group2).group_prev_ = end1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pos = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
|
||||
{
|
||||
split_group(end);
|
||||
b.next_ = end;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
734
include/boost/unordered/detail/table.hpp
Normal file
734
include/boost/unordered/detail/table.hpp
Normal file
@ -0,0 +1,734 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
|
||||
#include <boost/unordered/detail/buckets.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Helper methods
|
||||
|
||||
// strong exception safety, no side effects
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline bool hash_table<H, P, A, G, K>::equal(
|
||||
key_type const& k, value_type const& v) const
|
||||
{
|
||||
return this->key_eq()(k, get_key(v));
|
||||
}
|
||||
|
||||
// strong exception safety, no side effects
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr
|
||||
hash_table<H, P, A, G, K>::find_iterator(
|
||||
bucket_ptr bucket, key_type const& k) const
|
||||
{
|
||||
node_ptr it = bucket->next_;
|
||||
while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
|
||||
!equal(k, node::get_value(it)))
|
||||
{
|
||||
it = node::next_group(it);
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
// strong exception safety, no side effects
|
||||
// pre: this->buckets_
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr
|
||||
hash_table<H, P, A, G, K>::find_iterator(key_type const& k) const
|
||||
{
|
||||
return find_iterator(this->get_bucket(this->bucket_index(k)), k);
|
||||
}
|
||||
|
||||
// strong exception safety, no side effects
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr*
|
||||
hash_table<H, P, A, G, K>::find_for_erase(
|
||||
bucket_ptr bucket, key_type const& k) const
|
||||
{
|
||||
node_ptr* it = &bucket->next_;
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(*it) &&
|
||||
!equal(k, node::get_value(*it)))
|
||||
{
|
||||
it = &node::next_group(*it);
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Load methods
|
||||
|
||||
// no throw
|
||||
template <class H, class P, class A, class G, class K>
|
||||
std::size_t hash_table<H, P, A, G, K>::max_size() const
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// size < mlf_ * count
|
||||
return double_to_size_t(ceil(
|
||||
(double) this->mlf_ * this->max_bucket_count())) - 1;
|
||||
}
|
||||
|
||||
// strong safety
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline std::size_t hash_table<H, P, A, G, K>::bucket_index(
|
||||
key_type const& k) const
|
||||
{
|
||||
// hash_function can throw:
|
||||
return this->hash_function()(k) % this->bucket_count_;
|
||||
}
|
||||
|
||||
|
||||
// no throw
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline std::size_t hash_table<H, P, A, G, K>::calculate_max_load()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// From 6.3.1/13:
|
||||
// Only resize when size >= mlf_ * count
|
||||
return double_to_size_t(ceil((double) mlf_ * this->bucket_count_));
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>::max_load_factor(float z)
|
||||
{
|
||||
BOOST_ASSERT(z > 0);
|
||||
mlf_ = (std::max)(z, minimum_max_load_factor);
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
|
||||
// no throw
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline std::size_t hash_table<H, P, A, G, K>::min_buckets_for_size(
|
||||
std::size_t size) const
|
||||
{
|
||||
BOOST_ASSERT(this->mlf_ != 0);
|
||||
|
||||
using namespace std;
|
||||
|
||||
// From 6.3.1/13:
|
||||
// size < mlf_ * count
|
||||
// => count > size / mlf_
|
||||
//
|
||||
// Or from rehash post-condition:
|
||||
// count > size / mlf_
|
||||
return next_prime(double_to_size_t(floor(size / (double) mlf_)) + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// recompute_begin_bucket
|
||||
|
||||
// init_buckets
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::init_buckets()
|
||||
{
|
||||
if (this->size_) {
|
||||
this->cached_begin_bucket_ = this->buckets_;
|
||||
while (!this->cached_begin_bucket_->next_)
|
||||
++this->cached_begin_bucket_;
|
||||
} else {
|
||||
this->cached_begin_bucket_ = this->get_bucket(this->bucket_count_);
|
||||
}
|
||||
this->max_load_ = calculate_max_load();
|
||||
}
|
||||
|
||||
// After an erase cached_begin_bucket_ might be left pointing to
|
||||
// an empty bucket, so this is called to update it
|
||||
//
|
||||
// no throw
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(bucket_ptr b)
|
||||
{
|
||||
BOOST_ASSERT(!(b < this->cached_begin_bucket_));
|
||||
|
||||
if(b == this->cached_begin_bucket_)
|
||||
{
|
||||
if (this->size_ != 0) {
|
||||
while (!this->cached_begin_bucket_->next_)
|
||||
++this->cached_begin_bucket_;
|
||||
} else {
|
||||
this->cached_begin_bucket_ =
|
||||
this->get_bucket(this->bucket_count_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is called when a range has been erased
|
||||
//
|
||||
// no throw
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(
|
||||
bucket_ptr b1, bucket_ptr b2)
|
||||
{
|
||||
BOOST_ASSERT(!(b1 < this->cached_begin_bucket_) && !(b2 < b1));
|
||||
BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_));
|
||||
|
||||
if(b1 == this->cached_begin_bucket_ && !b1->next_)
|
||||
this->cached_begin_bucket_ = b2;
|
||||
}
|
||||
|
||||
// no throw
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline float hash_table<H, P, A, G, K>::load_factor() const
|
||||
{
|
||||
BOOST_ASSERT(this->bucket_count_ != 0);
|
||||
return static_cast<float>(this->size_)
|
||||
/ static_cast<float>(this->bucket_count_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
hash_table<H, P, A, G, K>::hash_table(std::size_t num_buckets,
|
||||
hasher const& hf, key_equal const& eq, node_allocator const& a)
|
||||
: buckets(a, next_prime(num_buckets)),
|
||||
base(hf, eq),
|
||||
size_(),
|
||||
mlf_(1.0f),
|
||||
cached_begin_bucket_(),
|
||||
max_load_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Copy Construct with allocator
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
hash_table<H, P, A, G, K>::hash_table(hash_table const& x,
|
||||
node_allocator const& a)
|
||||
: buckets(a, x.min_buckets_for_size(x.size_)),
|
||||
base(x),
|
||||
size_(x.size_),
|
||||
mlf_(x.mlf_),
|
||||
cached_begin_bucket_(),
|
||||
max_load_(0)
|
||||
{
|
||||
if(x.size_) {
|
||||
x.copy_buckets_to(*this);
|
||||
this->init_buckets();
|
||||
}
|
||||
}
|
||||
|
||||
// Move Construct
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
hash_table<H, P, A, G, K>::hash_table(hash_table& x, move_tag)
|
||||
: buckets(x.node_alloc(), x.bucket_count_),
|
||||
base(x),
|
||||
size_(0),
|
||||
mlf_(1.0f),
|
||||
cached_begin_bucket_(),
|
||||
max_load_(0)
|
||||
{
|
||||
this->partial_swap(x);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
hash_table<H, P, A, G, K>::hash_table(hash_table& x,
|
||||
node_allocator const& a, move_tag)
|
||||
: buckets(a, x.bucket_count_),
|
||||
base(x),
|
||||
size_(0),
|
||||
mlf_(x.mlf_),
|
||||
cached_begin_bucket_(),
|
||||
max_load_(0)
|
||||
{
|
||||
if(a == x.node_alloc()) {
|
||||
this->partial_swap(x);
|
||||
}
|
||||
else if(x.size_) {
|
||||
x.copy_buckets_to(*this);
|
||||
this->size_ = x.size_;
|
||||
this->init_buckets();
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
hash_table<H, P, A, G, K>& hash_table<H, P, A, G, K>::operator=(
|
||||
hash_table const& x)
|
||||
{
|
||||
hash_table tmp(x, this->node_alloc());
|
||||
this->fast_swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Swap & Move
|
||||
|
||||
// Swap
|
||||
//
|
||||
// Strong exception safety
|
||||
//
|
||||
// Can throw if hash or predicate object's copy constructor throws
|
||||
// or if allocators are unequal.
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::partial_swap(hash_table& x)
|
||||
{
|
||||
this->buckets::swap(x); // No throw
|
||||
std::swap(this->size_, x.size_);
|
||||
std::swap(this->mlf_, x.mlf_);
|
||||
std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
|
||||
std::swap(this->max_load_, x.max_load_);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::fast_swap(hash_table& x)
|
||||
{
|
||||
// These can throw, but they only affect the function objects
|
||||
// that aren't in use so it is strongly exception safe, via.
|
||||
// double buffering.
|
||||
{
|
||||
set_hash_functions<H, P> op1(*this, x);
|
||||
set_hash_functions<H, P> op2(x, *this);
|
||||
op1.commit();
|
||||
op2.commit();
|
||||
}
|
||||
this->buckets::swap(x); // No throw
|
||||
std::swap(this->size_, x.size_);
|
||||
std::swap(this->mlf_, x.mlf_);
|
||||
std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
|
||||
std::swap(this->max_load_, x.max_load_);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::slow_swap(hash_table& x)
|
||||
{
|
||||
if(this == &x) return;
|
||||
|
||||
{
|
||||
// These can throw, but they only affect the function objects
|
||||
// that aren't in use so it is strongly exception safe, via.
|
||||
// double buffering.
|
||||
set_hash_functions<H, P> op1(*this, x);
|
||||
set_hash_functions<H, P> op2(x, *this);
|
||||
|
||||
// Create new buckets in separate hash_buckets objects
|
||||
// which will clean up if anything throws an exception.
|
||||
// (all can throw, but with no effect as these are new objects).
|
||||
|
||||
buckets b1(this->node_alloc(), x.min_buckets_for_size(x.size_));
|
||||
if(x.size_) x.copy_buckets_to(b1);
|
||||
|
||||
buckets b2(x.node_alloc(), this->min_buckets_for_size(this->size_));
|
||||
if(this->size_) copy_buckets_to(b2);
|
||||
|
||||
// Modifying the data, so no throw from now on.
|
||||
|
||||
b1.swap(*this);
|
||||
b2.swap(x);
|
||||
op1.commit();
|
||||
op2.commit();
|
||||
}
|
||||
|
||||
std::swap(this->size_, x.size_);
|
||||
|
||||
if(this->buckets_) this->init_buckets();
|
||||
if(x.buckets_) x.init_buckets();
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>::swap(hash_table& x)
|
||||
{
|
||||
if(this->node_alloc() == x.node_alloc()) {
|
||||
if(this != &x) this->fast_swap(x);
|
||||
}
|
||||
else {
|
||||
this->slow_swap(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Move
|
||||
//
|
||||
// Strong exception safety (might change unused function objects)
|
||||
//
|
||||
// Can throw if hash or predicate object's copy constructor throws
|
||||
// or if allocators are unequal.
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>::move(hash_table& x)
|
||||
{
|
||||
// This can throw, but it only affects the function objects
|
||||
// that aren't in use so it is strongly exception safe, via.
|
||||
// double buffering.
|
||||
set_hash_functions<H, P> new_func_this(*this, x);
|
||||
|
||||
if(this->node_alloc() == x.node_alloc()) {
|
||||
this->buckets::move(x); // no throw
|
||||
this->size_ = x.size_;
|
||||
this->cached_begin_bucket_ = x.cached_begin_bucket_;
|
||||
this->max_load_ = x.max_load_;
|
||||
x.size_ = 0;
|
||||
}
|
||||
else {
|
||||
// Create new buckets in separate HASH_TABLE_DATA objects
|
||||
// which will clean up if anything throws an exception.
|
||||
// (all can throw, but with no effect as these are new objects).
|
||||
|
||||
buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_));
|
||||
if(x.size_) x.copy_buckets_to(b);
|
||||
|
||||
// Start updating the data here, no throw from now on.
|
||||
this->size_ = x.size_;
|
||||
b.swap(*this);
|
||||
this->init_buckets();
|
||||
}
|
||||
|
||||
// We've made it, the rest is no throw.
|
||||
this->mlf_ = x.mlf_;
|
||||
new_func_this.commit();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Reserve & Rehash
|
||||
|
||||
// basic exception safety
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::create_for_insert(std::size_t size)
|
||||
{
|
||||
this->bucket_count_ = (std::max)(this->bucket_count_,
|
||||
this->min_buckets_for_size(size));
|
||||
this->create_buckets();
|
||||
this->init_buckets();
|
||||
}
|
||||
|
||||
// basic exception safety
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline bool hash_table<H, P, A, G, K>::reserve_for_insert(std::size_t size)
|
||||
{
|
||||
if(size >= max_load_) {
|
||||
std::size_t num_buckets
|
||||
= this->min_buckets_for_size((std::max)(size,
|
||||
this->size_ + (this->size_ >> 1)));
|
||||
if(num_buckets != this->bucket_count_) {
|
||||
rehash_impl(num_buckets);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise.
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline void hash_table<H, P, A, G, K>::rehash(std::size_t min_buckets)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if(!this->size_) {
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->bucket_count_ = next_prime(min_buckets);
|
||||
}
|
||||
else {
|
||||
// no throw:
|
||||
min_buckets = next_prime((std::max)(min_buckets,
|
||||
double_to_size_t(floor(this->size_ / (double) mlf_)) + 1));
|
||||
if(min_buckets != this->bucket_count_) rehash_impl(min_buckets);
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>
|
||||
::rehash_impl(std::size_t num_buckets)
|
||||
{
|
||||
hasher const& hf = this->hash_function();
|
||||
std::size_t size = this->size_;
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
|
||||
buckets dst(this->node_alloc(), num_buckets);
|
||||
dst.create_buckets();
|
||||
|
||||
buckets src(this->node_alloc(), this->bucket_count_);
|
||||
src.swap(*this);
|
||||
this->size_ = 0;
|
||||
|
||||
for(bucket_ptr bucket = this->cached_begin_bucket_;
|
||||
bucket != end; ++bucket)
|
||||
{
|
||||
node_ptr group = bucket->next_;
|
||||
while(group) {
|
||||
// Move the first group of equivalent nodes in bucket to dst.
|
||||
|
||||
// This next line throws iff the hash function throws.
|
||||
bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
|
||||
hf(get_key_from_ptr(group)));
|
||||
|
||||
node_ptr& next_group = node::next_group(group);
|
||||
bucket->next_ = next_group;
|
||||
next_group = dst_bucket->next_;
|
||||
dst_bucket->next_ = group;
|
||||
group = bucket->next_;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap the new nodes back into the container and setup the local
|
||||
// variables.
|
||||
this->size_ = size;
|
||||
dst.swap(*this); // no throw
|
||||
this->init_buckets();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// copy_buckets_to
|
||||
|
||||
// copy_buckets_to
|
||||
//
|
||||
// basic excpetion safety. If an exception is thrown this will
|
||||
// leave dst partially filled.
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>
|
||||
::copy_buckets_to(buckets& dst) const
|
||||
{
|
||||
BOOST_ASSERT(this->buckets_ && !dst.buckets_);
|
||||
|
||||
hasher const& hf = this->hash_function();
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
|
||||
hash_node_constructor<A, G> a(dst);
|
||||
dst.create_buckets();
|
||||
|
||||
// no throw:
|
||||
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i) {
|
||||
// no throw:
|
||||
for(node_ptr it = i->next_; it;) {
|
||||
// hash function can throw.
|
||||
bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
|
||||
hf(get_key_from_ptr(it)));
|
||||
// throws, strong
|
||||
|
||||
node_ptr group_end = node::next_group(it);
|
||||
|
||||
a.construct(node::get_value(it));
|
||||
node_ptr n = a.release();
|
||||
node::add_to_bucket(n, *dst_bucket);
|
||||
|
||||
for(it = it->next_; it != group_end; it = it->next_) {
|
||||
a.construct(node::get_value(it));
|
||||
node::add_after_node(a.release(), n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Misc. key methods
|
||||
|
||||
// strong exception safety
|
||||
|
||||
// count
|
||||
//
|
||||
// strong exception safety, no side effects
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
std::size_t hash_table<H, P, A, G, K>::count(key_type const& k) const
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
node_ptr it = find_iterator(k); // throws, strong
|
||||
return BOOST_UNORDERED_BORLAND_BOOL(it) ? node::group_count(it) : 0;
|
||||
}
|
||||
|
||||
// find
|
||||
//
|
||||
// strong exception safety, no side effects
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
|
||||
hash_table<H, P, A, G, K>::find(key_type const& k) const
|
||||
{
|
||||
if(!this->size_) return this->end();
|
||||
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
node_ptr it = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(it))
|
||||
return iterator_base(bucket, it);
|
||||
else
|
||||
return this->end();
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME A::value_type&
|
||||
hash_table<H, P, A, G, K>::at(key_type const& k) const
|
||||
{
|
||||
if(!this->size_)
|
||||
throw std::out_of_range("Unable to find key in unordered_map.");
|
||||
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
node_ptr it = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(it))
|
||||
return node::get_value(it);
|
||||
else
|
||||
throw std::out_of_range("Unable to find key in unordered_map.");
|
||||
}
|
||||
|
||||
// equal_range
|
||||
//
|
||||
// strong exception safety, no side effects
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_pair
|
||||
hash_table<H, P, A, G, K>::equal_range(key_type const& k) const
|
||||
{
|
||||
if(!this->size_)
|
||||
return iterator_pair(this->end(), this->end());
|
||||
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
node_ptr it = find_iterator(bucket, k);
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(it)) {
|
||||
iterator_base first(iterator_base(bucket, it));
|
||||
iterator_base second(first);
|
||||
second.increment_bucket(node::next_group(second.node_));
|
||||
return iterator_pair(first, second);
|
||||
}
|
||||
else {
|
||||
return iterator_pair(this->end(), this->end());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Erase methods
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
void hash_table<H, P, A, G, K>::clear()
|
||||
{
|
||||
if(!this->size_) return;
|
||||
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
|
||||
this->clear_bucket(begin);
|
||||
}
|
||||
|
||||
this->size_ = 0;
|
||||
this->cached_begin_bucket_ = end;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
inline std::size_t hash_table<H, P, A, G, K>::erase_group(
|
||||
node_ptr* it, bucket_ptr bucket)
|
||||
{
|
||||
node_ptr pos = *it;
|
||||
node_ptr end = node::next_group(pos);
|
||||
*it = end;
|
||||
std::size_t count = this->delete_nodes(pos, end);
|
||||
this->size_ -= count;
|
||||
this->recompute_begin_bucket(bucket);
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
std::size_t hash_table<H, P, A, G, K>::erase_key(key_type const& k)
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
|
||||
// No side effects in initial section
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
node_ptr* it = this->find_for_erase(bucket, k);
|
||||
|
||||
// No throw.
|
||||
return *it ? this->erase_group(it, bucket) : 0;
|
||||
}
|
||||
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
|
||||
hash_table<H, P, A, G, K>::erase(iterator_base r)
|
||||
{
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator_base next = r;
|
||||
next.increment();
|
||||
--this->size_;
|
||||
node::unlink_node(*r.bucket_, r.node_);
|
||||
this->delete_node(r.node_);
|
||||
// r has been invalidated but its bucket is still valid
|
||||
this->recompute_begin_bucket(r.bucket_, next.bucket_);
|
||||
return next;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
|
||||
hash_table<H, P, A, G, K>::erase_range(
|
||||
iterator_base r1, iterator_base r2)
|
||||
{
|
||||
if(r1 != r2)
|
||||
{
|
||||
BOOST_ASSERT(r1.node_);
|
||||
if (r1.bucket_ == r2.bucket_) {
|
||||
node::unlink_nodes(*r1.bucket_, r1.node_, r2.node_);
|
||||
this->size_ -= this->delete_nodes(r1.node_, r2.node_);
|
||||
|
||||
// No need to call recompute_begin_bucket because
|
||||
// the nodes are only deleted from one bucket, which
|
||||
// still contains r2 after the erase.
|
||||
BOOST_ASSERT(r1.bucket_->next_);
|
||||
}
|
||||
else {
|
||||
bucket_ptr end_bucket = r2.node_ ?
|
||||
r2.bucket_ : this->get_bucket(this->bucket_count_);
|
||||
BOOST_ASSERT(r1.bucket_ < end_bucket);
|
||||
node::unlink_nodes(*r1.bucket_, r1.node_, node_ptr());
|
||||
this->size_ -= this->delete_nodes(r1.node_, node_ptr());
|
||||
|
||||
bucket_ptr i = r1.bucket_;
|
||||
for(++i; i != end_bucket; ++i) {
|
||||
this->size_ -= this->delete_nodes(i->next_, node_ptr());
|
||||
i->next_ = node_ptr();
|
||||
}
|
||||
|
||||
if(r2.node_) {
|
||||
node_ptr first = r2.bucket_->next_;
|
||||
node::unlink_nodes(*r2.bucket_, r2.node_);
|
||||
this->size_ -= this->delete_nodes(first, r2.node_);
|
||||
}
|
||||
|
||||
// r1 has been invalidated but its bucket is still
|
||||
// valid.
|
||||
this->recompute_begin_bucket(r1.bucket_, end_bucket);
|
||||
}
|
||||
}
|
||||
|
||||
return r2;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
|
||||
hash_table<H, P, A, G, K>::emplace_empty_impl_with_node(
|
||||
node_constructor& a, std::size_t size)
|
||||
{
|
||||
key_type const& k = get_key(a.value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
if(this->buckets_) this->reserve_for_insert(size);
|
||||
else this->create_for_insert(size);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr n = a.release();
|
||||
node::add_to_bucket(n, *bucket);
|
||||
++this->size_;
|
||||
this->cached_begin_bucket_ = bucket;
|
||||
return iterator_base(bucket, n);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
387
include/boost/unordered/detail/unique.hpp
Normal file
387
include/boost/unordered/detail/unique.hpp
Normal file
@ -0,0 +1,387 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Equality
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_unique_table<H, P, A, K>
|
||||
::equals(hash_unique_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
|
||||
{
|
||||
node_ptr it1 = i->next_;
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
|
||||
{
|
||||
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
|
||||
if(!extractor::compare_mapped(
|
||||
node::get_value(it1), node::get_value(it2)))
|
||||
return false;
|
||||
it1 = it1->next_;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// A convenience method for adding nodes.
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::node_ptr
|
||||
hash_unique_table<H, P, A, K>::add_node(node_constructor& a,
|
||||
bucket_ptr bucket)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
node::add_to_bucket(n, *bucket);
|
||||
++this->size_;
|
||||
if(bucket < this->cached_begin_bucket_)
|
||||
this->cached_begin_bucket_ = bucket;
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert methods
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
|
||||
hash_unique_table<H, P, A, K>::operator[](key_type const& k)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
|
||||
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
if(!this->buckets_) {
|
||||
node_constructor a(*this);
|
||||
a.construct_pair(k, (mapped_type*) 0);
|
||||
return *this->emplace_empty_impl_with_node(a, 1);
|
||||
}
|
||||
|
||||
node_ptr pos = this->find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
return node::get_value(pos);
|
||||
}
|
||||
else {
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct_pair(k, (mapped_type*) 0);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return node::get_value(add_node(a, bucket));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = this->find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return emplace_return(iterator_base(bucket, pos), false);
|
||||
} else {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return emplace_return(
|
||||
iterator_base(bucket, add_node(a, bucket)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_impl(key_type const& k,
|
||||
Args&&... args)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = this->find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return emplace_return(iterator_base(bucket, pos), false);
|
||||
|
||||
} else {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return emplace_return(
|
||||
iterator_base(bucket, add_node(a, bucket)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_impl(no_key, Args&&... args)
|
||||
{
|
||||
// Construct the node regardless - in order to get the key.
|
||||
// It will be discarded if it isn't used
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
return emplace_impl_with_node(a);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_empty_impl(Args&&... args)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>::emplace_impl( \
|
||||
key_type const& k, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
std::size_t hash_value = this->hash_function()(k); \
|
||||
bucket_ptr bucket \
|
||||
= this->bucket_ptr_from_hash(hash_value); \
|
||||
node_ptr pos = this->find_iterator(bucket, k); \
|
||||
\
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
|
||||
return emplace_return(iterator_base(bucket, pos), false); \
|
||||
} else { \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
\
|
||||
if(this->reserve_for_insert(this->size_ + 1)) \
|
||||
bucket = this->bucket_ptr_from_hash(hash_value); \
|
||||
\
|
||||
return emplace_return(iterator_base(bucket, \
|
||||
add_node(a, bucket)), true); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>:: \
|
||||
emplace_impl(no_key, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
return emplace_impl_with_node(a); \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>:: \
|
||||
emplace_empty_impl( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (unique keys)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace(Args&&... args)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(
|
||||
extractor::extract(std::forward<Args>(args)...),
|
||||
std::forward<Args>(args)...) :
|
||||
emplace_empty_impl(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class Arg0>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace(Arg0 const& arg0)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(extractor::extract(arg0), arg0) :
|
||||
emplace_empty_impl(arg0);
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>::emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
return this->size_ ? \
|
||||
emplace_impl(extractor::extract(arg0, arg1), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)) : \
|
||||
emplace_empty_impl( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
inline void hash_unique_table<H, P, A, K>::insert_range_impl(
|
||||
key_type const&, InputIt i, InputIt j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
if(!this->size_) {
|
||||
a.construct(*i);
|
||||
this->emplace_empty_impl_with_node(a, 1);
|
||||
++i;
|
||||
if(i == j) return;
|
||||
}
|
||||
|
||||
do {
|
||||
// No side effects in this initial code
|
||||
// Note: can't use get_key as '*i' might not be value_type - it could
|
||||
// be a pair with first_types as key_type without const or a
|
||||
// different second_type.
|
||||
key_type const& k = extractor::extract(*i);
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = this->find_iterator(bucket, k);
|
||||
|
||||
if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
a.construct(*i);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->size_ + 1 >= this->max_load_) {
|
||||
this->reserve_for_insert(this->size_ + insert_size(i, j));
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
}
|
||||
|
||||
// Nothing after this point can throw.
|
||||
add_node(a, bucket);
|
||||
}
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
inline void hash_unique_table<H, P, A, K>::insert_range_impl(
|
||||
no_key, InputIt i, InputIt j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
if(!this->size_) {
|
||||
a.construct(*i);
|
||||
this->emplace_empty_impl_with_node(a, 1);
|
||||
++i;
|
||||
if(i == j) return;
|
||||
}
|
||||
|
||||
do {
|
||||
// No side effects in this initial code
|
||||
a.construct(*i);
|
||||
emplace_impl_with_node(a);
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
void hash_unique_table<H, P, A, K>::insert_range(InputIt i, InputIt j)
|
||||
{
|
||||
if(i != j)
|
||||
return insert_range_impl(extractor::extract(*i), i, j);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
320
include/boost/unordered/detail/util.hpp
Normal file
320
include/boost/unordered/detail/util.hpp
Normal file
@ -0,0 +1,320 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// convert double to std::size_t
|
||||
|
||||
inline std::size_t double_to_size_t(double f)
|
||||
{
|
||||
return f >= static_cast<double>(
|
||||
(std::numeric_limits<std::size_t>::max)()) ?
|
||||
(std::numeric_limits<std::size_t>::max)() :
|
||||
static_cast<std::size_t>(f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// primes
|
||||
|
||||
template<class T> struct prime_list_template
|
||||
{
|
||||
static std::size_t const value[];
|
||||
static std::ptrdiff_t const length;
|
||||
};
|
||||
|
||||
#define BOOST_UNORDERED_PRIMES \
|
||||
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
||||
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
|
||||
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
|
||||
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
|
||||
(1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
|
||||
(50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
|
||||
(1610612741ul)(3221225473ul)(4294967291ul)
|
||||
|
||||
template<class T>
|
||||
std::size_t const prime_list_template<T>::value[] = {
|
||||
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::ptrdiff_t const prime_list_template<T>::length
|
||||
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
|
||||
|
||||
#undef BOOST_UNORDERED_PRIMES
|
||||
|
||||
typedef prime_list_template<std::size_t> prime_list;
|
||||
|
||||
// no throw
|
||||
inline std::size_t next_prime(std::size_t num) {
|
||||
std::size_t const* const prime_list_begin = prime_list::value;
|
||||
std::size_t const* const prime_list_end = prime_list_begin +
|
||||
prime_list::length;
|
||||
std::size_t const* bound =
|
||||
std::lower_bound(prime_list_begin, prime_list_end, num);
|
||||
if(bound == prime_list_end)
|
||||
bound--;
|
||||
return *bound;
|
||||
}
|
||||
|
||||
// no throw
|
||||
inline std::size_t prev_prime(std::size_t num) {
|
||||
std::size_t const* const prime_list_begin = prime_list::value;
|
||||
std::size_t const* const prime_list_end = prime_list_begin +
|
||||
prime_list::length;
|
||||
std::size_t const* bound =
|
||||
std::upper_bound(prime_list_begin,prime_list_end, num);
|
||||
if(bound != prime_list_begin)
|
||||
bound--;
|
||||
return *bound;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// pair_cast - because some libraries don't have the full pair constructors.
|
||||
|
||||
template <class Dst1, class Dst2, class Src1, class Src2>
|
||||
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
|
||||
{
|
||||
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// insert_size/initial_size
|
||||
|
||||
#if !defined(BOOST_NO_STD_DISTANCE)
|
||||
using ::std::distance;
|
||||
#else
|
||||
template <class ForwardIterator>
|
||||
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
|
||||
std::size_t x;
|
||||
std::distance(i, j, x);
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class I>
|
||||
inline std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
|
||||
{
|
||||
return std::distance(i, j);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t insert_size(I i, I j)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
|
||||
iterator_traversal_tag;
|
||||
return insert_size(i, j, iterator_traversal_tag);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t initial_size(I i, I j,
|
||||
std::size_t num_buckets = boost::unordered_detail::default_bucket_count)
|
||||
{
|
||||
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
|
||||
num_buckets);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Node Constructors
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class T, class... Args>
|
||||
inline void construct_impl(T*, void* address, Args&&... args)
|
||||
{
|
||||
new(address) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_CPP0X_PAIR)
|
||||
template <class First, class Second, class Key, class Arg0, class... Args>
|
||||
inline void construct_impl(std::pair<First, Second>*, void* address,
|
||||
Key&& k, Arg0&& arg0, Args&&... args)
|
||||
)
|
||||
{
|
||||
new(address) std::pair<First, Second>(k,
|
||||
Second(arg0, std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
T*, void* address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
} \
|
||||
\
|
||||
template <class First, class Second, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
std::pair<First, Second>*, void* address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
new(address) std::pair<First, Second>(k, \
|
||||
Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
#endif
|
||||
|
||||
// hash_node_constructor
|
||||
//
|
||||
// Used to construct nodes in an exception safe manner.
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
class hash_node_constructor
|
||||
{
|
||||
typedef hash_buckets<Alloc, Grouped> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
|
||||
|
||||
buckets& buckets_;
|
||||
real_node_ptr node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
|
||||
public:
|
||||
|
||||
hash_node_constructor(buckets& m) :
|
||||
buckets_(m),
|
||||
node_(),
|
||||
node_constructed_(false),
|
||||
value_constructed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
~hash_node_constructor();
|
||||
void construct_preamble();
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
construct_preamble();
|
||||
construct_impl((value_type*) 0, node_->address(),
|
||||
std::forward<Args>(args)...);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
void construct( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
construct_preamble(); \
|
||||
construct_impl( \
|
||||
(value_type*) 0, node_->address(), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
|
||||
); \
|
||||
value_constructed_ = true; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT
|
||||
|
||||
#endif
|
||||
template <class K, class M>
|
||||
void construct_pair(K const& k, M*)
|
||||
{
|
||||
construct_preamble();
|
||||
new(node_->address()) value_type(k, M());
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
value_type& value() const
|
||||
{
|
||||
BOOST_ASSERT(node_);
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
// no throw
|
||||
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
|
||||
{
|
||||
real_node_ptr p = node_;
|
||||
node_ = real_node_ptr();
|
||||
// node_ptr cast
|
||||
return buckets_.bucket_alloc().address(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
hash_node_constructor(hash_node_constructor const&);
|
||||
hash_node_constructor& operator=(hash_node_constructor const&);
|
||||
};
|
||||
|
||||
// hash_node_constructor
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
}
|
||||
|
||||
if (node_constructed_)
|
||||
buckets_.node_alloc().destroy(node_);
|
||||
|
||||
buckets_.node_alloc().deallocate(node_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
|
||||
{
|
||||
if(!node_) {
|
||||
node_constructed_ = false;
|
||||
value_constructed_ = false;
|
||||
|
||||
node_ = buckets_.node_alloc().allocate(1);
|
||||
buckets_.node_alloc().construct(node_, node());
|
||||
node_constructed_ = true;
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_ && value_constructed_);
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
1032
include/boost/unordered/unordered_map.hpp
Normal file
1032
include/boost/unordered/unordered_map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
53
include/boost/unordered/unordered_map_fwd.hpp
Normal file
53
include/boost/unordered/unordered_map_fwd.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
// Copyright (C) 2008-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Key,
|
||||
class T,
|
||||
class Hash = hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class unordered_map;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator!=(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_map<K, T, H, P, A>&,
|
||||
unordered_map<K, T, H, P, A>&);
|
||||
|
||||
template <class Key,
|
||||
class T,
|
||||
class Hash = hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class unordered_multimap;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator==(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator!=(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_multimap<K, T, H, P, A>&,
|
||||
unordered_multimap<K, T, H, P, A>&);
|
||||
}
|
||||
|
||||
#endif
|
975
include/boost/unordered/unordered_set.hpp
Normal file
975
include/boost/unordered/unordered_set.hpp
Normal file
@ -0,0 +1,975 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 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)
|
||||
|
||||
// See http://www.boost.org/libs/unordered for documentation
|
||||
|
||||
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
#include <boost/unordered/detail/move.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:4396) //the inline specifier cannot be used when a
|
||||
// friend declaration refers to a specialization
|
||||
// of a function template
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Value, class Hash, class Pred, class Alloc>
|
||||
class unordered_set
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Value key_type;
|
||||
typedef Value value_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
typedef Alloc allocator_type;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
#endif
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_unique_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::set_extractor> table;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_iterator;
|
||||
typedef const_local_iterator local_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
#endif
|
||||
|
||||
table table_;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME table::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_set(
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
explicit unordered_set(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set const& other, allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
~unordered_set() {}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_set(unordered_set&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set& operator=(unordered_set&& x)
|
||||
{
|
||||
table_.move(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_set(boost::unordered_detail::move_from<
|
||||
unordered_set<Value, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_set& operator=(unordered_set x)
|
||||
{
|
||||
table_.move(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_set(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
unordered_set& operator=(std::initializer_list<value_type> list)
|
||||
{
|
||||
table_.clear();
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(table_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(table_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(table_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
table_.emplace(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...).first);
|
||||
}
|
||||
#else
|
||||
|
||||
std::pair<iterator, bool> emplace(value_type const& v = value_type())
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace(v).first);
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
std::pair<iterator, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)).first); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#endif
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& obj)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
table_.emplace(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator, const value_type& obj)
|
||||
{
|
||||
return iterator(table_.emplace(obj).first);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
void insert(std::initializer_list<value_type> list)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return table_.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
table_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_set& other)
|
||||
{
|
||||
table_.swap(other.table_);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return table_.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return table_.key_eq();
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return table_.count(k);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return table_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.bucket_index(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(
|
||||
unordered_set const&, unordered_set const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(
|
||||
unordered_set const&, unordered_set const&);
|
||||
#endif
|
||||
}; // class template unordered_set
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_set<T, H, P, A> const& m1,
|
||||
unordered_set<T, H, P, A> const& m2)
|
||||
{
|
||||
return m1.table_.equals(m2.table_);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_set<T, H, P, A> const& m1,
|
||||
unordered_set<T, H, P, A> const& m2)
|
||||
{
|
||||
return !m1.table_.equals(m2.table_);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
template <class Value, class Hash, class Pred, class Alloc>
|
||||
class unordered_multiset
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Value key_type;
|
||||
typedef Value value_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
typedef Alloc allocator_type;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
#endif
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::set_extractor> table;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_iterator;
|
||||
typedef const_local_iterator local_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
#endif
|
||||
|
||||
table table_;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME table::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
explicit unordered_multiset(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset const& other,
|
||||
allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
~unordered_multiset() {}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset& operator=(unordered_multiset&& x)
|
||||
{
|
||||
table_.move(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multiset(boost::unordered_detail::move_from<
|
||||
unordered_multiset<Value, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_multiset& operator=(unordered_multiset x)
|
||||
{
|
||||
table_.move(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_multiset(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
unordered_multiset& operator=(std::initializer_list<value_type> list)
|
||||
{
|
||||
table_.clear();
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(table_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(table_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(table_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
|
||||
iterator emplace(value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace(v));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator( \
|
||||
table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#endif
|
||||
|
||||
iterator insert(const value_type& obj)
|
||||
{
|
||||
return iterator(table_.emplace(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator, const value_type& obj)
|
||||
{
|
||||
return iterator(table_.emplace(obj));
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
void insert(std::initializer_list<value_type> list)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return table_.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
table_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_multiset& other)
|
||||
{
|
||||
table_.swap(other.table_);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return table_.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return table_.key_eq();
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return table_.count(k);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return table_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.bucket_index(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(
|
||||
unordered_multiset const&, unordered_multiset const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(
|
||||
unordered_multiset const&, unordered_multiset const&);
|
||||
#endif
|
||||
}; // class template unordered_multiset
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
|
||||
unordered_multiset<T, H, P, A> const& m2)
|
||||
{
|
||||
return m1.table_.equals(m2.table_);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
|
||||
unordered_multiset<T, H, P, A> const& m2)
|
||||
{
|
||||
return !m1.table_.equals(m2.table_);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
unordered_multiset<T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
51
include/boost/unordered/unordered_set_fwd.hpp
Normal file
51
include/boost/unordered/unordered_set_fwd.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
// Copyright (C) 2008-2009 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Value,
|
||||
class Hash = hash<Value>,
|
||||
class Pred = std::equal_to<Value>,
|
||||
class Alloc = std::allocator<Value> >
|
||||
class unordered_set;
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator==(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator!=(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2);
|
||||
|
||||
template <class Value,
|
||||
class Hash = hash<Value>,
|
||||
class Pred = std::equal_to<Value>,
|
||||
class Alloc = std::allocator<Value> >
|
||||
class unordered_multiset;
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator==(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator!=(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
unordered_multiset<T, H, P, A> &m2);
|
||||
}
|
||||
|
||||
#endif
|
@ -13,775 +13,6 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered/detail/hash_table.hpp>
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
#include <boost/unordered/detail/move.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Key,
|
||||
class T,
|
||||
class Hash = hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class unordered_map
|
||||
{
|
||||
typedef boost::unordered_detail::hash_types_unique_keys<
|
||||
std::pair<const Key, T>, Key, Hash, Pred, Alloc
|
||||
> implementation;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
|
||||
|
||||
public:
|
||||
|
||||
// types
|
||||
|
||||
typedef Key key_type;
|
||||
typedef std::pair<const Key, T> value_type;
|
||||
typedef T mapped_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
|
||||
typedef Alloc allocator_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_map(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Should this be explicit?
|
||||
unordered_map(allocator_type const& a)
|
||||
: base(boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_map(unordered_map const& other, allocator_type const& a)
|
||||
: base(other.base, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_map(InputIterator f, InputIterator l)
|
||||
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_map(InputIterator f, InputIterator l,
|
||||
size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(f, l, n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_map(unordered_map&& other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_map(unordered_map&& other, allocator_type const& a)
|
||||
: base(other.base, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_map& operator=(unordered_map&& x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_map(boost::unordered_detail::move_from<unordered_map<Key, T, Hash, Pred, Alloc> > other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_map& operator=(unordered_map x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return base.get_allocator();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return base.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return base.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return base.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
base.insert(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& obj)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
base.insert(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
base.insert_range(first, last);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(base.data_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return base.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(base.data_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
base.data_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_map& other)
|
||||
{
|
||||
base.swap(other.base);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return base.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return base.key_eq();
|
||||
}
|
||||
|
||||
mapped_type& operator[](const key_type &k)
|
||||
{
|
||||
return base[k].second;
|
||||
}
|
||||
|
||||
mapped_type& at(const key_type& k)
|
||||
{
|
||||
return base.at(k).second;
|
||||
}
|
||||
|
||||
mapped_type const& at(const key_type& k) const
|
||||
{
|
||||
return base.at(k).second;
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
iterator find(const key_type& k)
|
||||
{
|
||||
return iterator(base.find(k));
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(base.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return base.count(k);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(const key_type& k)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return base.bucket_count();
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return base.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return base.data_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return base.bucket(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return base.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return base.max_load_factor();
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
base.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
base.rehash(n);
|
||||
}
|
||||
|
||||
friend bool operator==(unordered_map const& m1, unordered_map const& m2)
|
||||
{
|
||||
return m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend bool operator!=(unordered_map const& m1, unordered_map const& m2)
|
||||
{
|
||||
return !m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(unordered_map const& m)
|
||||
{
|
||||
return m.base.hash_value();
|
||||
}
|
||||
}; // class template unordered_map
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_map<K, T, H, P, A> &m1,
|
||||
unordered_map<K, T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
template <class Key,
|
||||
class T,
|
||||
class Hash = hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class unordered_multimap
|
||||
{
|
||||
typedef boost::unordered_detail::hash_types_equivalent_keys<
|
||||
std::pair<const Key, T>, Key, Hash, Pred, Alloc
|
||||
> implementation;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
|
||||
|
||||
public:
|
||||
|
||||
// types
|
||||
|
||||
typedef Key key_type;
|
||||
typedef std::pair<const Key, T> value_type;
|
||||
typedef T mapped_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
|
||||
typedef Alloc allocator_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_multimap(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap(allocator_type const& a)
|
||||
: base(boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap(unordered_multimap const& other, allocator_type const& a)
|
||||
: base(other.base, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multimap(InputIterator f, InputIterator l)
|
||||
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multimap(InputIterator f, InputIterator l,
|
||||
size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(f, l, n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap(unordered_multimap&& other, allocator_type const& a)
|
||||
: base(other.base, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap& operator=(unordered_multimap&& x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multimap(boost::unordered_detail::move_from<unordered_multimap<Key, T, Hash, Pred, Alloc> > other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_multimap& operator=(unordered_multimap x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
private:
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return base.get_allocator();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return base.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return base.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return base.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
return iterator(base.insert(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator insert(const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
base.insert_range(first, last);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(base.data_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return base.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(base.data_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
base.data_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_multimap& other)
|
||||
{
|
||||
base.swap(other.base);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return base.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return base.key_eq();
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
iterator find(const key_type& k)
|
||||
{
|
||||
return iterator(base.find(k));
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(base.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return base.count(k);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(const key_type& k)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return base.bucket_count();
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return base.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return base.data_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return base.bucket(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return base.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return base.max_load_factor();
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
base.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
base.rehash(n);
|
||||
}
|
||||
|
||||
friend bool operator==(unordered_multimap const& m1, unordered_multimap const& m2)
|
||||
{
|
||||
return m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend bool operator!=(unordered_multimap const& m1, unordered_multimap const& m2)
|
||||
{
|
||||
return !m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(unordered_multimap const& m)
|
||||
{
|
||||
return m.base.hash_value();
|
||||
}
|
||||
}; // class template unordered_multimap
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_multimap<K, T, H, P, A> &m1,
|
||||
unordered_multimap<K, T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
|
||||
#endif // BOOST_UNORDERED_MAP_HPP_INCLUDED
|
||||
|
@ -13,731 +13,6 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered/detail/hash_table.hpp>
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
#include <boost/unordered/detail/move.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Value,
|
||||
class Hash = hash<Value>,
|
||||
class Pred = std::equal_to<Value>,
|
||||
class Alloc = std::allocator<Value> >
|
||||
class unordered_set
|
||||
{
|
||||
typedef boost::unordered_detail::hash_types_unique_keys<
|
||||
Value, Value, Hash, Pred, Alloc
|
||||
> implementation;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
|
||||
|
||||
public:
|
||||
|
||||
// types
|
||||
|
||||
typedef Value key_type;
|
||||
typedef Value value_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
|
||||
typedef Alloc allocator_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_set(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Should this be explicit?
|
||||
unordered_set(allocator_type const& a)
|
||||
: base(boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set const& other, allocator_type const& a)
|
||||
: base(other.base, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_set(InputIterator f, InputIterator l)
|
||||
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_set(InputIterator f, InputIterator l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(f, l, n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_set(unordered_set&& other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set&& other, allocator_type const& a)
|
||||
: base(other.base, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set& operator=(unordered_set&& x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_set(boost::unordered_detail::move_from<unordered_set<Value, Hash, Pred, Alloc> > other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_set& operator=(unordered_set x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return base.get_allocator();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return base.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return base.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return base.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
base.insert(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(
|
||||
base.insert_hint(get(hint), std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& obj)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>(
|
||||
base.insert(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
base.insert_range(first, last);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(base.data_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return base.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(base.data_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
base.data_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_set& other)
|
||||
{
|
||||
base.swap(other.base);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return base.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return base.key_eq();
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(base.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return base.count(k);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return base.bucket_count();
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return base.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return base.data_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return base.bucket(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return base.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return base.max_load_factor();
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
base.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
base.rehash(n);
|
||||
}
|
||||
|
||||
friend bool operator==(unordered_set const& m1, unordered_set const& m2)
|
||||
{
|
||||
return m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend bool operator!=(unordered_set const& m1, unordered_set const& m2)
|
||||
{
|
||||
return !m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(unordered_set const& m)
|
||||
{
|
||||
return m.base.hash_value();
|
||||
}
|
||||
}; // class template unordered_set
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
template <class Value,
|
||||
class Hash = hash<Value>,
|
||||
class Pred = std::equal_to<Value>,
|
||||
class Alloc = std::allocator<Value> >
|
||||
class unordered_multiset
|
||||
{
|
||||
typedef boost::unordered_detail::hash_types_equivalent_keys<
|
||||
Value, Value, Hash, Pred, Alloc
|
||||
> implementation;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
|
||||
|
||||
public:
|
||||
|
||||
//types
|
||||
|
||||
typedef Value key_type;
|
||||
typedef Value value_type;
|
||||
typedef Hash hasher;
|
||||
typedef Pred key_equal;
|
||||
|
||||
typedef Alloc allocator_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
|
||||
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Should this be explicit?
|
||||
unordered_multiset(allocator_type const& a)
|
||||
: base(boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset const& other, allocator_type const& a)
|
||||
: base(other.base, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multiset(InputIterator f, InputIterator l)
|
||||
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multiset(InputIterator f, InputIterator l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: base(f, l, n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset&& other, allocator_type const& a)
|
||||
: base(other.base, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset& operator=(unordered_multiset&& x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multiset(boost::unordered_detail::move_from<unordered_multiset<Value, Hash, Pred, Alloc> > other)
|
||||
: base(other.base, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
|
||||
unordered_multiset& operator=(unordered_multiset x)
|
||||
{
|
||||
base.move(x.base);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
|
||||
get(const_iterator const& it)
|
||||
{
|
||||
return boost::unordered_detail::iterator_access::get(it);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return base.get_allocator();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return base.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return base.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return base.max_size();
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(base.data_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator(base.data_.end());
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
return iterator(base.insert(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator insert(const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert(obj));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& obj)
|
||||
{
|
||||
return iterator(base.insert_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
base.insert_range(first, last);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
return iterator(base.data_.erase(get(position)));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
return base.erase_key(k);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(base.data_.erase_range(get(first), get(last)));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
base.data_.clear();
|
||||
}
|
||||
|
||||
void swap(unordered_multiset& other)
|
||||
{
|
||||
base.swap(other.base);
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
hasher hash_function() const
|
||||
{
|
||||
return base.hash_function();
|
||||
}
|
||||
|
||||
key_equal key_eq() const
|
||||
{
|
||||
return base.key_eq();
|
||||
}
|
||||
|
||||
// lookup
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(base.find(k));
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
return base.count(k);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
base.equal_range(k));
|
||||
}
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return base.bucket_count();
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return base.max_bucket_count();
|
||||
}
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{
|
||||
return base.data_.bucket_size(n);
|
||||
}
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return base.bucket(k);
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
{
|
||||
return local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
{
|
||||
return const_local_iterator(base.data_.end(n));
|
||||
}
|
||||
|
||||
// hash policy
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
return base.load_factor();
|
||||
}
|
||||
|
||||
float max_load_factor() const
|
||||
{
|
||||
return base.max_load_factor();
|
||||
}
|
||||
|
||||
void max_load_factor(float m)
|
||||
{
|
||||
base.max_load_factor(m);
|
||||
}
|
||||
|
||||
void rehash(size_type n)
|
||||
{
|
||||
base.rehash(n);
|
||||
}
|
||||
|
||||
friend bool operator==(unordered_multiset const& m1, unordered_multiset const& m2)
|
||||
{
|
||||
return m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend bool operator!=(unordered_multiset const& m1, unordered_multiset const& m2)
|
||||
{
|
||||
return !m1.base.equals(m2.base);
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(unordered_multiset const& m)
|
||||
{
|
||||
return m.base.hash_value();
|
||||
}
|
||||
}; // class template unordered_multiset
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
unordered_multiset<T, H, P, A> &m2)
|
||||
{
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
#include <boost/unordered/unordered_set.hpp>
|
||||
|
||||
#endif // BOOST_UNORDERED_SET_HPP_INCLUDED
|
||||
|
@ -3,5 +3,7 @@
|
||||
# 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)
|
||||
|
||||
import testing ;
|
||||
|
||||
build-project unordered ;
|
||||
build-project exception ;
|
||||
|
@ -8,11 +8,7 @@ import testing ;
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
alias framework : ;
|
||||
|
||||
project unordered-test/exception-tests
|
||||
: requirements
|
||||
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
|
||||
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
|
||||
;
|
||||
project unordered-test/exception-tests ;
|
||||
|
||||
test-suite unordered-exception
|
||||
:
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -25,7 +25,7 @@ struct erase_test_base : public test::exception_base
|
||||
void check(T const& x) const {
|
||||
std::string scope(test::scope);
|
||||
|
||||
BOOST_CHECK(scope.find("hash::") != std::string::npos ||
|
||||
BOOST_TEST(scope.find("hash::") != std::string::npos ||
|
||||
scope.find("equal_to::") != std::string::npos ||
|
||||
scope == "operator==(object, object)");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -31,7 +31,7 @@ struct insert_test_base : public test::exception_base
|
||||
std::string scope(test::scope);
|
||||
|
||||
if(scope.find("hash::operator()") == std::string::npos)
|
||||
strong.test(x);
|
||||
strong.test(x, test::exception::detail::tracker.count_allocations);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
@ -47,7 +47,7 @@ struct emplace_test1 : public insert_test_base<T>
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(), end = this->values.end(); it != end; ++it)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
x.emplace(*it);
|
||||
}
|
||||
}
|
||||
@ -64,7 +64,7 @@ struct insert_test1 : public insert_test_base<T>
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(), end = this->values.end(); it != end; ++it)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
x.insert(*it);
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ struct insert_test2 : public insert_test_base<T>
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(), end = this->values.end(); it != end; ++it)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
x.insert(x.begin(), *it);
|
||||
}
|
||||
}
|
||||
@ -106,7 +106,7 @@ struct insert_test4 : public insert_test_base<T>
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(), end = this->values.end(); it != end; ++it)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
x.insert(it, boost::next(it));
|
||||
}
|
||||
}
|
||||
@ -128,10 +128,10 @@ struct insert_test_rehash1 : public insert_test_base<T>
|
||||
size_type bucket_count = x.bucket_count();
|
||||
size_type initial_elements = static_cast<size_type>(
|
||||
ceil(bucket_count * (double) x.max_load_factor()) - 1);
|
||||
BOOST_REQUIRE(initial_elements < this->values.size());
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_REQUIRE(bucket_count == x.bucket_count());
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -144,13 +144,13 @@ struct insert_test_rehash1 : public insert_test_base<T>
|
||||
it = boost::next(this->values.begin(), x.size()), end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
pos = x.insert(pos, *it);
|
||||
}
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_REQUIRE(x.bucket_count() != bucket_count);
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
};
|
||||
|
||||
@ -167,13 +167,13 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
|
||||
it = boost::next(this->values.begin(), x.size()), end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count)
|
||||
{
|
||||
strong.store(x);
|
||||
strong.store(x, test::exception::detail::tracker.count_allocations);
|
||||
x.insert(*it);
|
||||
}
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_REQUIRE(x.bucket_count() != bucket_count);
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
};
|
||||
|
||||
@ -195,12 +195,12 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
rehash_bucket_count = static_cast<size_type>(
|
||||
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
|
||||
|
||||
size_type initial_elements = rehash_bucket_count - 5;
|
||||
size_type initial_elements = rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
|
||||
|
||||
BOOST_REQUIRE(initial_elements < this->values.size());
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_REQUIRE(original_bucket_count == x.bucket_count());
|
||||
BOOST_TEST(original_bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -212,12 +212,12 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_REQUIRE(x.bucket_count() != bucket_count);
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
|
||||
void check(T const& x) const {
|
||||
if(x.size() < rehash_bucket_count) {
|
||||
//BOOST_CHECK(x.bucket_count() == original_bucket_count);
|
||||
//BOOST_TEST(x.bucket_count() == original_bucket_count);
|
||||
}
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -22,7 +22,7 @@ struct self_swap_base : public test::exception_base
|
||||
std::string scope(test::scope);
|
||||
|
||||
#if BOOST_UNORDERED_SWAP_METHOD != 2
|
||||
BOOST_CHECK(
|
||||
BOOST_TEST(
|
||||
scope == "hash::operator(hash)" ||
|
||||
scope == "hash::operator=(hash)" ||
|
||||
scope == "equal_to::operator(equal_to)" ||
|
||||
@ -77,7 +77,7 @@ struct swap_base : public test::exception_base
|
||||
std::string scope(test::scope);
|
||||
|
||||
#if BOOST_UNORDERED_SWAP_METHOD != 2
|
||||
BOOST_CHECK(
|
||||
BOOST_TEST(
|
||||
scope == "hash::operator(hash)" ||
|
||||
scope == "hash::operator=(hash)" ||
|
||||
scope == "equal_to::operator(equal_to)" ||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
|
||||
// Copyright 2008 Daniel James.
|
||||
// Copyright 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace test {
|
||||
struct object_count {
|
||||
int instances;
|
||||
@ -36,6 +38,11 @@ namespace test {
|
||||
bool operator!=(object_count const& x) const {
|
||||
return !(*this == x);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, object_count const& c) {
|
||||
out<<"[instances: "<<c.instances<<", constructions: "<<c.constructions<<"]";
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -53,6 +60,11 @@ namespace test {
|
||||
struct globally_counted_object
|
||||
: counted_object<globally_counted_object> {};
|
||||
|
||||
// This won't be a problem as I'm only using a single compile unit
|
||||
// in each test (this is actually require by the minimal test
|
||||
// framework).
|
||||
//
|
||||
// boostinspect:nounnamed
|
||||
namespace {
|
||||
object_count& global_object_count = globally_counted_object::count_;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
@ -44,6 +44,11 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
// This won't be a problem as I'm only using a single compile unit
|
||||
// in each test (this is actually require by the minimal test
|
||||
// framework).
|
||||
//
|
||||
// boostinspect:nounnamed
|
||||
namespace {
|
||||
equivalent_type equivalent;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -8,25 +8,10 @@
|
||||
|
||||
#include "./test.hpp"
|
||||
|
||||
#if defined(BOOST_UNORDERED_FULL_TEST)
|
||||
# define BOOST_TEST_MAIN
|
||||
# include <boost/test/exception_safety.hpp>
|
||||
# include <boost/test/unit_test.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/preprocessor/seq/for_each_product.hpp>
|
||||
#include <boost/preprocessor/seq/elem.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
#if defined(BOOST_UNORDERED_FULL_TEST)
|
||||
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
|
||||
UNORDERED_AUTO_TEST(name) \
|
||||
{ \
|
||||
test_func< type > fixture; \
|
||||
::test::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
}
|
||||
# define UNORDERED_EPOINT_IMPL BOOST_ITEST_EPOINT
|
||||
#else
|
||||
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
|
||||
UNORDERED_AUTO_TEST(name) \
|
||||
{ \
|
||||
@ -34,7 +19,6 @@
|
||||
::test::lightweight::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
}
|
||||
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
|
||||
#endif
|
||||
|
||||
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
|
||||
|
||||
@ -178,16 +162,7 @@ namespace test {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if defined(BOOST_UNORDERED_FULL_TEST)
|
||||
template <class Test>
|
||||
void exception_safety(Test const& f, char const* name) {
|
||||
test_runner<Test> runner(f);
|
||||
::boost::itest::exception_safety(runner, name);
|
||||
}
|
||||
#else
|
||||
// Quick exception testing based on lightweight test
|
||||
|
||||
namespace lightweight {
|
||||
@ -237,7 +212,6 @@ namespace test {
|
||||
} while(!success);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,24 +1,39 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class Iterator>
|
||||
struct proxy
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
|
||||
|
||||
proxy(value_type const& v) : v_(v) {}
|
||||
proxy(proxy const& x) : v_(x.v_) {}
|
||||
operator value_type const&() const { return v_; }
|
||||
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template <class Iterator>
|
||||
struct input_iterator_adaptor
|
||||
: boost::iterator_adaptor<
|
||||
input_iterator_adaptor<Iterator>, Iterator,
|
||||
boost::use_default, std::input_iterator_tag>
|
||||
boost::use_default, std::input_iterator_tag,
|
||||
proxy<Iterator> >
|
||||
{
|
||||
typedef boost::iterator_adaptor<
|
||||
input_iterator_adaptor<Iterator>, Iterator,
|
||||
boost::use_default, std::input_iterator_tag> base;
|
||||
boost::use_default, std::input_iterator_tag,
|
||||
proxy<Iterator> > base;
|
||||
|
||||
explicit input_iterator_adaptor(Iterator it = Iterator())
|
||||
: base(it) {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2008 Daniel James.
|
||||
// Copyright 2008-2009 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)
|
||||
|
||||
@ -21,14 +21,17 @@ namespace test
|
||||
|
||||
namespace test_detail
|
||||
{
|
||||
template <typename T> struct list_node;
|
||||
template <typename T> class list_node;
|
||||
template <typename T> class list_data;
|
||||
template <typename T> class list_iterator;
|
||||
template <typename T> class list_const_iterator;
|
||||
|
||||
template <typename T>
|
||||
struct list_node
|
||||
class list_node
|
||||
{
|
||||
list_node(list_node const&);
|
||||
list_node& operator=(list_node const&);
|
||||
public:
|
||||
T value_;
|
||||
list_node* next_;
|
||||
|
||||
@ -81,7 +84,7 @@ namespace test
|
||||
T* operator->() const { return &ptr_->value_; }
|
||||
list_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this; }
|
||||
list_iterator& operator++(int) {
|
||||
list_iterator operator++(int) {
|
||||
list_iterator tmp = *this; ptr_ = ptr_->next_; return tmp; }
|
||||
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
|
||||
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
|
||||
@ -108,7 +111,7 @@ namespace test
|
||||
T const* operator->() const { return &ptr_->value_; }
|
||||
list_const_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this; }
|
||||
list_const_iterator& operator++(int) {
|
||||
list_const_iterator operator++(int) {
|
||||
list_const_iterator tmp = *this; ptr_ = ptr_->next_; return tmp; }
|
||||
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
|
||||
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
|
||||
@ -144,6 +147,7 @@ namespace test
|
||||
list& operator=(list const& other) {
|
||||
clear();
|
||||
insert(other.begin(), other.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(data_.first_); }
|
||||
@ -242,14 +246,28 @@ namespace test
|
||||
node** merge_adjacent_ranges(node** first, node** second,
|
||||
node** third, Less less)
|
||||
{
|
||||
while(first != second) {
|
||||
if(less((*second)->value_, (*first)->value_)) {
|
||||
swap_adjacent_ranges(first, second, third);
|
||||
std::swap(second, third);
|
||||
for(;;) {
|
||||
for(;;) {
|
||||
if(first == second) return third;
|
||||
if(less((*second)->value_, (*first)->value_)) break;
|
||||
first = &(*first)->next_;
|
||||
}
|
||||
|
||||
swap_adjacent_ranges(first, second, third);
|
||||
first = &(*first)->next_;
|
||||
|
||||
// Since the two ranges we just swapped, the order is now:
|
||||
// first...third...second
|
||||
|
||||
for(;;) {
|
||||
if(first == third) return second;
|
||||
if(!less((*first)->value_, (*third)->value_)) break;
|
||||
first = &(*first)->next_;
|
||||
}
|
||||
|
||||
swap_adjacent_ranges(first, third, second);
|
||||
first = &(*first)->next_;
|
||||
}
|
||||
return third;
|
||||
}
|
||||
|
||||
void swap_adjacent_ranges(node** first, node** second, node** third)
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -18,11 +18,6 @@ namespace test
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// This annoymous namespace won't cause ODR violations as I won't
|
||||
// be linking multiple translation units together. I'll probably
|
||||
// move this into a cpp file before a full release, but for now it's
|
||||
// the most convenient way.
|
||||
|
||||
struct memory_area {
|
||||
void const* start;
|
||||
void const* end;
|
||||
@ -103,7 +98,7 @@ namespace test
|
||||
|
||||
void allocator_unref()
|
||||
{
|
||||
BOOST_CHECK(count_allocators > 0);
|
||||
BOOST_TEST(count_allocators > 0);
|
||||
if(count_allocators > 0) {
|
||||
--count_allocators;
|
||||
if(count_allocators == 0) {
|
||||
@ -116,9 +111,9 @@ namespace test
|
||||
count_constructions = 0;
|
||||
allocated_memory.clear();
|
||||
|
||||
BOOST_CHECK(no_allocations_left);
|
||||
BOOST_CHECK(no_constructions_left);
|
||||
BOOST_CHECK(allocated_memory_empty);
|
||||
BOOST_TEST(no_allocations_left);
|
||||
BOOST_TEST(no_constructions_left);
|
||||
BOOST_TEST(allocated_memory_empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,12 +139,12 @@ namespace test
|
||||
if(pos == allocated_memory.end()) {
|
||||
BOOST_ERROR("Deallocating unknown pointer.");
|
||||
} else {
|
||||
BOOST_CHECK(pos->first.start == ptr);
|
||||
BOOST_CHECK(pos->first.end == (char*) ptr + n * size);
|
||||
BOOST_CHECK(pos->second.tag_ == tag);
|
||||
BOOST_TEST(pos->first.start == ptr);
|
||||
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
|
||||
BOOST_TEST(pos->second.tag_ == tag);
|
||||
allocated_memory.erase(pos);
|
||||
}
|
||||
BOOST_CHECK(count_allocations > 0);
|
||||
BOOST_TEST(count_allocations > 0);
|
||||
if(count_allocations > 0) --count_allocations;
|
||||
}
|
||||
|
||||
@ -160,7 +155,7 @@ namespace test
|
||||
|
||||
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
|
||||
{
|
||||
BOOST_CHECK(count_constructions > 0);
|
||||
BOOST_TEST(count_constructions > 0);
|
||||
if(count_constructions > 0) --count_constructions;
|
||||
}
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
@ -20,18 +20,22 @@ namespace test
|
||||
{
|
||||
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
|
||||
values_type values_;
|
||||
unsigned int allocations_;
|
||||
public:
|
||||
void store(X const& x) {
|
||||
void store(X const& x, unsigned int allocations = 0) {
|
||||
DISABLE_EXCEPTIONS;
|
||||
values_.clear();
|
||||
values_.insert(x.cbegin(), x.cend());
|
||||
allocations_ = allocations;
|
||||
}
|
||||
|
||||
void test(X const& x) const {
|
||||
void test(X const& x, unsigned int allocations = 0) const {
|
||||
if(!(x.size() == values_.size() &&
|
||||
std::equal(x.cbegin(), x.cend(), values_.begin(),
|
||||
test::equivalent)))
|
||||
BOOST_ERROR("Strong exception safety failure.");
|
||||
if(allocations != allocations_)
|
||||
BOOST_ERROR("Strong exception failure: extra allocations.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,20 +1,12 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_TEST_HEADER
|
||||
|
||||
#if defined(BOOST_UNORDERED_FULL_TEST)
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#define UNORDERED_AUTO_TEST(x) BOOST_AUTO_TEST_CASE(x)
|
||||
#define RUN_TESTS()
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <iostream>
|
||||
@ -30,7 +22,8 @@
|
||||
}; \
|
||||
BOOST_PP_CAT(x, _type) x; \
|
||||
void BOOST_PP_CAT(x, _type)::run()
|
||||
#define RUN_TESTS() int test_main(int, char**) { ::test::test_list::run_tests(); return 0; }
|
||||
#define RUN_TESTS() int main(int, char**) \
|
||||
{ ::test::test_list::run_tests(); return boost::report_errors(); }
|
||||
|
||||
namespace test {
|
||||
struct registered_test_base {
|
||||
@ -74,8 +67,6 @@ namespace test {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/preprocessor/seq/for_each_product.hpp>
|
||||
#include <boost/preprocessor/seq/fold_left.hpp>
|
||||
#include <boost/preprocessor/seq/to_tuple.hpp>
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -49,7 +49,7 @@ namespace test
|
||||
value_list values2(x2.begin(), x2.end());
|
||||
values1.sort();
|
||||
values2.sort();
|
||||
BOOST_CHECK(values1.size() == values2.size() &&
|
||||
BOOST_TEST(values1.size() == values2.size() &&
|
||||
std::equal(values1.begin(), values1.end(), values2.begin(),
|
||||
test::equivalent));
|
||||
}
|
||||
@ -61,7 +61,7 @@ namespace test
|
||||
test::list<T> values2(x2.first, x2.second);
|
||||
values1.sort();
|
||||
values2.sort();
|
||||
BOOST_CHECK(values1.size() == values2.size() &&
|
||||
BOOST_TEST(values1.size() == values2.size() &&
|
||||
std::equal(values1.begin(), values1.end(), values2.begin(), test::equivalent));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <new>
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include "../helpers/allocator.hpp"
|
||||
#include "./memory.hpp"
|
||||
#include "../helpers/memory.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
@ -347,7 +347,7 @@ namespace exception
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -229,7 +229,7 @@ namespace minimal
|
||||
|
||||
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
new((void*)p.ptr_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
@ -240,7 +240,7 @@ namespace minimal
|
||||
size_type max_size() const { return 1000; }
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
|
||||
BOOST_WORKAROUND(MSVC, <= 1300)
|
||||
BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
public: allocator& operator=(allocator const&) { return *this;}
|
||||
#else
|
||||
private: allocator& operator=(allocator const&);
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <iostream>
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include "../helpers/count.hpp"
|
||||
#include "./memory.hpp"
|
||||
#include "../helpers/memory.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace test
|
||||
@ -93,6 +93,10 @@ namespace test
|
||||
return x1.type_ != x2.type_;
|
||||
}
|
||||
};
|
||||
|
||||
std::size_t hash_value(test::object const& x) {
|
||||
return hash()(x);
|
||||
}
|
||||
|
||||
class less
|
||||
{
|
||||
@ -156,6 +160,11 @@ namespace test
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This won't be a problem as I'm only using a single compile unit
|
||||
// in each test (this is actually require by the minimal test
|
||||
// framework).
|
||||
//
|
||||
// boostinspect:nounnamed
|
||||
namespace {
|
||||
test::detail::memory_tracker<std::allocator<int> > tracker;
|
||||
}
|
||||
@ -213,7 +222,7 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
|
@ -7,13 +7,17 @@ import testing ;
|
||||
|
||||
project unordered-test/unordered
|
||||
: requirements
|
||||
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
|
||||
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
|
||||
#<toolset>msvc:<cxxflags>/W4
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>intel:<cxxflags>-strict-ansi
|
||||
<toolset>msvc:<cxxflags>/W4
|
||||
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter -pedantic"
|
||||
;
|
||||
|
||||
test-suite unordered
|
||||
:
|
||||
[ run fwd_set_test.cpp ]
|
||||
[ run fwd_map_test.cpp ]
|
||||
[ run compile_set.cpp ]
|
||||
[ run compile_map.cpp ]
|
||||
[ run link_test_1.cpp link_test_2.cpp ]
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -27,9 +27,9 @@ void assign_tests1(T*, test::random_generator generator = test::default_generato
|
||||
{
|
||||
T x;
|
||||
x = x;
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests1.2\n";
|
||||
@ -47,7 +47,7 @@ void assign_tests1(T*, test::random_generator generator = test::default_generato
|
||||
y.max_load_factor(x.max_load_factor() / 20);
|
||||
y = x;
|
||||
tracker.compare(y);
|
||||
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,8 +67,8 @@ void assign_tests2(T*, test::random_generator generator = test::default_generato
|
||||
T x1(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
test::check_container(x2, v);
|
||||
}
|
||||
|
||||
@ -78,9 +78,9 @@ void assign_tests2(T*, test::random_generator generator = test::default_generato
|
||||
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
|
||||
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
|
||||
x2 = x1;
|
||||
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
|
||||
BOOST_CHECK(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
test::check_container(x2, v1);
|
||||
}
|
||||
}
|
||||
@ -103,6 +103,37 @@ UNORDERED_TEST(assign_tests2,
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
std::initializer_list<std::pair<int const, int> > init;
|
||||
boost::unordered_map<int, int> x1;
|
||||
x1[25] = 3;
|
||||
x1[16] = 10;
|
||||
BOOST_TEST(!x1.empty());
|
||||
x1 = init;
|
||||
BOOST_TEST(x1.empty());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
UNORDERED_AUTO_TEST(assign_initializer_list)
|
||||
{
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
|
||||
boost::unordered_set<int> x;
|
||||
x.insert(10);
|
||||
x.insert(20);
|
||||
x = { 1, 2, -10 };
|
||||
BOOST_TEST(x.find(10) == x.end());
|
||||
BOOST_TEST(x.find(-10) != x.end());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2007-2008 Daniel James.
|
||||
// Copyright 2007-2009 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)
|
||||
|
||||
@ -16,8 +16,8 @@ UNORDERED_AUTO_TEST(at_tests) {
|
||||
x["one"] = 1;
|
||||
x["two"] = 2;
|
||||
|
||||
BOOST_CHECK(x.at("one") == 1);
|
||||
BOOST_CHECK(x.at("two") == 2);
|
||||
BOOST_TEST(x.at("one") == 1);
|
||||
BOOST_TEST(x.at("two") == 2);
|
||||
|
||||
try {
|
||||
x.at("three");
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -24,7 +24,7 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
|
||||
|
||||
X x(v.begin(), v.end());
|
||||
|
||||
BOOST_CHECK(x.bucket_count() < x.max_bucket_count());
|
||||
BOOST_TEST(x.bucket_count() < x.max_bucket_count());
|
||||
std::cerr<<x.bucket_count()<<"<"<<x.max_bucket_count()<<"\n";
|
||||
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
|
||||
@ -32,21 +32,21 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
size_type bucket = x.bucket(test::get_key<X>(*it));
|
||||
|
||||
BOOST_CHECK(bucket < x.bucket_count());
|
||||
BOOST_TEST(bucket < x.bucket_count());
|
||||
if(bucket < x.max_bucket_count()) {
|
||||
// lit? lend?? I need a new naming scheme.
|
||||
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
|
||||
while(lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) ++lit;
|
||||
BOOST_CHECK(lit != lend);
|
||||
BOOST_TEST(lit != lend);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_type i = 0; i < x.bucket_count(); ++i) {
|
||||
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.begin(i), x.end(i)));
|
||||
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.cbegin(i), x.cend(i)));
|
||||
BOOST_TEST(x.bucket_size(i) == (size_type) std::distance(x.begin(i), x.end(i)));
|
||||
BOOST_TEST(x.bucket_size(i) == (size_type) std::distance(x.cbegin(i), x.cend(i)));
|
||||
X const& x_ref = x;
|
||||
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.begin(i), x_ref.end(i)));
|
||||
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.cbegin(i), x_ref.cend(i)));
|
||||
BOOST_TEST(x.bucket_size(i) == (size_type) std::distance(x_ref.begin(i), x_ref.end(i)));
|
||||
BOOST_TEST(x.bucket_size(i) == (size_type) std::distance(x_ref.cbegin(i), x_ref.cend(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -13,6 +13,21 @@
|
||||
#include "../objects/minimal.hpp"
|
||||
#include "./compile_tests.hpp"
|
||||
|
||||
// Explicit instantiation to catch compile-time errors
|
||||
|
||||
template class boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::default_copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
template class boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
|
||||
UNORDERED_AUTO_TEST(test0)
|
||||
{
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -13,6 +13,19 @@
|
||||
#include "../objects/minimal.hpp"
|
||||
#include "./compile_tests.hpp"
|
||||
|
||||
// Explicit instantiation to catch compile-time errors
|
||||
|
||||
template class boost::unordered_set<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
template class boost::unordered_multiset<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
|
||||
UNORDERED_AUTO_TEST(test0)
|
||||
{
|
||||
test::minimal::assignable assignable = test::minimal::assignable::create();
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2005-2008 Daniel James.
|
||||
// Copyright 2005-2009 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)
|
||||
|
||||
@ -87,10 +87,10 @@ void container_test(X& r, T const&)
|
||||
// I'm not sure about either of these tests...
|
||||
size_type max_diff((std::numeric_limits<difference_type>::max)());
|
||||
difference_type converted_diff(max_diff);
|
||||
BOOST_CHECK((std::numeric_limits<difference_type>::max)()
|
||||
BOOST_TEST((std::numeric_limits<difference_type>::max)()
|
||||
== converted_diff);
|
||||
|
||||
BOOST_CHECK(
|
||||
BOOST_TEST(
|
||||
static_cast<comparison_type>(
|
||||
(std::numeric_limits<size_type>::max)()) >
|
||||
static_cast<comparison_type>(
|
||||
@ -98,8 +98,8 @@ void container_test(X& r, T const&)
|
||||
|
||||
// I don't test the runtime post-conditions here.
|
||||
X u;
|
||||
BOOST_CHECK(u.size() == 0);
|
||||
BOOST_CHECK(X().size() == 0);
|
||||
BOOST_TEST(u.size() == 0);
|
||||
BOOST_TEST(X().size() == 0);
|
||||
|
||||
X a,b;
|
||||
|
||||
@ -151,14 +151,12 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
|
||||
r.insert(std::pair<Key const, T>(k, v));
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
Key k_lvalue(k);
|
||||
T v_lvalue(v);
|
||||
|
||||
r.emplace(k, v);
|
||||
r.emplace(k_lvalue, v_lvalue);
|
||||
r.emplace(rvalue(k), rvalue(v));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X>
|
||||
@ -168,11 +166,6 @@ void equality_test(X& r)
|
||||
|
||||
test::check_return_type<bool>::equals(a == b);
|
||||
test::check_return_type<bool>::equals(a != b);
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
test::check_return_type<std::size_t>::equals(boost::hash_value(a));
|
||||
#else
|
||||
test::check_return_type<std::size_t>::equals(hash_value(a));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
@ -180,9 +173,7 @@ void unordered_unique_test(X& r, T const& t)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
@ -190,9 +181,7 @@ void unordered_equivalent_test(X& r, T const& t)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
test::check_return_type<iterator>::equals(r.insert(t));
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
test::check_return_type<iterator>::equals(r.emplace(t));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X, class Key, class T>
|
||||
@ -294,14 +283,12 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
test::check_return_type<iterator>::equals(a.emplace(q, t));
|
||||
#endif
|
||||
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
|
||||
|
||||
a.insert(i, j);
|
||||
test::check_return_type<size_type>::equals(a.erase(k));
|
||||
|
||||
BOOST_CHECK(a.empty());
|
||||
BOOST_TEST(a.empty());
|
||||
if(a.empty()) {
|
||||
a.insert(t);
|
||||
q = a.cbegin();
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -29,42 +29,42 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
std::cerr<<"Construct 1\n";
|
||||
{
|
||||
T x(0, hf, eq);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 2\n";
|
||||
{
|
||||
T x(100, hf);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(x.bucket_count() >= 100);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 3\n";
|
||||
{
|
||||
T x(2000);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(x.bucket_count() >= 2000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 2000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 4\n";
|
||||
{
|
||||
T x;
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@ -72,10 +72,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(1000, generator);
|
||||
T x(v.begin(), v.end(), 10000, hf, eq);
|
||||
BOOST_CHECK(x.bucket_count() >= 10000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -84,10 +84,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(10, generator);
|
||||
T x(v.begin(), v.end(), 10000, hf);
|
||||
BOOST_CHECK(x.bucket_count() >= 10000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -96,10 +96,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(100, generator);
|
||||
T x(v.begin(), v.end(), 100);
|
||||
BOOST_CHECK(x.bucket_count() >= 100);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -108,9 +108,9 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(1, generator);
|
||||
T x(v.begin(), v.end());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -118,10 +118,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
std::cerr<<"Construct 9\n";
|
||||
{
|
||||
T x(0, hf, eq, al);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@ -129,10 +129,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(1000, generator);
|
||||
T x(v.begin(), v.end(), 10000, hf, eq, al);
|
||||
BOOST_CHECK(x.bucket_count() >= 10000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -141,10 +141,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
|
||||
{
|
||||
test::random_values<T> v(1000, generator);
|
||||
T x(al);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
@ -165,21 +165,21 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
|
||||
std::cerr<<"Construct 1\n";
|
||||
{
|
||||
T x(10000, hf1, eq1);
|
||||
BOOST_CHECK(x.bucket_count() >= 10000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 2\n";
|
||||
{
|
||||
T x(100, hf1);
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(x.bucket_count() >= 100);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@ -187,9 +187,9 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
|
||||
{
|
||||
test::random_values<T> v(100, generator);
|
||||
T x(v.begin(), v.end(), 0, hf1, eq1);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -198,10 +198,10 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
|
||||
{
|
||||
test::random_values<T> v(5, generator);
|
||||
T x(v.begin(), v.end(), 1000, hf1);
|
||||
BOOST_CHECK(x.bucket_count() >= 1000);
|
||||
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
|
||||
BOOST_TEST(x.bucket_count() >= 1000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@ -250,6 +250,72 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 9\n";
|
||||
{
|
||||
test::random_values<T> v(100, generator);
|
||||
T x(50);
|
||||
BOOST_TEST(x.bucket_count() >= 50);
|
||||
x.max_load_factor(10);
|
||||
BOOST_TEST(x.bucket_count() >= 50);
|
||||
x.insert(v.begin(), v.end());
|
||||
BOOST_TEST(x.bucket_count() >= 50);
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
|
||||
|
||||
std::cerr<<"Initializer list construct 1\n";
|
||||
{
|
||||
T x(list);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr<<"Initializer list construct 2\n";
|
||||
{
|
||||
T x(list, 1000);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 1000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr<<"Initializer list construct 3\n";
|
||||
{
|
||||
T x(list, 10, hf1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr<<"Initializer list construct 4\n";
|
||||
{
|
||||
T x(list, 10, hf1, eq1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr<<"Initializer list construct 5\n";
|
||||
{
|
||||
T x(list, 10, hf1, eq1, al1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -288,6 +354,28 @@ UNORDERED_TEST(map_constructor_test,
|
||||
((test_map)(test_multimap))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_default_initializer_list) {
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
std::initializer_list<int> init;
|
||||
boost::unordered_set<int> x1 = init;
|
||||
BOOST_TEST(x1.empty());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_initializer_list) {
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
boost::unordered_set<int> x1 = { 2, 10, 45, -5 };
|
||||
BOOST_TEST(x1.find(10) != x1.end());
|
||||
BOOST_TEST(x1.find(46) == x1.end());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -27,11 +27,11 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
|
||||
{
|
||||
T x;
|
||||
T y(x);
|
||||
BOOST_CHECK(y.empty());
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
|
||||
T x(v.begin(), v.end());
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
BOOST_TEST(equivalent(y));
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
@ -55,9 +55,9 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
|
||||
x.max_load_factor(x.load_factor() / 4);
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
BOOST_TEST(equivalent(y));
|
||||
// This isn't guaranteed:
|
||||
BOOST_CHECK(y.load_factor() < y.max_load_factor());
|
||||
BOOST_TEST(y.load_factor() < y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
}
|
||||
@ -75,22 +75,22 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
|
||||
{
|
||||
T x(10000, hf, eq, al);
|
||||
T y(x);
|
||||
BOOST_CHECK(y.empty());
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
{
|
||||
T x(1000, hf, eq, al);
|
||||
T y(x, al2);
|
||||
BOOST_CHECK(y.empty());
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
|
||||
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
@ -100,9 +100,9 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
|
||||
T x(v.begin(), v.end(), 0, hf, eq, al);
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
BOOST_TEST(equivalent(y));
|
||||
test::check_equivalent_keys(y);
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
}
|
||||
|
||||
{
|
||||
@ -111,9 +111,9 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
|
||||
T x(v.begin(), v.end(), 0, hf, eq, al);
|
||||
T y(x, al2);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
BOOST_TEST(equivalent(y));
|
||||
test::check_equivalent_keys(y);
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2008 Daniel James.
|
||||
// Copyright 2008-2009 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)
|
||||
|
||||
@ -13,6 +13,10 @@ namespace equality_tests
|
||||
{
|
||||
struct mod_compare
|
||||
{
|
||||
bool alt_hash_;
|
||||
|
||||
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
|
||||
|
||||
bool operator()(int x, int y) const
|
||||
{
|
||||
return x % 1000 == y % 1000;
|
||||
@ -20,123 +24,142 @@ namespace equality_tests
|
||||
|
||||
int operator()(int x) const
|
||||
{
|
||||
return x % 250;
|
||||
return alt_hash_ ? x % 250 : (x + 5) % 250;
|
||||
}
|
||||
};
|
||||
|
||||
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
|
||||
do { \
|
||||
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_CHECK(set1 op set2); \
|
||||
} while(false)
|
||||
do { \
|
||||
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_TEST(set1 op set2); \
|
||||
} while(false)
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
|
||||
do { \
|
||||
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_CHECK(set1 op set2); \
|
||||
} while(false)
|
||||
do { \
|
||||
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_TEST(set1 op set2); \
|
||||
} while(false)
|
||||
|
||||
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
|
||||
do { \
|
||||
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_CHECK(map1 op map2); \
|
||||
} while(false)
|
||||
do { \
|
||||
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_TEST(map1 op map2); \
|
||||
} while(false)
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
|
||||
do { \
|
||||
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_CHECK(map1 op map2); \
|
||||
} while(false)
|
||||
do { \
|
||||
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_TEST(map1 op map2); \
|
||||
} while(false)
|
||||
|
||||
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
|
||||
#define UNORDERED_MAP_INSERT(r, map, item) \
|
||||
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
|
||||
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_size_tests)
|
||||
{
|
||||
boost::unordered_set<int> x1, x2;
|
||||
BOOST_CHECK(x1 == x2);
|
||||
BOOST_CHECK(!(x1 != x2));
|
||||
UNORDERED_AUTO_TEST(equality_size_tests)
|
||||
{
|
||||
boost::unordered_set<int> x1, x2;
|
||||
BOOST_TEST(x1 == x2);
|
||||
BOOST_TEST(!(x1 != x2));
|
||||
|
||||
x1.insert(1);
|
||||
BOOST_CHECK(x1 != x2);
|
||||
BOOST_CHECK(!(x1 == x2));
|
||||
BOOST_CHECK(x2 != x1);
|
||||
BOOST_CHECK(!(x2 == x1));
|
||||
|
||||
x2.insert(1);
|
||||
BOOST_CHECK(x1 == x2);
|
||||
BOOST_CHECK(!(x1 != x2));
|
||||
|
||||
x2.insert(2);
|
||||
BOOST_CHECK(x1 != x2);
|
||||
BOOST_CHECK(!(x1 == x2));
|
||||
BOOST_CHECK(x2 != x1);
|
||||
BOOST_CHECK(!(x2 == x1));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_key_value_tests)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2));
|
||||
UNORDERED_EQUALITY_SET_TEST((2), ==, (2));
|
||||
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)));
|
||||
}
|
||||
|
||||
x1.insert(1);
|
||||
BOOST_TEST(x1 != x2);
|
||||
BOOST_TEST(!(x1 == x2));
|
||||
BOOST_TEST(x2 != x1);
|
||||
BOOST_TEST(!(x2 == x1));
|
||||
|
||||
x2.insert(1);
|
||||
BOOST_TEST(x1 == x2);
|
||||
BOOST_TEST(!(x1 != x2));
|
||||
|
||||
x2.insert(2);
|
||||
BOOST_TEST(x1 != x2);
|
||||
BOOST_TEST(!(x1 == x2));
|
||||
BOOST_TEST(x2 != x1);
|
||||
BOOST_TEST(!(x2 == x1));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_key_value_tests)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2));
|
||||
UNORDERED_EQUALITY_SET_TEST((2), ==, (2));
|
||||
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_collision_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1), !=, (501));
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(251), !=, (1)(501));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)));
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(501), ==, (1)(501));
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1)(501), ==, (501)(1));
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1), !=, (501));
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(251), !=, (1)(501));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)));
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(501), ==, (1)(501));
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1)(501), ==, (501)(1));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_group_size_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(10)(20)(20), !=, (10)(10)(20));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((10)(1))((20)(1))((20)(1)), !=,
|
||||
((10)(1))((20)(1))((10)(1)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((20)(1))((10)(1))((10)(1)), ==,
|
||||
((10)(1))((20)(1))((10)(1)));
|
||||
UNORDERED_AUTO_TEST(equality_group_size_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(10)(20)(20), !=, (10)(10)(20));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((10)(1))((20)(1))((20)(1)), !=,
|
||||
((10)(1))((20)(1))((10)(1)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((20)(1))((10)(1))((10)(1)), ==,
|
||||
((10)(1))((20)(1))((10)(1)));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_map_value_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)));
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), ==, ((1)(1)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)));
|
||||
}
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)));
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), ==, ((1)(1)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)));
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_predicate_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1), ==, (1001));
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)));
|
||||
}
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1), ==, (1001));
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)));
|
||||
}
|
||||
|
||||
// Test that equality still works when the two containers have
|
||||
// different hash functions but the same equality predicate.
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_different_hash_test)
|
||||
{
|
||||
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
|
||||
set set1(0, mod_compare(false), mod_compare(false));
|
||||
set set2(0, mod_compare(true), mod_compare(true));
|
||||
BOOST_TEST(set1 == set2);
|
||||
set1.insert(1); set2.insert(2);
|
||||
BOOST_TEST(set1 != set2);
|
||||
set1.insert(2); set2.insert(1);
|
||||
BOOST_TEST(set1 == set2);
|
||||
set1.insert(10); set2.insert(20);
|
||||
BOOST_TEST(set1 != set2);
|
||||
set1.insert(20); set2.insert(10);
|
||||
BOOST_TEST(set1 == set2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -67,11 +67,11 @@ UNORDERED_AUTO_TEST(single_item_tests)
|
||||
|
||||
collide_map x(init.begin(), init.end());
|
||||
x.erase(x.begin(), x.begin());
|
||||
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
|
||||
x.erase(x.end(), x.end());
|
||||
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
|
||||
x.erase(x.begin(), x.end());
|
||||
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
|
||||
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
|
||||
@ -83,14 +83,14 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
|
||||
{
|
||||
collide_map x(init.begin(), init.end());
|
||||
x.erase(x.begin(), x.end());
|
||||
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
|
||||
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
collide_map x(init.begin(), init.end());
|
||||
int value = boost::next(x.begin())->second;
|
||||
x.erase(x.begin(), boost::next(x.begin()));
|
||||
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
|
||||
x.begin()->first == 1 && x.begin()->second == value);
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
|
||||
collide_map x(init.begin(), init.end());
|
||||
int value = x.begin()->second;
|
||||
x.erase(boost::next(x.begin()), x.end());
|
||||
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
|
||||
x.begin()->first == 1 && x.begin()->second == value);
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ bool compare(Range1 const& x, Range2 const& y)
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
bool general_erase_range_test(Container& x, int start, int end)
|
||||
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
|
||||
{
|
||||
collide_list l(x.begin(), x.end());
|
||||
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -32,10 +32,10 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
|
||||
{
|
||||
std::size_t count = x.count(test::get_key<Container>(*it));
|
||||
std::size_t old_size = x.size();
|
||||
BOOST_CHECK(count == x.erase(test::get_key<Container>(*it)));
|
||||
BOOST_CHECK(x.size() == old_size - count);
|
||||
BOOST_CHECK(x.count(test::get_key<Container>(*it)) == 0);
|
||||
BOOST_CHECK(x.find(test::get_key<Container>(*it)) == x.end());
|
||||
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
|
||||
BOOST_TEST(x.size() == old_size - count);
|
||||
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
|
||||
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,11 +50,11 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
|
||||
std::size_t count = x.count(key);
|
||||
BOOST_DEDUCED_TYPENAME Container::iterator pos = x.erase(x.begin());
|
||||
--size;
|
||||
BOOST_CHECK(pos == x.begin());
|
||||
BOOST_CHECK(x.count(key) == count - 1);
|
||||
BOOST_CHECK(x.size() == size);
|
||||
BOOST_TEST(pos == x.begin());
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
}
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr<<"erase(random position).\n";
|
||||
@ -77,15 +77,15 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
|
||||
next = boost::next(pos);
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type key = test::get_key<Container>(*pos);
|
||||
std::size_t count = x.count(key);
|
||||
BOOST_CHECK(next == x.erase(pos));
|
||||
BOOST_TEST(next == x.erase(pos));
|
||||
--size;
|
||||
if(size > 0)
|
||||
BOOST_CHECK(index == 0 ? next == x.begin() :
|
||||
BOOST_TEST(index == 0 ? next == x.begin() :
|
||||
next == boost::next(prev));
|
||||
BOOST_CHECK(x.count(key) == count - 1);
|
||||
BOOST_CHECK(x.size() == size);
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
}
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr<<"erase(ranges).\n";
|
||||
@ -99,15 +99,15 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
|
||||
// returns 'the iterator immediately following the erase elements'
|
||||
// and if nothing is erased, then there's nothing to follow. But I
|
||||
// think this is the only sensible option...
|
||||
BOOST_CHECK(x.erase(x.end(), x.end()) == x.end());
|
||||
BOOST_CHECK(x.erase(x.begin(), x.begin()) == x.begin());
|
||||
BOOST_CHECK(x.size() == size);
|
||||
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
|
||||
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
|
||||
BOOST_TEST(x.size() == size);
|
||||
|
||||
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.end());
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(x.begin() == x.end());
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
|
||||
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.begin());
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
|
||||
}
|
||||
|
||||
std::cerr<<"clear().\n";
|
||||
@ -115,8 +115,8 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
|
||||
test::random_values<Container> v(500, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
x.clear();
|
||||
BOOST_CHECK(x.empty());
|
||||
BOOST_CHECK(x.begin() == x.end());
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
}
|
||||
|
||||
std::cerr<<"\n";
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -34,12 +34,12 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
|
||||
iterator pos = x.find(key);
|
||||
BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = x_const.find(key);
|
||||
BOOST_CHECK(pos != x.end() &&
|
||||
BOOST_TEST(pos != x.end() &&
|
||||
x.key_eq()(key, test::get_key<X>(*pos)));
|
||||
BOOST_CHECK(const_pos != x_const.end() &&
|
||||
BOOST_TEST(const_pos != x_const.end() &&
|
||||
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
|
||||
|
||||
BOOST_CHECK(x.count(key) == tracker.count(key));
|
||||
BOOST_TEST(x.count(key) == tracker.count(key));
|
||||
|
||||
test::compare_pairs(x.equal_range(key),
|
||||
tracker.equal_range(key),
|
||||
@ -56,11 +56,11 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2);
|
||||
if(tracker.find(test::get_key<X>(key)) == tracker.end())
|
||||
{
|
||||
BOOST_CHECK(x.find(key) == x.end());
|
||||
BOOST_CHECK(x_const.find(key) == x_const.end());
|
||||
BOOST_CHECK(x.count(key) == 0);
|
||||
BOOST_TEST(x.find(key) == x.end());
|
||||
BOOST_TEST(x_const.find(key) == x_const.end());
|
||||
BOOST_TEST(x.count(key) == 0);
|
||||
std::pair<iterator, iterator> range = x.equal_range(key);
|
||||
BOOST_CHECK(range.first == range.second);
|
||||
BOOST_TEST(range.first == range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,10 +73,10 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
v2.begin(); it3 != v2.end(); ++it3)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3);
|
||||
BOOST_CHECK(x.find(key) == x.end());
|
||||
BOOST_CHECK(x.count(key) == 0);
|
||||
BOOST_TEST(x.find(key) == x.end());
|
||||
BOOST_TEST(x.count(key) == 0);
|
||||
std::pair<iterator, iterator> range = x.equal_range(key);
|
||||
BOOST_CHECK(range.first == range.second);
|
||||
BOOST_TEST(range.first == range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
test/unordered/fwd_map_test.cpp
Normal file
62
test/unordered/fwd_map_test.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
// Copyright 2008-2009 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)
|
||||
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
|
||||
typedef boost::unordered_map<int, int> int_map;
|
||||
|
||||
void call_swap(int_map& x, int_map& y) {
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_map& x, int_map& y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_map& x, int_map& y) {
|
||||
return x != y;
|
||||
}
|
||||
|
||||
typedef boost::unordered_multimap<int, int> int_multimap;
|
||||
|
||||
void call_swap(int_multimap& x, int_multimap& y) {
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_multimap& x, int_multimap& y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_multimap& x, int_multimap& y) {
|
||||
return x != y;
|
||||
}
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
|
||||
int_map x, y;
|
||||
x[1] = 2;
|
||||
y[2] = 1;
|
||||
call_swap(x, y);
|
||||
|
||||
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
|
||||
BOOST_TEST(y.find(2) == y.end());
|
||||
|
||||
BOOST_TEST(x.find(1) == x.end());
|
||||
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
|
||||
|
||||
BOOST_TEST(!call_equals(x, y));
|
||||
BOOST_TEST(call_not_equals(x, y));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function) {
|
||||
int_multimap x, y;
|
||||
call_swap(x, y);
|
||||
BOOST_TEST(call_equals(x, y));
|
||||
BOOST_TEST(!call_not_equals(x, y));
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
84
test/unordered/fwd_set_test.cpp
Normal file
84
test/unordered/fwd_set_test.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
// Copyright 2008-2009 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)
|
||||
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
|
||||
struct true_type { char x[100]; };
|
||||
struct false_type { char x; };
|
||||
|
||||
false_type is_unordered_set_impl(void*);
|
||||
|
||||
template <class Value, class Hash, class Pred, class Alloc>
|
||||
true_type is_unordered_set_impl(
|
||||
boost::unordered_set<Value, Hash, Pred, Alloc>*);
|
||||
|
||||
typedef boost::unordered_set<int> int_set;
|
||||
|
||||
void call_swap(int_set& x, int_set& y) {
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_set& x, int_set& y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_set& x, int_set& y) {
|
||||
return x != y;
|
||||
}
|
||||
|
||||
typedef boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
void call_swap(int_multiset& x, int_multiset& y) {
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_multiset& x, int_multiset& y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_multiset& x, int_multiset& y) {
|
||||
return x != y;
|
||||
}
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
|
||||
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0)) == sizeof(true_type));
|
||||
}
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
UNORDERED_AUTO_TEST(use_fwd_declared_trait) {
|
||||
boost::unordered_set<int> x;
|
||||
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
|
||||
|
||||
int dummy;
|
||||
BOOST_TEST(sizeof(is_unordered_set_impl(&dummy)) == sizeof(false_type));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(use_set_fwd_declared_function) {
|
||||
int_set x, y;
|
||||
x.insert(1);
|
||||
y.insert(2);
|
||||
call_swap(x, y);
|
||||
|
||||
BOOST_TEST(y.find(1) != y.end());
|
||||
BOOST_TEST(y.find(2) == y.end());
|
||||
|
||||
BOOST_TEST(x.find(1) == x.end());
|
||||
BOOST_TEST(x.find(2) != x.end());
|
||||
|
||||
BOOST_TEST(!call_equals(x, y));
|
||||
BOOST_TEST(call_not_equals(x, y));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function) {
|
||||
int_multiset x, y;
|
||||
call_swap(x, y);
|
||||
BOOST_TEST(call_equals(x, y));
|
||||
BOOST_TEST(!call_not_equals(x, y));
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2007-2008 Daniel James.
|
||||
// Copyright 2007-2009 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)
|
||||
|
||||
@ -47,13 +47,13 @@ UNORDERED_AUTO_TEST(stable_insert_test1) {
|
||||
x.insert(insert_stable::member(1,3));
|
||||
|
||||
boost::unordered_multiset<insert_stable::member>::const_iterator it = x.begin(), end = x.end();
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->tag2_ == 1); ++it; }
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->tag2_ == 2); ++it; }
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->tag2_ == 3); ++it; }
|
||||
BOOST_CHECK(it == end);
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->tag2_ == 1); ++it; }
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->tag2_ == 2); ++it; }
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->tag2_ == 3); ++it; }
|
||||
BOOST_TEST(it == end);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(stable_insert_test2) {
|
||||
@ -66,13 +66,13 @@ UNORDERED_AUTO_TEST(stable_insert_test2) {
|
||||
|
||||
it = x.begin();
|
||||
iterator end = x.end();
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->first.tag2_ == 1 && it->second == 1); ++it; }
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->first.tag2_ == 2 && it->second == 2); ++it; }
|
||||
BOOST_CHECK(it != end);
|
||||
if(it != end) { BOOST_CHECK(it->first.tag2_ == 3 && it->second == 3); ++it; }
|
||||
BOOST_CHECK(it == end);
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->first.tag2_ == 1 && it->second == 1); ++it; }
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->first.tag2_ == 2 && it->second == 2); ++it; }
|
||||
BOOST_TEST(it != end);
|
||||
if(it != end) { BOOST_TEST(it->first.tag2_ == 3 && it->second == 3); ++it; }
|
||||
BOOST_TEST(it == end);
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -43,13 +43,13 @@ void unique_insert_tests1(X*, test::random_generator generator = test::default_g
|
||||
std::pair<iterator, bool> r1 = x.insert(*it);
|
||||
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 = tracker.insert(*it);
|
||||
|
||||
BOOST_CHECK(r1.second == r2.second);
|
||||
BOOST_CHECK(*r1.first == *r2.first);
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -73,12 +73,12 @@ void equivalent_insert_tests1(X*, test::random_generator generator = test::defau
|
||||
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it);
|
||||
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 = tracker.insert(*it);
|
||||
|
||||
BOOST_CHECK(*r1 == *r2);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -107,11 +107,11 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
|
||||
|
||||
iterator r1 = x.insert(x.begin(), *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
|
||||
BOOST_CHECK(*r1 == *r2);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -133,11 +133,11 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
|
||||
|
||||
const_iterator r1 = x.insert(x_const.end(), *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.end(), *it);
|
||||
BOOST_CHECK(*r1 == *r2);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -159,11 +159,11 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
|
||||
|
||||
pos = x.insert(pos, *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
|
||||
BOOST_CHECK(*pos == *r2);
|
||||
BOOST_TEST(*pos == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -187,7 +187,7 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -243,13 +243,13 @@ void unique_emplace_tests1(X*, test::random_generator generator = test::default_
|
||||
std::pair<iterator, bool> r1 = x.emplace(*it);
|
||||
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 = tracker.insert(*it);
|
||||
|
||||
BOOST_CHECK(r1.second == r2.second);
|
||||
BOOST_CHECK(*r1.first == *r2.first);
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -273,12 +273,12 @@ void equivalent_emplace_tests1(X*, test::random_generator generator = test::defa
|
||||
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.emplace(*it);
|
||||
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 = tracker.insert(*it);
|
||||
|
||||
BOOST_CHECK(*r1 == *r2);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
@ -307,16 +307,18 @@ void map_tests(X*, test::random_generator generator = test::default_generator)
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
// Some tests for when the range's value type doesn't match the container's value type.
|
||||
|
||||
template <class X>
|
||||
void associative_insert_range_test(X*, test::random_generator generator = test::default_generator)
|
||||
void map_insert_range_test1(X*, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"associative_insert_range_test\n";
|
||||
std::cerr<<"map_insert_range_test1\n";
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME X::key_type, BOOST_DEDUCED_TYPENAME X::mapped_type> > list;
|
||||
test::random_values<X> v(1000, generator);
|
||||
@ -327,6 +329,20 @@ void associative_insert_range_test(X*, test::random_generator generator = test::
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void map_insert_range_test2(X*, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"map_insert_range_test2\n";
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, int> > list;
|
||||
test::random_values<boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, int> > v(1000, generator);
|
||||
list l(v.begin(), v.end());
|
||||
|
||||
X x; x.insert(l.begin(), l.end());
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
|
||||
@ -367,11 +383,64 @@ UNORDERED_TEST(map_tests,
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(associative_insert_range_test,
|
||||
UNORDERED_TEST(map_insert_range_test1,
|
||||
((test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(map_insert_range_test2,
|
||||
((test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
{
|
||||
boost::unordered_set<int> set;
|
||||
set.insert({1,2,3,1});
|
||||
BOOST_TEST_EQ(set.size(), 3u);
|
||||
BOOST_TEST(set.find(1) != set.end());
|
||||
BOOST_TEST(set.find(4) == set.end());
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
|
||||
{
|
||||
boost::unordered_multiset<std::string> multiset;
|
||||
//multiset.insert({});
|
||||
BOOST_TEST(multiset.empty());
|
||||
multiset.insert({"a"});
|
||||
BOOST_TEST_EQ(multiset.size(), 1u);
|
||||
BOOST_TEST(multiset.find("a") != multiset.end());
|
||||
BOOST_TEST(multiset.find("b") == multiset.end());
|
||||
multiset.insert({"a","b"});
|
||||
BOOST_TEST(multiset.size() == 3);
|
||||
BOOST_TEST_EQ(multiset.count("a"), 2u);
|
||||
BOOST_TEST_EQ(multiset.count("b"), 1u);
|
||||
BOOST_TEST_EQ(multiset.count("c"), 0u);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_map)
|
||||
{
|
||||
boost::unordered_map<std::string, std::string> map;
|
||||
//map.insert({});
|
||||
BOOST_TEST(map.empty());
|
||||
map.insert({{"a", "b"},{"a", "b"},{"d", ""}});
|
||||
BOOST_TEST_EQ(map.size(), 2u);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
|
||||
{
|
||||
boost::unordered_multimap<std::string, std::string> multimap;
|
||||
//multimap.insert({});
|
||||
BOOST_TEST(multimap.empty());
|
||||
multimap.insert({{"a", "b"},{"a", "b"},{"d", ""}});
|
||||
BOOST_TEST_EQ(multimap.size(), 3u);
|
||||
BOOST_TEST_EQ(multimap.count("a"), 2u);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -24,13 +24,13 @@ void set_load_factor_tests(X* = 0)
|
||||
{
|
||||
X x;
|
||||
|
||||
BOOST_CHECK(x.max_load_factor() == 1.0);
|
||||
BOOST_CHECK(x.load_factor() == 0);
|
||||
BOOST_TEST(x.max_load_factor() == 1.0);
|
||||
BOOST_TEST(x.load_factor() == 0);
|
||||
|
||||
// A valid implementation could fail these tests, but I think they're
|
||||
// reasonable.
|
||||
x.max_load_factor(2.0); BOOST_CHECK(x.max_load_factor() == 2.0);
|
||||
x.max_load_factor(0.5); BOOST_CHECK(x.max_load_factor() == 0.5);
|
||||
x.max_load_factor(2.0); BOOST_TEST(x.max_load_factor() == 2.0);
|
||||
x.max_load_factor(0.5); BOOST_TEST(x.max_load_factor() == 0.5);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
@ -49,7 +49,7 @@ void insert_test(X*, float mlf, test::random_generator generator = test::default
|
||||
old_bucket_count = x.bucket_count();
|
||||
x.insert(*it);
|
||||
if(old_size + 1 < b * old_bucket_count)
|
||||
BOOST_CHECK(x.bucket_count() == old_bucket_count);
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2008 Daniel James.
|
||||
// Copyright 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@ -52,11 +52,11 @@ namespace move_tests
|
||||
|
||||
{
|
||||
T y(empty(ptr));
|
||||
BOOST_CHECK(y.empty());
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_CHECK(y.max_load_factor() == 1.0);
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(y.max_load_factor() == 1.0);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ namespace move_tests
|
||||
test::random_values<T> v(1000, generator);
|
||||
test::object_count count;
|
||||
T y(create(v, count));
|
||||
BOOST_CHECK(count == test::global_object_count);
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
test::check_container(y, v);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
@ -78,7 +78,7 @@ namespace move_tests
|
||||
test::object_count count;
|
||||
T y;
|
||||
y = create(v, count);
|
||||
BOOST_CHECK(count == test::global_object_count);
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
test::check_container(y, v);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
@ -98,12 +98,12 @@ namespace move_tests
|
||||
{
|
||||
test::random_values<T> v(500, generator);
|
||||
T y(create(v, count, hf, eq, al, 0.5));
|
||||
BOOST_CHECK(count == test::global_object_count);
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
test::check_container(y, v);
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_CHECK(y.max_load_factor() == 0.5); // Not necessarily required.
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
@ -111,33 +111,33 @@ namespace move_tests
|
||||
// TODO: To do this correctly requires the fancy new allocator stuff.
|
||||
test::random_values<T> v(500, generator);
|
||||
T y(create(v, count, hf, eq, al, 2.0), al2);
|
||||
BOOST_CHECK(count != test::global_object_count);
|
||||
BOOST_TEST(count != test::global_object_count);
|
||||
test::check_container(y, v);
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
|
||||
BOOST_CHECK(y.max_load_factor() == 2.0); // Not necessarily required.
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
test::random_values<T> v(25, generator);
|
||||
T y(create(v, count, hf, eq, al, 1.0), al);
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
BOOST_CHECK(count == test::global_object_count);
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
#else
|
||||
BOOST_CHECK(test::global_object_count.constructions - count.constructions <=
|
||||
BOOST_TEST(test::global_object_count.constructions - count.constructions <=
|
||||
(test::is_map<T>::value ? 50 : 25));
|
||||
BOOST_CHECK(count.instances == test::global_object_count.instances);
|
||||
BOOST_TEST(count.instances == test::global_object_count.instances);
|
||||
#endif
|
||||
test::check_container(y, v);
|
||||
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_CHECK(y.max_load_factor() == 1.0); // Not necessarily required.
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al));
|
||||
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -26,12 +26,49 @@ void rehash_empty_test1(X* = 0)
|
||||
X x;
|
||||
|
||||
x.rehash(10000);
|
||||
BOOST_CHECK(postcondition(x, 10000));
|
||||
BOOST_TEST(postcondition(x, 10000));
|
||||
|
||||
x.rehash(0);
|
||||
BOOST_CHECK(postcondition(x, 0));
|
||||
BOOST_TEST(postcondition(x, 0));
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void rehash_empty_test2(X* = 0, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::random_values<X> v(1000, generator);
|
||||
test::ordered<X> tracker;
|
||||
|
||||
X x;
|
||||
|
||||
x.rehash(10000);
|
||||
BOOST_TEST(postcondition(x, 10000));
|
||||
|
||||
tracker.insert_range(v.begin(), v.end());
|
||||
x.insert(v.begin(), v.end());
|
||||
tracker.compare(x);
|
||||
|
||||
BOOST_TEST(postcondition(x, 10000));
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void rehash_empty_test3(X* = 0, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::random_values<X> v(1000, generator);
|
||||
test::ordered<X> tracker;
|
||||
|
||||
X x;
|
||||
|
||||
x.rehash(0);
|
||||
BOOST_TEST(postcondition(x, 0));
|
||||
|
||||
tracker.insert_range(v.begin(), v.end());
|
||||
x.insert(v.begin(), v.end());
|
||||
tracker.compare(x);
|
||||
|
||||
BOOST_TEST(postcondition(x, 0));
|
||||
}
|
||||
|
||||
|
||||
template <class X>
|
||||
void rehash_test1(X* = 0, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
@ -40,18 +77,18 @@ void rehash_test1(X* = 0, test::random_generator generator = test::default_gener
|
||||
tracker.insert_range(v.begin(), v.end());
|
||||
X x(v.begin(), v.end());
|
||||
|
||||
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
|
||||
x.rehash(0); BOOST_TEST(postcondition(x, 0));
|
||||
tracker.compare(x);
|
||||
|
||||
x.max_load_factor(0.25);
|
||||
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
|
||||
x.rehash(0); BOOST_TEST(postcondition(x, 0));
|
||||
tracker.compare(x);
|
||||
|
||||
x.max_load_factor(50.0);
|
||||
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
|
||||
x.rehash(0); BOOST_TEST(postcondition(x, 0));
|
||||
tracker.compare(x);
|
||||
|
||||
x.rehash(1000); BOOST_CHECK(postcondition(x, 1000));
|
||||
x.rehash(1000); BOOST_TEST(postcondition(x, 1000));
|
||||
tracker.compare(x);
|
||||
}
|
||||
|
||||
@ -63,6 +100,12 @@ boost::unordered_multimap<int, int>* int_multimap_ptr;
|
||||
UNORDERED_TEST(rehash_empty_test1,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_empty_test2,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_empty_test3,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_test1,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -19,67 +19,68 @@ void simple_test(X const& a)
|
||||
|
||||
{
|
||||
X u;
|
||||
BOOST_CHECK(u.size() == 0);
|
||||
BOOST_CHECK(X().size() == 0);
|
||||
BOOST_TEST(u.size() == 0);
|
||||
BOOST_TEST(X().size() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_CHECK(equivalent(X(a)));
|
||||
BOOST_TEST(equivalent(X(a)));
|
||||
}
|
||||
|
||||
{
|
||||
X u(a);
|
||||
BOOST_CHECK(equivalent(u));
|
||||
BOOST_TEST(equivalent(u));
|
||||
}
|
||||
|
||||
{
|
||||
X u = a;
|
||||
BOOST_CHECK(equivalent(u));
|
||||
BOOST_TEST(equivalent(u));
|
||||
}
|
||||
|
||||
{
|
||||
X b(a);
|
||||
BOOST_CHECK(b.begin() == const_cast<X const&>(b).cbegin());
|
||||
BOOST_CHECK(b.end() == const_cast<X const&>(b).cend());
|
||||
BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
|
||||
BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
|
||||
}
|
||||
|
||||
{
|
||||
X b(a);
|
||||
X c;
|
||||
BOOST_CHECK(equivalent(b));
|
||||
BOOST_CHECK(c.empty());
|
||||
BOOST_TEST(equivalent(b));
|
||||
BOOST_TEST(c.empty());
|
||||
b.swap(c);
|
||||
BOOST_CHECK(b.empty());
|
||||
BOOST_CHECK(equivalent(c));
|
||||
BOOST_TEST(b.empty());
|
||||
BOOST_TEST(equivalent(c));
|
||||
b.swap(c);
|
||||
BOOST_CHECK(c.empty());
|
||||
BOOST_CHECK(equivalent(b));
|
||||
BOOST_TEST(c.empty());
|
||||
BOOST_TEST(equivalent(b));
|
||||
}
|
||||
|
||||
{
|
||||
X u;
|
||||
X& r = u;
|
||||
BOOST_CHECK(&(r = r) == &r);
|
||||
BOOST_CHECK(r.empty());
|
||||
BOOST_CHECK(&(r = a) == &r);
|
||||
BOOST_CHECK(equivalent(r));
|
||||
BOOST_CHECK(&(r = r) == &r);
|
||||
BOOST_CHECK(equivalent(r));
|
||||
BOOST_TEST(&(r = r) == &r);
|
||||
|
||||
BOOST_TEST(r.empty());
|
||||
BOOST_TEST(&(r = a) == &r);
|
||||
BOOST_TEST(equivalent(r));
|
||||
BOOST_TEST(&(r = r) == &r);
|
||||
BOOST_TEST(equivalent(r));
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_CHECK(a.size() ==
|
||||
BOOST_TEST(a.size() ==
|
||||
(BOOST_DEDUCED_TYPENAME X::size_type) std::distance(a.begin(), a.end()));
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_CHECK(a.empty() == (a.size() == 0));
|
||||
BOOST_TEST(a.empty() == (a.size() == 0));
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_CHECK(a.empty() == (a.begin() == a.end()));
|
||||
BOOST_TEST(a.empty() == (a.begin() == a.end()));
|
||||
X u;
|
||||
BOOST_CHECK(u.begin() == u.end());
|
||||
BOOST_TEST(u.begin() == u.end());
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +92,7 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
boost::unordered_set<int> set;
|
||||
simple_test(set);
|
||||
|
||||
|
||||
set.insert(1); set.insert(2); set.insert(1456);
|
||||
simple_test(set);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright 2006-2008 Daniel James.
|
||||
// Copyright 2006-2009 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)
|
||||
|
||||
@ -68,12 +68,22 @@ namespace unnecessary_copy_tests
|
||||
#define COPY_COUNT(n) \
|
||||
if(count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr<<"Number of copies: "<<count_copies::copies<<std::endl; \
|
||||
std::cerr<<"Number of copies: "<<count_copies::copies<<" expecting: "<<n<<std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT(n) \
|
||||
if(count_copies::moves != n) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr<<"Number of moves: "<<count_copies::moves<<std::endl; \
|
||||
std::cerr<<"Number of moves: "<<count_copies::moves<<" expecting: "<<n<<std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_RANGE(a, b) \
|
||||
if(count_copies::copies < a || count_copies::copies > b) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr<<"Number of copies: "<<count_copies::copies<<" expecting: ["<<a<<", "<<b<<"]"<<std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT_RANGE(a, b) \
|
||||
if(count_copies::moves < a || count_copies::moves > b) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr<<"Number of moves: "<<count_copies::copies<<" expecting: ["<<a<<", "<<b<<"]"<<std::endl; \
|
||||
}
|
||||
|
||||
namespace unnecessary_copy_tests
|
||||
@ -84,12 +94,11 @@ namespace unnecessary_copy_tests
|
||||
template <class T>
|
||||
void unnecessary_copy_insert_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
reset();
|
||||
x.insert(a);
|
||||
COPY_COUNT(2);
|
||||
COPY_COUNT(1);
|
||||
}
|
||||
|
||||
boost::unordered_set<count_copies>* set;
|
||||
@ -100,7 +109,6 @@ namespace unnecessary_copy_tests
|
||||
UNORDERED_TEST(unnecessary_copy_insert_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_test(T*)
|
||||
{
|
||||
@ -118,9 +126,19 @@ namespace unnecessary_copy_tests
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
COPY_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_move_test(T*)
|
||||
{
|
||||
@ -132,13 +150,11 @@ namespace unnecessary_copy_tests
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#endif
|
||||
|
||||
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
||||
{
|
||||
reset();
|
||||
@ -173,10 +189,12 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(std::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#endif
|
||||
|
||||
// Just in case a did get moved...
|
||||
count_copies b;
|
||||
@ -193,8 +211,12 @@ namespace unnecessary_copy_tests
|
||||
|
||||
// The container will have to create b copy in order to compare with
|
||||
// the existing element.
|
||||
//
|
||||
// Note to self: If copy_count == 0 it's an error not an optimization.
|
||||
// TODO: Devise a better test.
|
||||
|
||||
reset();
|
||||
|
||||
x.emplace(b, b);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
}
|
||||
@ -231,24 +253,22 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
x.emplace(a_ref);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
// TODO: This doesn't work on older versions of gcc.
|
||||
//count_copies part;
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
//reset();
|
||||
//std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
//x.emplace(a_ref);
|
||||
//COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
// No move should take place.
|
||||
// (since a is already in the container)
|
||||
reset();
|
||||
x.emplace(std::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#endif
|
||||
|
||||
// Just in case a did get moved
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
|
||||
// This test requires a C++0x std::pair. Which gcc hasn't got yet.
|
||||
//reset();
|
||||
//x.emplace(b.first.tag_);
|
||||
//COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
@ -268,10 +288,9 @@ namespace unnecessary_copy_tests
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(b.first.tag_, b.second.tag_);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
Reference in New Issue
Block a user