mirror of
https://github.com/boostorg/unordered.git
synced 2026-08-06 13:44:12 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4076e1297 |
@@ -1 +0,0 @@
|
||||
/doc/html/
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
# Copyright (C) 2016 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)
|
||||
|
||||
# Use Trusty to get a reasonably recent version of Boost.
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
language: c++
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libboost-tools-dev
|
||||
- libxml2-utils
|
||||
- g++-multilib
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-std11
|
||||
#- compiler: gcc
|
||||
# env: BJAM_TOOLSET=gcc-m32
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-std11m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-std11
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang-std11m32
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- touch Jamroot.jam
|
||||
- cd $HOME
|
||||
- |
|
||||
echo "using gcc : : g++-4.8 -Werror --std=c++03 -fsanitize=address ;" > ~/user-config.jam
|
||||
echo "using gcc : std11 : g++-4.8 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : m32 : g++-4.8 -m32 -Werror -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : std11m32 : g++-4.8 -m32 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : : clang++ -Werror --std=c++03 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : std11 : clang++ -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
# sanitized=address not available for 32-bit clang on travis.
|
||||
echo "using clang : m32 : clang++ -m32 -Werror --std=c++03 ;" >> ~/user-config.jam
|
||||
echo "using clang : std11m32 : clang++ -m32 -Werror --std=c++11 ;" >> ~/user-config.jam
|
||||
- cat ~/user-config.jam
|
||||
- wget -O boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/snapshots/master/boost_1_62_0.tar.bz2/download
|
||||
- tar -xjf boost.tar.bz2
|
||||
- mv boost_1_62_0 boost
|
||||
- rm -r boost/boost/unordered
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- bjam ${BJAM_TOOLSET} include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
|
||||
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
|
||||
@@ -57,12 +57,3 @@ boostbook standalone : unordered :
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: unordered
|
||||
:
|
||||
:
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease ;
|
||||
explicit boostrelease ;
|
||||
|
||||
+1
-105
@@ -3,9 +3,6 @@
|
||||
/ 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) ]
|
||||
|
||||
[template ticket[number]'''<ulink
|
||||
url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
|
||||
|
||||
[section:changes Change Log]
|
||||
|
||||
[h2 Review Version]
|
||||
@@ -47,7 +44,7 @@ First official release.
|
||||
|
||||
[h2 Boost 1.38.0]
|
||||
|
||||
* Use [@boost:/libs/core/swap.html `boost::swap`].
|
||||
* 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
|
||||
@@ -202,105 +199,4 @@ C++11 support has resulted in some breaking changes:
|
||||
for 64 bit values.
|
||||
* Some internal changes.
|
||||
|
||||
[h2 Boost 1.51.0]
|
||||
|
||||
* Fix construction/destruction issue when using a C++11 compiler with a
|
||||
C++03 allocator ([ticket 7100]).
|
||||
* Remove a `try..catch` to support compiling without exceptions.
|
||||
* Adjust SFINAE use to try to supprt g++ 3.4 ([ticket 7175]).
|
||||
* Updated to use the new config macros.
|
||||
|
||||
[h2 Boost 1.52.0]
|
||||
|
||||
* Faster assign, which assigns to existing nodes where possible, rather than
|
||||
creating entirely new nodes and copy constructing.
|
||||
* Fixed bug in `erase_range` ([ticket 7471]).
|
||||
* Reverted some of the internal changes to how nodes are created, especially
|
||||
for C++11 compilers. 'construct' and 'destroy' should work a little better
|
||||
for C++11 allocators.
|
||||
* Simplified the implementation a bit. Hopefully more robust.
|
||||
|
||||
[h2 Boost 1.53.0]
|
||||
|
||||
* Remove support for the old pre-standard variadic pair constructors, and
|
||||
equality implementation. Both have been deprecated since Boost 1.48.
|
||||
* Remove use of deprecated config macros.
|
||||
* More internal implementation changes, including a much simpler
|
||||
implementation of `erase`.
|
||||
|
||||
[h2 Boost 1.54.0]
|
||||
|
||||
* Mark methods specified in standard as `noexpect`. More to come in the next
|
||||
release.
|
||||
* If the hash function and equality predicate are known to both have nothrow
|
||||
move assignment or construction then use them.
|
||||
|
||||
[h2 Boost 1.55.0]
|
||||
|
||||
* Avoid some warnings ([ticket 8851], [ticket 8874]).
|
||||
* Avoid exposing some detail functions via. ADL on the iterators.
|
||||
* Follow the standard by only using the allocators' construct and destroy
|
||||
methods to construct and destroy stored elements. Don't use them for internal
|
||||
data like pointers.
|
||||
|
||||
[h2 Boost 1.56.0]
|
||||
|
||||
* Fix some shadowed variable warnings ([ticket 9377]).
|
||||
* Fix allocator use in documentation ([ticket 9719]).
|
||||
* Always use prime number of buckets for integers. Fixes performance
|
||||
regression when inserting consecutive integers, although makes other
|
||||
uses slower ([ticket 9282]).
|
||||
* Only construct elements using allocators, as specified in C++11 standard.
|
||||
|
||||
[h2 Boost 1.57.0]
|
||||
|
||||
* Fix the `pointer` typedef in iterators ([ticket 10672]).
|
||||
* Fix Coverity warning
|
||||
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
|
||||
|
||||
[h2 Boost 1.58.0]
|
||||
|
||||
* Remove unnecessary template parameter from const iterators.
|
||||
* Rename private `iterator` typedef in some iterator classes, as it
|
||||
confuses some traits classes.
|
||||
* Fix move assignment with stateful, propagate_on_container_move_assign
|
||||
allocators ([ticket 10777]).
|
||||
* Fix rare exception safety issue in move assignment.
|
||||
* Fix potential overflow when calculating number of buckets to allocate
|
||||
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
|
||||
|
||||
[h2 Boost 1.62.0]
|
||||
|
||||
* Remove use of deprecated `boost::iterator`.
|
||||
* Remove `BOOST_NO_STD_DISTANCE` workaround.
|
||||
* Remove `BOOST_UNORDERED_DEPRECATED_EQUALITY` warning.
|
||||
* Simpler implementation of assignment, fixes an exception safety issue
|
||||
for `unordered_multiset` and `unordered_multimap`. Might be a little slower.
|
||||
* Stop using return value SFINAE which some older compilers have issues
|
||||
with.
|
||||
|
||||
[h2 Boost 1.63.0]
|
||||
|
||||
* Check hint iterator in `insert`/`emplace_hint`.
|
||||
* Fix some warnings, mostly in the tests.
|
||||
* Manually write out `emplace_args` for small numbers of arguments -
|
||||
should make template error messages a little more bearable.
|
||||
* Remove superfluous use of `boost::forward` in emplace arguments,
|
||||
which fixes emplacing string literals in old versions of Visual C++.
|
||||
* Fix an exception safety issue in assignment. If bucket allocation
|
||||
throws an exception, it can overwrite the hash and equality functions while
|
||||
leaving the existing elements in place. This would mean that the function
|
||||
objects wouldn't match the container elements, so elements might be in the
|
||||
wrong bucket and equivalent elements would be incorrectly handled.
|
||||
* Various reference documentation improvements.
|
||||
* Better allocator support ([ticket 12459]).
|
||||
* Make the no argument constructors implicit.
|
||||
* Implement missing allocator aware constructors.
|
||||
* Fix assigning the hash/key equality functions for empty containers.
|
||||
* Remove unary/binary_function from the examples in the documentation.
|
||||
They are removed in C++17.
|
||||
* Support 10 constructor arguments in emplace. It was meant to support up to 10
|
||||
arguments, but an off by one error in the preprocessor code meant it only
|
||||
supports up to 10.
|
||||
|
||||
[endsect]
|
||||
|
||||
+4
-5
@@ -8,12 +8,11 @@
|
||||
|
||||
Support for move semantics is implemented using Boost.Move. If rvalue
|
||||
references are available it will use them, but if not it uses a close,
|
||||
but imperfect emulation. On such compilers:
|
||||
but imperfect emulation. On such compilers you'll need to use Boost.Move
|
||||
to take advantage of using movable container elements, also note that:
|
||||
|
||||
* Non-copyable objects can be stored in the containers.
|
||||
They can be constructed in place using `emplace`, or if they support
|
||||
Boost.Move, moved into place.
|
||||
* The containers themselves are not movable.
|
||||
* Non-copyable objects can be stored in the containers, but without support
|
||||
for rvalue references the container will not be movable.
|
||||
* Argument forwarding is not perfect.
|
||||
|
||||
[endsect]
|
||||
|
||||
+2
-2
@@ -54,14 +54,14 @@ order to work with non-C++11 compilers and libraries.
|
||||
class Key, class Mapped,
|
||||
class Hash = ``[classref boost::hash]``<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
|
||||
class Alloc = std::allocator<Key> >
|
||||
class ``[classref boost::unordered_map unordered_map]``;
|
||||
|
||||
template<
|
||||
class Key, class Mapped,
|
||||
class Hash = ``[classref boost::hash]``<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
|
||||
class Alloc = std::allocator<Key> >
|
||||
class ``[classref boost::unordered_multimap unordered_multimap]``;
|
||||
}
|
||||
|
||||
|
||||
+8
-13
@@ -3,7 +3,7 @@
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[def __wang__
|
||||
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
Thomas Wang's article on integer hash functions]]
|
||||
|
||||
[section:rationale Implementation Rationale]
|
||||
@@ -85,8 +85,7 @@ of 2.
|
||||
|
||||
Using a prime number of buckets, and choosing a bucket by using the modulus
|
||||
of the hash function's result will usually give a good result. The downside
|
||||
is that the required modulus operation is fairly expensive. This is what the
|
||||
containers do in most cases.
|
||||
is that the required modulus operation is fairly expensive.
|
||||
|
||||
Using a power of 2 allows for much quicker selection of the bucket
|
||||
to use, but at the expense of loosing the upper bits of the hash value.
|
||||
@@ -96,16 +95,12 @@ functions this can't be relied on.
|
||||
|
||||
To avoid this a transformation could be applied to the hash function, for an
|
||||
example see __wang__. Unfortunately, a transformation like Wang's requires
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough
|
||||
to use as a default. It can applicable in certain cases so the containers
|
||||
have a policy based implementation that can use this alternative technique.
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough.
|
||||
This leaves more expensive methods, such as Knuth's Multiplicative Method
|
||||
(mentioned in Wang's article). These don't tend to work as well as taking the
|
||||
modulus of a prime, and the extra computation required might negate
|
||||
efficiency advantage of power of 2 hash tables.
|
||||
|
||||
Currently this is only done on 64 bit architecures, where prime number
|
||||
modulus can be expensive. Although this varies depending on the architecture,
|
||||
so I probably should revisit it.
|
||||
|
||||
I'm also thinking of introducing a mechanism whereby a hash function can
|
||||
indicate that it's safe to be used directly with power of 2 buckets, in
|
||||
which case a faster plain power of 2 implementation can be used.
|
||||
So, this implementation uses a prime number for the hash table size.
|
||||
|
||||
[endsect]
|
||||
|
||||
+20
-331
@@ -67,20 +67,14 @@ EOL;
|
||||
<?php if ($map): ?>
|
||||
<row>
|
||||
<entry><emphasis>Key</emphasis></entry>
|
||||
<entry><code>Key</code> must be <code>Erasable</code> from the container
|
||||
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
|
||||
</entry></row>
|
||||
<entry>Key must be Assignable and CopyConstructible.</entry></row>
|
||||
<row>
|
||||
<entry><emphasis>Mapped</emphasis></entry>
|
||||
<entry><code>Mapped</code> must be <code>Erasable</code> from the container
|
||||
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
|
||||
</entry></row>
|
||||
<entry>Mapped must be CopyConstructible</entry></row>
|
||||
<?php else: ?>
|
||||
<row>
|
||||
<entry><emphasis>Value</emphasis></entry>
|
||||
<entry><code>Value</code> must be <code>Erasable</code> from the container
|
||||
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
|
||||
</entry></row>
|
||||
<entry>Value must be Assignable and CopyConstructible</entry></row>
|
||||
<?php endif ?>
|
||||
<row>
|
||||
<entry><emphasis>Hash</emphasis></entry>
|
||||
@@ -189,22 +183,10 @@ EOL;
|
||||
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<constructor>
|
||||
<postconditions>
|
||||
<code><methodname>size</methodname>() == 0</code>
|
||||
</postconditions>
|
||||
<description>
|
||||
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
|
||||
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
<default><emphasis>implementation-defined</emphasis></default>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
@@ -224,11 +206,6 @@ EOL;
|
||||
<description>
|
||||
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
|
||||
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<template>
|
||||
@@ -258,18 +235,8 @@ EOL;
|
||||
<default>allocator_type()</default>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
<code>eq</code> as the key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0
|
||||
and inserts the elements from [f, l) into it.
|
||||
</para>
|
||||
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
|
||||
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter>
|
||||
@@ -327,168 +294,6 @@ EOL;
|
||||
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
|
||||
</description>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="x">
|
||||
<paramtype><?php echo $name; ?> &&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is implemented using Boost.Move.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move insertable.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="il">
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
<default><emphasis>implementation-defined</emphasis></default>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
<default>hasher()</default>
|
||||
</parameter>
|
||||
<parameter name="eq">
|
||||
<paramtype>key_equal const&</paramtype>
|
||||
<default>key_equal()</default>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
<default>allocator_type()</default>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
<code>eq</code> as the key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0
|
||||
and inserts the elements from <code>il</code> into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
|
||||
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<postconditions>
|
||||
<code><methodname>size</methodname>() == 0</code>
|
||||
</postconditions>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
the default hash function and key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<postconditions>
|
||||
<code><methodname>size</methodname>() == 0</code>
|
||||
</postconditions>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
the default key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<template>
|
||||
<template-type-parameter name="InputIterator">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="f">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="l">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>a</code> as the allocator, with the
|
||||
default hash function and key equality predicate
|
||||
and a maximum load factor of 1.0
|
||||
and inserts the elements from [f, l) into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<template>
|
||||
<template-type-parameter name="InputIterator">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="f">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="l">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
<code>a</code> as the allocator, with the
|
||||
default key equality predicate
|
||||
and a maximum load factor of 1.0
|
||||
and inserts the elements from [f, l) into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
@@ -537,21 +342,6 @@ EOL;
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<type><?php echo $name; ?>&</type>
|
||||
<description>
|
||||
<para>Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is <code>CopyInsertable</code> into the container and
|
||||
<code>CopyAssignable</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
</method>
|
||||
@@ -618,11 +408,6 @@ EOL;
|
||||
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
|
||||
?></para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
|
||||
<code>X</code> from <code>args</code>.
|
||||
</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
@@ -643,6 +428,10 @@ EOL;
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@@ -664,11 +453,6 @@ EOL;
|
||||
?></para>
|
||||
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
|
||||
<code>X</code> from <code>args</code>.
|
||||
</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
@@ -689,6 +473,10 @@ EOL;
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@@ -702,39 +490,6 @@ EOL;
|
||||
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
|
||||
?></para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
<?php else: ?>
|
||||
<para>The bool component of the return type is true if an insert took place.</para>
|
||||
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent <?php echo $key_name; ?>.</para>
|
||||
<?php endif; ?>
|
||||
</returns>
|
||||
<throws>
|
||||
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
|
||||
</throws>
|
||||
<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>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
<parameter name="obj">
|
||||
<paramtype>value_type&&</paramtype>
|
||||
</parameter>
|
||||
<type><?php echo $equivalent_keys ? 'iterator' : 'std::pair<iterator, bool>' ?></type>
|
||||
<description>
|
||||
<para>Inserts <code>obj</code> in the container<?php
|
||||
echo $equivalent_keys ? '.' :
|
||||
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
|
||||
?></para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
@@ -767,44 +522,6 @@ EOL;
|
||||
<?php endif; ?>
|
||||
<para>hint is a suggestion to where the element should be inserted.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
<?php else: ?>
|
||||
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent <?php echo $key_name; ?>.</para>
|
||||
<?php endif; ?>
|
||||
</returns>
|
||||
<throws>
|
||||
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<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 <?php echo $key_name; ?>. </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>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
<parameter name="hint">
|
||||
<paramtype>const_iterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="obj">
|
||||
<paramtype>value_type&&</paramtype>
|
||||
</parameter>
|
||||
<type>iterator</type>
|
||||
<description>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>Inserts <code>obj</code> in the container.</para>
|
||||
<?php else: ?>
|
||||
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.</para>
|
||||
<?php endif; ?>
|
||||
<para>hint is a suggestion to where the element should be inserted.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
|
||||
</requires>
|
||||
<returns>
|
||||
<?php if ($equivalent_keys): ?>
|
||||
<para>An iterator pointing to the inserted element.</para>
|
||||
@@ -834,40 +551,8 @@ EOL;
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Inserts a range of elements into the container.
|
||||
<?php if (!$equivalent_keys): ?>
|
||||
Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
|
||||
<?php endif; ?>
|
||||
</para>
|
||||
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
|
||||
<code>X</code> from <code>*first</code>.</para>
|
||||
</requires>
|
||||
<throws>
|
||||
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
|
||||
</throws>
|
||||
<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>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
<parameter name="il">
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Inserts a range of elements into the container.
|
||||
<?php if (!$equivalent_keys): ?>
|
||||
Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
|
||||
<?php endif; ?>
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
|
||||
<code>X</code> from <code>*first</code>.</para>
|
||||
</requires>
|
||||
<throws>
|
||||
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
|
||||
</throws>
|
||||
@@ -1328,7 +1013,9 @@ EOL;
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@@ -1369,7 +1056,9 @@ EOL;
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
|
||||
+73
-1223
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@
|
||||
|
||||
//[case_insensitive_functions
|
||||
struct iequal_to
|
||||
: std::binary_function<std::string, std::string, bool>
|
||||
{
|
||||
bool operator()(std::string const& x,
|
||||
std::string const& y) const
|
||||
@@ -19,6 +20,7 @@
|
||||
};
|
||||
|
||||
struct ihash
|
||||
: std::unary_function<std::string, std::size_t>
|
||||
{
|
||||
std::size_t operator()(std::string const& x) const
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
}
|
||||
|
||||
struct point_hash
|
||||
: std::unary_function<point, std::size_t>
|
||||
{
|
||||
std::size_t operator()(point const& p) const
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
namespace hash_examples
|
||||
{
|
||||
struct iequal_to
|
||||
: std::binary_function<std::string, std::string, bool>
|
||||
{
|
||||
iequal_to() {}
|
||||
explicit iequal_to(std::locale const& l) : locale_(l) {}
|
||||
@@ -33,6 +34,7 @@ namespace hash_examples
|
||||
};
|
||||
|
||||
struct ihash
|
||||
: std::unary_function<std::string, std::size_t>
|
||||
{
|
||||
ihash() {}
|
||||
explicit ihash(std::locale const& l) : locale_(l) {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,6 @@
|
||||
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -51,7 +46,7 @@ namespace detail {
|
||||
typedef ValueType value_type;
|
||||
typedef ValueType key_type;
|
||||
|
||||
static key_type const& extract(value_type const& v)
|
||||
static key_type const& extract(key_type const& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
@@ -61,25 +56,30 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
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();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const&, value_type const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Key, class ValueType>
|
||||
@@ -93,6 +93,11 @@ namespace detail {
|
||||
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)
|
||||
{
|
||||
@@ -106,6 +111,21 @@ namespace detail {
|
||||
return v.first;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
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&)
|
||||
{
|
||||
@@ -123,27 +143,19 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class Arg3, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
|
||||
Args const&...)
|
||||
template <class Arg, class Arg1>
|
||||
static no_key extract(Arg const&, Arg1 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
template <typename T2> \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_ tuple<> const&, T2 const&) \
|
||||
namespace_::tuple<> const&, BOOST_FWD_REF(T2)) \
|
||||
{ \
|
||||
return no_key(); \
|
||||
} \
|
||||
@@ -151,17 +163,17 @@ namespace detail {
|
||||
template <typename T, typename T2> \
|
||||
static typename is_key<key_type, T>::type \
|
||||
extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_ tuple<T> const& k, T2 const&) \
|
||||
namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
|
||||
{ \
|
||||
return typename is_key<key_type, T>::type( \
|
||||
namespace_ get<0>(k)); \
|
||||
namespace_::get<0>(k)); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_ tuple<> const&) \
|
||||
namespace_::tuple<> const&) \
|
||||
{ \
|
||||
return no_key(); \
|
||||
} \
|
||||
@@ -169,19 +181,25 @@ namespace detail {
|
||||
template <typename T> \
|
||||
static typename is_key<key_type, T>::type \
|
||||
extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_ tuple<T> const& k) \
|
||||
namespace_::tuple<T> const& k) \
|
||||
{ \
|
||||
return typename is_key<key_type, T>::type( \
|
||||
namespace_ get<0>(k)); \
|
||||
namespace_::get<0>(k)); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
|
||||
#endif
|
||||
|
||||
|
||||
static bool compare_mapped(value_type const& x, value_type const& y)
|
||||
{
|
||||
return x.second == y.second;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
|
||||
@@ -1,56 +1,22 @@
|
||||
|
||||
// Copyright (C) 2008-2016 Daniel James.
|
||||
// Copyright (C) 2008-2011 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_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
|
||||
// Already defined.
|
||||
#elif defined(BOOST_LIBSTDCXX11)
|
||||
// https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70
|
||||
# if BOOST_LIBSTDCXX_VERSION > 40600
|
||||
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
# endif
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
|
||||
# if LIBCPP_VERSION >= 3000
|
||||
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
# endif
|
||||
#elif defined(BOOST_MSVC)
|
||||
// Apparently C++11 standard supported in Visual Studio 2012
|
||||
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
|
||||
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
|
||||
# if BOOST_MSVC >= 1700
|
||||
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
using std::piecewise_construct_t;
|
||||
using std::piecewise_construct;
|
||||
#else
|
||||
struct piecewise_construct_t {};
|
||||
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
// Copyright (C) 2005-2016 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>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct map
|
||||
{
|
||||
typedef boost::unordered::detail::map<A, K, M, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator>
|
||||
traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> cl_iterator;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_grouped_node<allocator,
|
||||
value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> cl_iterator;
|
||||
};
|
||||
|
||||
}}}
|
||||
@@ -1,75 +0,0 @@
|
||||
|
||||
// Copyright (C) 2005-2016 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>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct set
|
||||
{
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> cl_iterator;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct multiset
|
||||
{
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_grouped_node<allocator,
|
||||
value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, policy> cl_iterator;
|
||||
};
|
||||
}}}
|
||||
@@ -7,17 +7,11 @@
|
||||
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/buckets.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
@@ -43,10 +37,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
sizeof(value_type),
|
||||
boost::alignment_of<value_type>::value>::type data_;
|
||||
|
||||
value_base() :
|
||||
data_()
|
||||
{}
|
||||
|
||||
void* address() {
|
||||
return this;
|
||||
}
|
||||
@@ -66,6 +56,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Types>
|
||||
struct table :
|
||||
boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node,
|
||||
typename Types::policy>,
|
||||
boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal>
|
||||
@@ -74,8 +69,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
table(table const&);
|
||||
table& operator=(table const&);
|
||||
public:
|
||||
typedef typename Types::node node;
|
||||
typedef typename Types::bucket bucket;
|
||||
typedef typename Types::hasher hasher;
|
||||
typedef typename Types::key_equal key_equal;
|
||||
typedef typename Types::key_type key_type;
|
||||
@@ -84,138 +77,28 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename Types::table table_impl;
|
||||
typedef typename Types::link_pointer link_pointer;
|
||||
typedef typename Types::policy policy;
|
||||
typedef typename Types::iterator iterator;
|
||||
typedef typename Types::c_iterator c_iterator;
|
||||
typedef typename Types::l_iterator l_iterator;
|
||||
typedef typename Types::cl_iterator cl_iterator;
|
||||
|
||||
typedef boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal> functions;
|
||||
typedef typename functions::set_hash_functions set_hash_functions;
|
||||
|
||||
typedef typename Types::allocator allocator;
|
||||
typedef typename boost::unordered::detail::
|
||||
rebind_wrap<allocator, node>::type node_allocator;
|
||||
typedef typename boost::unordered::detail::
|
||||
rebind_wrap<allocator, bucket>::type bucket_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<node_allocator>
|
||||
node_allocator_traits;
|
||||
typedef boost::unordered::detail::allocator_traits<bucket_allocator>
|
||||
bucket_allocator_traits;
|
||||
typedef typename node_allocator_traits::pointer
|
||||
node_pointer;
|
||||
typedef typename node_allocator_traits::const_pointer
|
||||
const_node_pointer;
|
||||
typedef typename bucket_allocator_traits::pointer
|
||||
bucket_pointer;
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
typedef boost::unordered::detail::node_tmp<node_allocator>
|
||||
node_tmp;
|
||||
typedef boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node,
|
||||
typename Types::policy> buckets;
|
||||
|
||||
typedef typename buckets::node_allocator node_allocator;
|
||||
typedef typename buckets::node_allocator_traits node_allocator_traits;
|
||||
typedef typename buckets::node_pointer node_pointer;
|
||||
typedef typename buckets::const_node_pointer const_node_pointer;
|
||||
|
||||
typedef typename table::iterator iterator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Members
|
||||
|
||||
boost::unordered::detail::compressed<bucket_allocator, node_allocator>
|
||||
allocators_;
|
||||
std::size_t bucket_count_;
|
||||
std::size_t size_;
|
||||
float mlf_;
|
||||
std::size_t max_load_;
|
||||
bucket_pointer buckets_;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Node functions
|
||||
|
||||
static inline node_pointer next_node(link_pointer n) {
|
||||
return static_cast<node_pointer>(n->next_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
{
|
||||
// -1 to account for the start bucket.
|
||||
return policy::prev_bucket_count(
|
||||
bucket_allocator_traits::max_size(bucket_alloc()) - 1);
|
||||
}
|
||||
|
||||
bucket_pointer get_bucket(std::size_t bucket_index) const
|
||||
{
|
||||
BOOST_ASSERT(buckets_);
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
|
||||
}
|
||||
|
||||
link_pointer get_previous_start() const
|
||||
{
|
||||
return get_bucket(bucket_count_)->first_from_start();
|
||||
}
|
||||
|
||||
link_pointer get_previous_start(std::size_t bucket_index) const
|
||||
{
|
||||
return get_bucket(bucket_index)->next_;
|
||||
}
|
||||
|
||||
node_pointer begin() const
|
||||
{
|
||||
return size_ ? next_node(get_previous_start()) : node_pointer();
|
||||
}
|
||||
|
||||
node_pointer begin(std::size_t bucket_index) const
|
||||
{
|
||||
if (!size_) return node_pointer();
|
||||
link_pointer prev = get_previous_start(bucket_index);
|
||||
return prev ? next_node(prev) : node_pointer();
|
||||
}
|
||||
|
||||
std::size_t hash_to_bucket(std::size_t hash_value) const
|
||||
{
|
||||
return policy::to_bucket(bucket_count_, hash_value);
|
||||
}
|
||||
|
||||
float load_factor() const
|
||||
{
|
||||
BOOST_ASSERT(bucket_count_ != 0);
|
||||
return static_cast<float>(size_)
|
||||
/ static_cast<float>(bucket_count_);
|
||||
}
|
||||
|
||||
std::size_t bucket_size(std::size_t index) const
|
||||
{
|
||||
node_pointer n = begin(index);
|
||||
if (!n) return 0;
|
||||
|
||||
std::size_t count = 0;
|
||||
while(n && hash_to_bucket(n->hash_) == index)
|
||||
{
|
||||
++count;
|
||||
n = next_node(n);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
std::size_t max_load_; // Only use if this->buckets_.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Load methods
|
||||
@@ -226,34 +109,34 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// size < mlf_ * count
|
||||
return boost::unordered::detail::double_to_size(ceil(
|
||||
static_cast<double>(mlf_) *
|
||||
static_cast<double>(max_bucket_count())
|
||||
static_cast<double>(this->mlf_) *
|
||||
static_cast<double>(this->max_bucket_count())
|
||||
)) - 1;
|
||||
}
|
||||
|
||||
void recalculate_max_load()
|
||||
std::size_t calculate_max_load()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// From 6.3.1/13:
|
||||
// Only resize when size >= mlf_ * count
|
||||
max_load_ = buckets_ ? boost::unordered::detail::double_to_size(ceil(
|
||||
static_cast<double>(mlf_) *
|
||||
static_cast<double>(bucket_count_)
|
||||
)) : 0;
|
||||
return boost::unordered::detail::double_to_size(ceil(
|
||||
static_cast<double>(this->mlf_) *
|
||||
static_cast<double>(this->bucket_count_)
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
void max_load_factor(float z)
|
||||
{
|
||||
BOOST_ASSERT(z > 0);
|
||||
mlf_ = (std::max)(z, minimum_max_load_factor);
|
||||
recalculate_max_load();
|
||||
if (this->buckets_)
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
|
||||
std::size_t min_buckets_for_size(std::size_t size) const
|
||||
{
|
||||
BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
|
||||
BOOST_ASSERT(this->mlf_ >= minimum_max_load_factor);
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -267,7 +150,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return policy::new_bucket_count(
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(size) /
|
||||
static_cast<double>(mlf_)) + 1));
|
||||
static_cast<double>(mlf_))) + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -277,416 +160,176 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hasher const& hf,
|
||||
key_equal const& eq,
|
||||
node_allocator const& a) :
|
||||
buckets(a, policy::new_bucket_count(num_buckets)),
|
||||
functions(hf, eq),
|
||||
allocators_(a,a),
|
||||
bucket_count_(policy::new_bucket_count(num_buckets)),
|
||||
size_(0),
|
||||
mlf_(1.0f),
|
||||
max_load_(0),
|
||||
buckets_()
|
||||
max_load_(0)
|
||||
{}
|
||||
|
||||
table(table const& x, node_allocator const& a) :
|
||||
buckets(a, x.min_buckets_for_size(x.size_)),
|
||||
functions(x),
|
||||
allocators_(a,a),
|
||||
bucket_count_(x.min_buckets_for_size(x.size_)),
|
||||
size_(0),
|
||||
mlf_(x.mlf_),
|
||||
max_load_(0),
|
||||
buckets_()
|
||||
{}
|
||||
|
||||
table(table& x, boost::unordered::detail::move_tag m) :
|
||||
functions(x, m),
|
||||
allocators_(x.allocators_, m),
|
||||
bucket_count_(x.bucket_count_),
|
||||
size_(x.size_),
|
||||
mlf_(x.mlf_),
|
||||
max_load_(x.max_load_),
|
||||
buckets_(x.buckets_)
|
||||
max_load_(0)
|
||||
{
|
||||
x.buckets_ = bucket_pointer();
|
||||
x.size_ = 0;
|
||||
x.max_load_ = 0;
|
||||
if(x.size_) {
|
||||
table_impl::copy_buckets_to(x, *this);
|
||||
this->max_load_ = calculate_max_load();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Why calculate_max_load?
|
||||
table(table& x, boost::unordered::detail::move_tag m) :
|
||||
buckets(x, m),
|
||||
functions(x),
|
||||
mlf_(x.mlf_),
|
||||
max_load_(calculate_max_load())
|
||||
{}
|
||||
|
||||
// TODO: Why not calculate_max_load?
|
||||
// TODO: Why do I use x's bucket count?
|
||||
table(table& x, node_allocator const& a,
|
||||
boost::unordered::detail::move_tag m) :
|
||||
functions(x, m),
|
||||
allocators_(a, a),
|
||||
bucket_count_(x.bucket_count_),
|
||||
size_(0),
|
||||
buckets(a, x.bucket_count_),
|
||||
functions(x),
|
||||
mlf_(x.mlf_),
|
||||
max_load_(x.max_load_),
|
||||
buckets_()
|
||||
{}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Initialisation.
|
||||
|
||||
void init(table const& x)
|
||||
max_load_(x.max_load_)
|
||||
{
|
||||
if (x.size_) {
|
||||
static_cast<table_impl*>(this)->copy_buckets(x);
|
||||
}
|
||||
}
|
||||
|
||||
void move_init(table& x)
|
||||
{
|
||||
if(node_alloc() == x.node_alloc()) {
|
||||
move_buckets_from(x);
|
||||
if(a == x.node_alloc()) {
|
||||
this->buckets::swap(x, false_type());
|
||||
}
|
||||
else if(x.size_) {
|
||||
// TODO: Could pick new bucket size?
|
||||
static_cast<table_impl*>(this)->move_buckets(x);
|
||||
// Use a temporary table because move_buckets_to leaves the
|
||||
// source container in a complete mess.
|
||||
|
||||
buckets tmp(x, m);
|
||||
table_impl::move_buckets_to(tmp, *this);
|
||||
this->max_load_ = calculate_max_load();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Create buckets
|
||||
// Iterators
|
||||
|
||||
void create_buckets(std::size_t new_count)
|
||||
{
|
||||
std::size_t length = new_count + 1;
|
||||
bucket_pointer new_buckets = bucket_allocator_traits::allocate(
|
||||
bucket_alloc(), length);
|
||||
bucket_pointer constructed = new_buckets;
|
||||
|
||||
BOOST_TRY {
|
||||
bucket_pointer end = new_buckets
|
||||
+ static_cast<std::ptrdiff_t>(length);
|
||||
for(; constructed != end; ++constructed) {
|
||||
new ((void*) boost::addressof(*constructed)) bucket();
|
||||
}
|
||||
|
||||
if (buckets_)
|
||||
{
|
||||
// Copy the nodes to the new buckets, including the dummy
|
||||
// node if there is one.
|
||||
(new_buckets +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
(buckets_ + static_cast<std::ptrdiff_t>(
|
||||
bucket_count_))->next_;
|
||||
destroy_buckets();
|
||||
}
|
||||
else if (bucket::extra_node)
|
||||
{
|
||||
node_constructor a(node_alloc());
|
||||
a.create_node();
|
||||
|
||||
(new_buckets +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
a.release();
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...) {
|
||||
for(bucket_pointer p = new_buckets; p != constructed; ++p) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*p));
|
||||
}
|
||||
|
||||
bucket_allocator_traits::deallocate(bucket_alloc(),
|
||||
new_buckets, length);
|
||||
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
bucket_count_ = new_count;
|
||||
buckets_ = new_buckets;
|
||||
recalculate_max_load();
|
||||
iterator begin() const {
|
||||
return !this->buckets_ ?
|
||||
iterator() : this->get_start();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Swap and Move
|
||||
|
||||
void swap_allocators(table& other, false_type)
|
||||
{
|
||||
boost::unordered::detail::func::ignore_unused_variable_warning(other);
|
||||
|
||||
// According to 23.2.1.8, if propagate_on_container_swap is
|
||||
// false the behaviour is undefined unless the allocators
|
||||
// are equal.
|
||||
BOOST_ASSERT(node_alloc() == other.node_alloc());
|
||||
}
|
||||
|
||||
void swap_allocators(table& other, true_type)
|
||||
{
|
||||
allocators_.swap(other.allocators_);
|
||||
}
|
||||
|
||||
// Only swaps the allocators if propagate_on_container_swap
|
||||
void swap(table& x)
|
||||
{
|
||||
set_hash_functions op1(*this, x);
|
||||
set_hash_functions op2(x, *this);
|
||||
|
||||
// I think swap can throw if Propagate::value,
|
||||
// since the allocators' swap can throw. Not sure though.
|
||||
swap_allocators(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_swap::value>());
|
||||
|
||||
boost::swap(buckets_, x.buckets_);
|
||||
boost::swap(bucket_count_, x.bucket_count_);
|
||||
boost::swap(size_, x.size_);
|
||||
std::swap(mlf_, x.mlf_);
|
||||
std::swap(max_load_, x.max_load_);
|
||||
op1.commit();
|
||||
op2.commit();
|
||||
}
|
||||
|
||||
// Only call with nodes allocated with the currect allocator, or
|
||||
// one that is equal to it. (Can't assert because other's
|
||||
// allocators might have already been moved).
|
||||
void move_buckets_from(table& other)
|
||||
{
|
||||
BOOST_ASSERT(!buckets_);
|
||||
buckets_ = other.buckets_;
|
||||
bucket_count_ = other.bucket_count_;
|
||||
size_ = other.size_;
|
||||
other.buckets_ = bucket_pointer();
|
||||
other.size_ = 0;
|
||||
other.max_load_ = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Delete/destruct
|
||||
|
||||
~table()
|
||||
{
|
||||
delete_buckets();
|
||||
}
|
||||
|
||||
void delete_node(link_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = n->next_;
|
||||
|
||||
boost::unordered::detail::func::call_destroy(node_alloc(),
|
||||
n->value_ptr());
|
||||
boost::unordered::detail::func::destroy(boost::addressof(*n));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
--size_;
|
||||
}
|
||||
|
||||
std::size_t delete_nodes(link_pointer prev, link_pointer end)
|
||||
{
|
||||
BOOST_ASSERT(prev->next_ != end);
|
||||
|
||||
std::size_t count = 0;
|
||||
|
||||
do {
|
||||
delete_node(prev);
|
||||
++count;
|
||||
} while (prev->next_ != end);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void delete_buckets()
|
||||
{
|
||||
if(buckets_) {
|
||||
if (size_) delete_nodes(get_previous_start(), link_pointer());
|
||||
|
||||
if (bucket::extra_node) {
|
||||
node_pointer n = static_cast<node_pointer>(
|
||||
get_bucket(bucket_count_)->next_);
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*n));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
}
|
||||
|
||||
destroy_buckets();
|
||||
buckets_ = bucket_pointer();
|
||||
max_load_ = 0;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(!size_);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (!size_) return;
|
||||
|
||||
delete_nodes(get_previous_start(), link_pointer());
|
||||
clear_buckets();
|
||||
|
||||
BOOST_ASSERT(!size_);
|
||||
}
|
||||
|
||||
void clear_buckets()
|
||||
{
|
||||
bucket_pointer end = get_bucket(bucket_count_);
|
||||
for(bucket_pointer it = buckets_; it != end; ++it)
|
||||
{
|
||||
it->next_ = node_pointer();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_buckets()
|
||||
{
|
||||
bucket_pointer end = get_bucket(bucket_count_ + 1);
|
||||
for(bucket_pointer it = buckets_; it != end; ++it)
|
||||
{
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*it));
|
||||
}
|
||||
|
||||
bucket_allocator_traits::deallocate(bucket_alloc(),
|
||||
buckets_, bucket_count_ + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Fix buckets after delete
|
||||
//
|
||||
|
||||
std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
|
||||
{
|
||||
link_pointer end = prev->next_;
|
||||
std::size_t bucket_index2 = bucket_index;
|
||||
|
||||
if (end)
|
||||
{
|
||||
bucket_index2 = hash_to_bucket(
|
||||
static_cast<node_pointer>(end)->hash_);
|
||||
|
||||
// If begin and end are in the same bucket, then
|
||||
// there's nothing to do.
|
||||
if (bucket_index == bucket_index2) return bucket_index2;
|
||||
|
||||
// Update the bucket containing end.
|
||||
get_bucket(bucket_index2)->next_ = prev;
|
||||
}
|
||||
|
||||
// Check if this bucket is now empty.
|
||||
bucket_pointer this_bucket = get_bucket(bucket_index);
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = link_pointer();
|
||||
|
||||
return bucket_index2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Assignment
|
||||
|
||||
void assign(table const& x)
|
||||
{
|
||||
if (this != boost::addressof(x))
|
||||
{
|
||||
assign(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_copy_assignment::value>());
|
||||
}
|
||||
assign(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_copy_assignment::value>());
|
||||
}
|
||||
|
||||
void assign(table const& x, false_type)
|
||||
{
|
||||
// Strong exception safety.
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
mlf_ = x.mlf_;
|
||||
recalculate_max_load();
|
||||
|
||||
if (!size_ && !x.size_) {
|
||||
new_func_this.commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (x.size_ >= max_load_) {
|
||||
create_buckets(min_buckets_for_size(x.size_));
|
||||
}
|
||||
else {
|
||||
clear_buckets();
|
||||
}
|
||||
|
||||
new_func_this.commit();
|
||||
static_cast<table_impl*>(this)->assign_buckets(x);
|
||||
table tmp(x, this->node_alloc());
|
||||
this->swap(tmp, false_type());
|
||||
}
|
||||
|
||||
void assign(table const& x, true_type)
|
||||
{
|
||||
if (node_alloc() == x.node_alloc()) {
|
||||
allocators_.assign(x.allocators_);
|
||||
assign(x, false_type());
|
||||
}
|
||||
else {
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
|
||||
// Delete everything with current allocators before assigning
|
||||
// the new ones.
|
||||
delete_buckets();
|
||||
allocators_.assign(x.allocators_);
|
||||
|
||||
// Copy over other data, all no throw.
|
||||
new_func_this.commit();
|
||||
mlf_ = x.mlf_;
|
||||
bucket_count_ = min_buckets_for_size(x.size_);
|
||||
max_load_ = 0;
|
||||
|
||||
// Finally copy the elements.
|
||||
if (x.size_) {
|
||||
static_cast<table_impl*>(this)->copy_buckets(x);
|
||||
}
|
||||
}
|
||||
table tmp(x, x.node_alloc());
|
||||
// Need to delete before setting the allocator so that buckets
|
||||
// aren't deleted with the wrong allocator.
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
// TODO: Can allocator assignment throw?
|
||||
this->allocators_.assign(x.allocators_);
|
||||
this->swap(tmp, false_type());
|
||||
}
|
||||
|
||||
void move_assign(table& x)
|
||||
{
|
||||
if (this != boost::addressof(x))
|
||||
{
|
||||
move_assign(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_move_assignment::value>());
|
||||
}
|
||||
move_assign(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_move_assignment::value>());
|
||||
}
|
||||
|
||||
void move_assign(table& x, true_type)
|
||||
{
|
||||
delete_buckets();
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
allocators_.move_assign(x.allocators_);
|
||||
// No throw from here.
|
||||
mlf_ = x.mlf_;
|
||||
max_load_ = x.max_load_;
|
||||
move_buckets_from(x);
|
||||
new_func_this.commit();
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->allocators_.move_assign(x.allocators_);
|
||||
move_assign_no_alloc(x);
|
||||
}
|
||||
|
||||
void move_assign(table& x, false_type)
|
||||
{
|
||||
if (node_alloc() == x.node_alloc()) {
|
||||
delete_buckets();
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
// No throw from here.
|
||||
mlf_ = x.mlf_;
|
||||
max_load_ = x.max_load_;
|
||||
move_buckets_from(x);
|
||||
new_func_this.commit();
|
||||
if(this->node_alloc() == x.node_alloc()) {
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
move_assign_no_alloc(x);
|
||||
}
|
||||
else {
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
mlf_ = x.mlf_;
|
||||
recalculate_max_load();
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
|
||||
if (!size_ && !x.size_) {
|
||||
new_func_this.commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (x.size_ >= max_load_) {
|
||||
create_buckets(min_buckets_for_size(x.size_));
|
||||
if (x.size_) {
|
||||
buckets b(this->node_alloc(),
|
||||
x.min_buckets_for_size(x.size_));
|
||||
buckets tmp(x, move_tag());
|
||||
table_impl::move_buckets_to(tmp, b);
|
||||
b.swap(*this);
|
||||
}
|
||||
else {
|
||||
clear_buckets();
|
||||
this->clear();
|
||||
}
|
||||
|
||||
|
||||
this->mlf_ = x.mlf_;
|
||||
if (this->buckets_) this->max_load_ = calculate_max_load();
|
||||
new_func_this.commit();
|
||||
static_cast<table_impl*>(this)->move_assign_buckets(x);
|
||||
}
|
||||
}
|
||||
|
||||
void move_assign_no_alloc(table& x)
|
||||
{
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
// No throw from here.
|
||||
this->move_buckets_from(x);
|
||||
this->mlf_ = x.mlf_;
|
||||
this->max_load_ = x.max_load_;
|
||||
new_func_this.commit();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Swap & Move
|
||||
|
||||
void swap(table& x)
|
||||
{
|
||||
swap(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
// Only swaps the allocators if Propagate::value
|
||||
template <typename Propagate>
|
||||
void swap(table& x, Propagate p)
|
||||
{
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
op1(*this, x);
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
op2(x, *this);
|
||||
// I think swap can throw if Propagate::value,
|
||||
// since the allocators' swap can throw. Not sure though.
|
||||
this->buckets::swap(x, p);
|
||||
std::swap(this->mlf_, x.mlf_);
|
||||
std::swap(this->max_load_, x.max_load_);
|
||||
op1.commit();
|
||||
op2.commit();
|
||||
}
|
||||
|
||||
// Swap everything but the allocators, and the functions objects.
|
||||
void swap_contents(table& x)
|
||||
{
|
||||
this->buckets::swap(x, false_type());
|
||||
std::swap(this->mlf_, x.mlf_);
|
||||
std::swap(this->max_load_, x.max_load_);
|
||||
}
|
||||
|
||||
// Accessors
|
||||
|
||||
@@ -703,27 +346,41 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Find Node
|
||||
|
||||
template <typename Key, typename Hash, typename Pred>
|
||||
node_pointer generic_find_node(
|
||||
iterator generic_find_node(
|
||||
Key const& k,
|
||||
Hash const& hf,
|
||||
Pred const& eq) const
|
||||
{
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(policy::apply_hash(hf, k), k, eq);
|
||||
}
|
||||
|
||||
node_pointer find_node(
|
||||
iterator find_node(
|
||||
std::size_t key_hash,
|
||||
key_type const& k) const
|
||||
{
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(key_hash, k, this->key_eq());
|
||||
}
|
||||
|
||||
node_pointer find_node(key_type const& k) const
|
||||
iterator find_node(key_type const& k) const
|
||||
{
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(hash(k), k, this->key_eq());
|
||||
find_node_impl(this->hash(k), k, this->key_eq());
|
||||
}
|
||||
|
||||
iterator find_matching_node(iterator n) const
|
||||
{
|
||||
// TODO: Does this apply to C++11?
|
||||
//
|
||||
// For some stupid reason, I decided to support equality comparison
|
||||
// when different hash functions are used. So I can't use the hash
|
||||
// value from the node here.
|
||||
|
||||
return find_node(get_key(*n));
|
||||
}
|
||||
|
||||
// Reserve and rehash
|
||||
@@ -740,19 +397,22 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename Types>
|
||||
inline void table<Types>::reserve_for_insert(std::size_t size)
|
||||
{
|
||||
if (!buckets_) {
|
||||
create_buckets((std::max)(bucket_count_,
|
||||
min_buckets_for_size(size)));
|
||||
if (!this->buckets_) {
|
||||
this->bucket_count_ = (std::max)(this->bucket_count_,
|
||||
this->min_buckets_for_size(size));
|
||||
this->create_buckets();
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
// According to the standard this should be 'size >= max_load_',
|
||||
// but I think this is better, defect report filed.
|
||||
else if(size > max_load_) {
|
||||
std::size_t num_buckets
|
||||
= min_buckets_for_size((std::max)(size,
|
||||
size_ + (size_ >> 1)));
|
||||
|
||||
if (num_buckets != bucket_count_)
|
||||
= this->min_buckets_for_size((std::max)(size,
|
||||
this->size_ + (this->size_ >> 1)));
|
||||
if (num_buckets != this->bucket_count_) {
|
||||
static_cast<table_impl*>(this)->rehash_impl(num_buckets);
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,18 +424,20 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if(!size_) {
|
||||
delete_buckets();
|
||||
bucket_count_ = policy::new_bucket_count(min_buckets);
|
||||
if(!this->size_) {
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->bucket_count_ = policy::new_bucket_count(min_buckets);
|
||||
}
|
||||
else {
|
||||
min_buckets = policy::new_bucket_count((std::max)(min_buckets,
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(size_) /
|
||||
static_cast<double>(this->size_) /
|
||||
static_cast<double>(mlf_))) + 1));
|
||||
|
||||
if(min_buckets != bucket_count_)
|
||||
if(min_buckets != this->bucket_count_) {
|
||||
static_cast<table_impl*>(this)->rehash_impl(min_buckets);
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,12 +445,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
inline void table<Types>::reserve(std::size_t num_elements)
|
||||
{
|
||||
rehash(static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>(num_elements) / mlf_)));
|
||||
std::ceil(static_cast<double>(num_elements) / this->mlf_)));
|
||||
}
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
@@ -24,23 +24,43 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename A, typename T>
|
||||
struct unique_node :
|
||||
boost::unordered::detail::node_base<
|
||||
typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, unique_node<A, T> >::type::pointer
|
||||
>,
|
||||
boost::unordered::detail::value_base<T>
|
||||
{
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, unique_node<A, T> >::type allocator;
|
||||
typedef typename ::boost::unordered::detail::
|
||||
allocator_traits<allocator>::pointer node_pointer;
|
||||
typedef node_pointer link_pointer;
|
||||
A, unique_node<A, T> >::type::pointer link_pointer;
|
||||
typedef boost::unordered::detail::node_base<link_pointer> node_base;
|
||||
|
||||
link_pointer next_;
|
||||
std::size_t hash_;
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
explicit unique_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
node_base(),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~unique_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
|
||||
unique_node(unique_node const&) {
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
#else
|
||||
unique_node() :
|
||||
next_(),
|
||||
node_base(),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(node_pointer)
|
||||
void init(link_pointer)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,29 +70,43 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct ptr_node :
|
||||
boost::unordered::detail::value_base<T>,
|
||||
boost::unordered::detail::ptr_bucket
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||
typedef ptr_node<T>* node_pointer;
|
||||
typedef bucket_base node_base;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
std::size_t hash_;
|
||||
boost::unordered::detail::value_base<T> value_base_;
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
explicit ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
bucket_base(),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~ptr_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
|
||||
ptr_node(ptr_node const&) {
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
#else
|
||||
ptr_node() :
|
||||
bucket_base(),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(node_pointer)
|
||||
void init(link_pointer)
|
||||
{
|
||||
}
|
||||
|
||||
void* address() { return value_base_.address(); }
|
||||
value_type& value() { return value_base_.value(); }
|
||||
value_type* value_ptr() { return value_base_.value_ptr(); }
|
||||
|
||||
private:
|
||||
ptr_node& operator=(ptr_node const&);
|
||||
};
|
||||
@@ -106,11 +140,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename T>
|
||||
struct pick_node
|
||||
{
|
||||
typedef typename boost::remove_const<T>::type nonconst;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<
|
||||
typename boost::unordered::detail::rebind_wrap<A,
|
||||
boost::unordered::detail::ptr_node<nonconst> >::type
|
||||
boost::unordered::detail::ptr_node<T> >::type
|
||||
> tentative_node_traits;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<
|
||||
@@ -118,7 +150,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::ptr_bucket >::type
|
||||
> tentative_bucket_traits;
|
||||
|
||||
typedef pick_node2<A, nonconst,
|
||||
typedef pick_node2<A, T,
|
||||
typename tentative_node_traits::pointer,
|
||||
typename tentative_bucket_traits::pointer> pick;
|
||||
|
||||
@@ -127,23 +159,75 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct set
|
||||
{
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T key_type;
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct map
|
||||
{
|
||||
typedef boost::unordered::detail::map<A, K, M, H, P> types;
|
||||
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K key_type;
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
struct table_impl : boost::unordered::detail::table<Types>
|
||||
{
|
||||
typedef boost::unordered::detail::table<Types> table;
|
||||
typedef typename table::value_type value_type;
|
||||
typedef typename table::bucket bucket;
|
||||
typedef typename table::buckets buckets;
|
||||
typedef typename table::policy policy;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
typedef typename table::node_allocator node_allocator;
|
||||
typedef typename table::node_allocator_traits node_allocator_traits;
|
||||
typedef typename table::bucket_pointer bucket_pointer;
|
||||
typedef typename table::link_pointer link_pointer;
|
||||
typedef typename table::previous_pointer previous_pointer;
|
||||
typedef typename table::hasher hasher;
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::node_tmp node_tmp;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
@@ -161,17 +245,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
table_impl(table_impl const& x)
|
||||
: table(x, node_allocator_traits::
|
||||
select_on_container_copy_construction(x.node_alloc()))
|
||||
{
|
||||
this->init(x);
|
||||
}
|
||||
select_on_container_copy_construction(x.node_alloc())) {}
|
||||
|
||||
table_impl(table_impl const& x,
|
||||
node_allocator const& a)
|
||||
: table(x, a)
|
||||
{
|
||||
this->init(x);
|
||||
}
|
||||
{}
|
||||
|
||||
table_impl(table_impl& x,
|
||||
boost::unordered::detail::move_tag m)
|
||||
@@ -182,57 +261,51 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_allocator const& a,
|
||||
boost::unordered::detail::move_tag m)
|
||||
: table(x, a, m)
|
||||
{
|
||||
this->move_init(x);
|
||||
}
|
||||
|
||||
// Node functions.
|
||||
|
||||
static inline node_pointer next_node(link_pointer n) {
|
||||
return static_cast<node_pointer>(n->next_);
|
||||
}
|
||||
{}
|
||||
|
||||
// Accessors
|
||||
|
||||
template <class Key, class Pred>
|
||||
node_pointer find_node_impl(
|
||||
iterator find_node_impl(
|
||||
std::size_t key_hash,
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
node_pointer n = this->begin(bucket_index);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
iterator n = this->get_start(bucket_index);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!n) return n;
|
||||
if (!n.node_) return n;
|
||||
|
||||
std::size_t node_hash = n->hash_;
|
||||
std::size_t node_hash = n.node_->hash_;
|
||||
if (key_hash == node_hash)
|
||||
{
|
||||
if (eq(k, this->get_key(n->value())))
|
||||
if (eq(k, this->get_key(*n)))
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return node_pointer();
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
n = next_node(n);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t count(key_type const& k) const
|
||||
{
|
||||
return this->find_node(k) ? 1 : 0;
|
||||
return this->find_node(k).node_ ? 1 : 0;
|
||||
}
|
||||
|
||||
value_type& at(key_type const& k) const
|
||||
{
|
||||
if (this->size_) {
|
||||
node_pointer n = this->find_node(k);
|
||||
if (n) return n->value();
|
||||
iterator it = this->find_node(k);
|
||||
if (it.node_) return *it;
|
||||
}
|
||||
|
||||
boost::throw_exception(
|
||||
@@ -242,8 +315,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(key_type const& k) const
|
||||
{
|
||||
node_pointer n = this->find_node(k);
|
||||
return std::make_pair(iterator(n), iterator(n ? next_node(n) : n));
|
||||
iterator n = this->find_node(k);
|
||||
iterator n2 = n;
|
||||
if (n2.node_) ++n2;
|
||||
return std::make_pair(n, n2);
|
||||
}
|
||||
|
||||
// equals
|
||||
@@ -251,13 +326,19 @@ namespace boost { namespace unordered { namespace detail {
|
||||
bool equals(table_impl const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
for(node_pointer n1 = this->begin(); n1; n1 = next_node(n1))
|
||||
for(iterator n1 = this->get_start(); n1.node_; ++n1)
|
||||
{
|
||||
node_pointer n2 = other.find_node(other.get_key(n1->value()));
|
||||
iterator n2 = other.find_matching_node(n1);
|
||||
|
||||
if (!n2 || n1->value() != n2->value())
|
||||
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
if (!n2.node_ || *n1 != *n2)
|
||||
return false;
|
||||
#else
|
||||
if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -265,88 +346,77 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Emplace/Insert
|
||||
|
||||
inline node_pointer add_node(
|
||||
node_pointer n,
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
std::size_t key_hash)
|
||||
{
|
||||
node_pointer n = a.release();
|
||||
n->hash_ = key_hash;
|
||||
|
||||
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
|
||||
bucket_pointer b = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
link_pointer start_node = this->get_previous_start();
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(this->hash_to_bucket(
|
||||
next_node(start_node)->hash_)
|
||||
this->get_bucket(policy::to_bucket(this->bucket_count_,
|
||||
static_cast<node_pointer>(start_node->next_)->hash_)
|
||||
)->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
n->next_ = start_node->next_;
|
||||
start_node->next_ = n;
|
||||
start_node->next_ = static_cast<link_pointer>(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = n;
|
||||
b->next_->next_ = static_cast<link_pointer>(n);
|
||||
}
|
||||
|
||||
++this->size_;
|
||||
return n;
|
||||
}
|
||||
|
||||
inline node_pointer resize_and_add_node(node_pointer n, std::size_t key_hash)
|
||||
{
|
||||
node_tmp b(n, this->node_alloc());
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return this->add_node(b.release(), key_hash);
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
value_type& operator[](key_type const& k)
|
||||
{
|
||||
typedef typename value_type::second_type mapped_type;
|
||||
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
if (pos) {
|
||||
return pos->value();
|
||||
}
|
||||
else {
|
||||
return this->resize_and_add_node(
|
||||
boost::unordered::detail::func::construct_node_pair(this->node_alloc(), k),
|
||||
key_hash)->value();
|
||||
}
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos.node_) return *pos;
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
|
||||
a.construct_value(BOOST_UNORDERED_EMPLACE_ARGS3(
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(k),
|
||||
boost::make_tuple()));
|
||||
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return *add_node(a, key_hash);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
emplace_return emplace(boost::unordered::detail::emplace_args1<
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return emplace_return(iterator(), false);
|
||||
}
|
||||
|
||||
iterator emplace_hint(c_iterator,
|
||||
boost::unordered::detail::emplace_args1<
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return iterator();
|
||||
return emplace_return(this->begin(), false);
|
||||
}
|
||||
# else
|
||||
emplace_return emplace(
|
||||
boost::unordered::detail::please_ignore_this_overload const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return emplace_return(iterator(), false);
|
||||
}
|
||||
|
||||
iterator emplace_hint(c_iterator,
|
||||
boost::unordered::detail::please_ignore_this_overload const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return iterator();
|
||||
return emplace_return(this->begin(), false);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
@@ -354,7 +424,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
return emplace_impl(
|
||||
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
@@ -365,108 +435,59 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
iterator emplace_hint(c_iterator hint,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
return emplace_hint_impl(hint,
|
||||
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
#else
|
||||
return emplace_hint_impl(hint,
|
||||
extractor::extract(args.a0, args.a1),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <typename A0>
|
||||
emplace_return emplace(
|
||||
boost::unordered::detail::emplace_args1<A0> const& args)
|
||||
{
|
||||
return emplace_impl(extractor::extract(args.a0), args);
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(c_iterator hint,
|
||||
boost::unordered::detail::emplace_args1<A0> const& args)
|
||||
{
|
||||
return emplace_hint_impl(hint, extractor::extract(args.a0), args);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
iterator emplace_hint_impl(c_iterator hint, key_type const& k,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
|
||||
return iterator(hint.node_);
|
||||
}
|
||||
else {
|
||||
return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
|
||||
}
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
emplace_return emplace_impl(key_type const& k,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
if (pos) {
|
||||
return emplace_return(iterator(pos), false);
|
||||
}
|
||||
else {
|
||||
return emplace_return(
|
||||
iterator(this->resize_and_add_node(
|
||||
boost::unordered::detail::func::construct_node_from_args(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
key_hash)),
|
||||
true);
|
||||
}
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos.node_) return emplace_return(pos, false);
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
iterator emplace_hint_impl(c_iterator hint, no_key,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
emplace_return emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_node_from_args(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
this->node_alloc());
|
||||
key_type const& k = this->get_key(b.node_->value());
|
||||
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
|
||||
return iterator(hint.node_);
|
||||
}
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
if (pos) {
|
||||
return iterator(pos);
|
||||
}
|
||||
else {
|
||||
return iterator(this->resize_and_add_node(b.release(), key_hash));
|
||||
}
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos.node_) return emplace_return(pos, false);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_node_from_args(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
this->node_alloc());
|
||||
key_type const& k = this->get_key(b.node_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
if (pos) {
|
||||
return emplace_return(iterator(pos), false);
|
||||
}
|
||||
else {
|
||||
return emplace_return(
|
||||
iterator(this->resize_and_add_node(b.release(), key_hash)),
|
||||
true);
|
||||
}
|
||||
// Don't have a key, so construct the node first in order
|
||||
// to be able to lookup the position.
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
return emplace_impl_with_node(a);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -485,9 +506,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <class InputIt>
|
||||
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
|
||||
{
|
||||
insert_range_impl2(k, i, j);
|
||||
node_constructor a(this->node_alloc());
|
||||
|
||||
while(++i != j) {
|
||||
// Special case for empty buckets so that we can use
|
||||
// max_load_ (which isn't valid when buckets_ is null).
|
||||
if (!this->buckets_) {
|
||||
insert_range_empty(a, k, i, j);
|
||||
if (++i == j) return;
|
||||
}
|
||||
|
||||
do {
|
||||
// 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.
|
||||
@@ -496,25 +524,40 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// key here. Could be more efficient if '*i' is expensive. Could
|
||||
// be less efficient if copying the full value_type is
|
||||
// expensive.
|
||||
insert_range_impl2(extractor::extract(*i), i, j);
|
||||
}
|
||||
insert_range_impl2(a, extractor::extract(*i), i, j);
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void insert_range_impl2(key_type const& k, InputIt i, InputIt j)
|
||||
void insert_range_empty(node_constructor& a, key_type const& k,
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
std::size_t key_hash = this->hash(k);
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
this->add_node(a, key_hash);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void insert_range_impl2(node_constructor& a, key_type const& k,
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (!pos.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
|
||||
if (!pos) {
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_node(this->node_alloc(), *i),
|
||||
this->node_alloc());
|
||||
if(this->size_ + 1 > this->max_load_)
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
this->add_node(b.release(), key_hash);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
this->add_node(a, key_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,24 +567,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor a(this->node_alloc());
|
||||
|
||||
do {
|
||||
if (!a.node_) { a.create_node(); }
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, a.node_->value_ptr(), *i);
|
||||
node_tmp b(a.release(), a.alloc_);
|
||||
|
||||
key_type const& k = this->get_key(b.node_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos) {
|
||||
a.reclaim(b.release());
|
||||
}
|
||||
else {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
this->add_node(b.release(), key_hash);
|
||||
}
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
emplace_impl_with_node(a);
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
@@ -555,125 +583,186 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t key_hash = this->hash(k);
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
bucket_pointer this_bucket = this->get_bucket(bucket_index);
|
||||
|
||||
previous_pointer prev = this_bucket->next_;
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash = next_node(prev)->hash_;
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return 0;
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
next_node(prev)->value())))
|
||||
static_cast<node_pointer>(prev->next_)->value())))
|
||||
break;
|
||||
prev = prev->next_;
|
||||
prev = static_cast<previous_pointer>(prev->next_);
|
||||
}
|
||||
|
||||
link_pointer end = next_node(prev)->next_;
|
||||
|
||||
std::size_t deleted_count = this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return deleted_count;
|
||||
node_pointer pos = static_cast<node_pointer>(prev->next_);
|
||||
node_pointer end = static_cast<node_pointer>(pos->next_);
|
||||
prev->next_ = pos->next_;
|
||||
this->fix_buckets(this_bucket, prev, end);
|
||||
return this->delete_nodes(c_iterator(pos), c_iterator(end));
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
{
|
||||
BOOST_ASSERT(r.node_);
|
||||
node_pointer next = next_node(r.node_);
|
||||
erase_nodes(r.node_, next);
|
||||
return iterator(next);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
|
||||
bucket_pointer this_bucket = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, r.node_->hash_));
|
||||
previous_pointer prev = unlink_node(*this_bucket, r.node_);
|
||||
|
||||
this->fix_buckets(this_bucket, prev, next.node_);
|
||||
|
||||
this->delete_node(r);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
erase_nodes(r1.node_, r2.node_);
|
||||
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
|
||||
previous_pointer prev = unlink_nodes(
|
||||
*this->get_bucket(bucket_index), r1.node_, r2.node_);
|
||||
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
|
||||
this->delete_nodes(r1, r2);
|
||||
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
void erase_nodes(node_pointer i, node_pointer j)
|
||||
static previous_pointer unlink_node(bucket& b, node_pointer n)
|
||||
{
|
||||
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
|
||||
return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
|
||||
}
|
||||
|
||||
// Find the node before i.
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
while(prev->next_ != i) prev = prev->next_;
|
||||
|
||||
// Delete the nodes.
|
||||
do {
|
||||
this->delete_node(prev);
|
||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||
} while (prev->next_ != j);
|
||||
static previous_pointer unlink_nodes(bucket& b,
|
||||
node_pointer begin, node_pointer end)
|
||||
{
|
||||
previous_pointer prev = b.next_;
|
||||
link_pointer begin_void = static_cast<link_pointer>(begin);
|
||||
while(prev->next_ != begin_void)
|
||||
prev = static_cast<previous_pointer>(prev->next_);
|
||||
prev->next_ = static_cast<link_pointer>(end);
|
||||
return prev;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// fill_buckets
|
||||
// copy_buckets_to
|
||||
//
|
||||
// Basic exception safety. If an exception is thrown this will
|
||||
// leave dst partially filled and the buckets unset.
|
||||
|
||||
void copy_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_node(
|
||||
this->node_alloc(), n->value()), n->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void move_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_node(
|
||||
this->node_alloc(), boost::move(n->value())), n->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void assign_buckets(table const& src)
|
||||
static void copy_buckets_to(buckets const& src, buckets& dst)
|
||||
{
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for(node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||
this->add_node(holder.copy_of(n->value()), n->hash_);
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets();
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(*n);
|
||||
|
||||
node_pointer node = a.release();
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
++n;
|
||||
|
||||
prev = place_in_bucket(dst, prev);
|
||||
}
|
||||
}
|
||||
|
||||
void move_assign_buckets(table& src)
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// move_buckets_to
|
||||
//
|
||||
// Basic exception safety. The source nodes are left in an unusable
|
||||
// state if an exception throws.
|
||||
|
||||
static void move_buckets_to(buckets& src, buckets& dst)
|
||||
{
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for(node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||
this->add_node(holder.move_copy_of(n->value()), n->hash_);
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets();
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(*n));
|
||||
|
||||
node_pointer node = a.release();
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
++n;
|
||||
|
||||
prev = place_in_bucket(dst, prev);
|
||||
}
|
||||
}
|
||||
|
||||
// strong otherwise exception safety
|
||||
void rehash_impl(std::size_t num_buckets)
|
||||
{
|
||||
BOOST_ASSERT(this->buckets_);
|
||||
BOOST_ASSERT(this->size_);
|
||||
|
||||
this->create_buckets(num_buckets);
|
||||
link_pointer prev = this->get_previous_start();
|
||||
buckets dst(this->node_alloc(), num_buckets);
|
||||
dst.create_buckets();
|
||||
|
||||
previous_pointer src_start = this->get_previous_start();
|
||||
previous_pointer dst_start = dst.get_previous_start();
|
||||
|
||||
dst_start->next_ = src_start->next_;
|
||||
src_start->next_ = link_pointer();
|
||||
dst.size_ = this->size_;
|
||||
this->size_ = 0;
|
||||
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
while (prev->next_)
|
||||
prev = place_in_bucket(*this, prev);
|
||||
prev = place_in_bucket(dst, prev);
|
||||
|
||||
// Swap the new nodes back into the container and setup the
|
||||
// variables.
|
||||
dst.swap(*this); // no throw
|
||||
}
|
||||
|
||||
// Iterate through the nodes placing them in the correct buckets.
|
||||
// pre: prev->next_ is not null.
|
||||
static link_pointer place_in_bucket(table& dst, link_pointer prev)
|
||||
static previous_pointer place_in_bucket(buckets& dst,
|
||||
previous_pointer prev)
|
||||
{
|
||||
node_pointer n = next_node(prev);
|
||||
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
bucket_pointer b = dst.get_bucket(
|
||||
buckets::to_bucket(dst.bucket_count_, n->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
return n;
|
||||
return static_cast<previous_pointer>(n);
|
||||
}
|
||||
else {
|
||||
prev->next_ = n->next_;
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = n;
|
||||
b->next_->next_ = static_cast<link_pointer>(n);
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
@@ -29,11 +28,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
struct move_tag {};
|
||||
struct empty_emplace {};
|
||||
|
||||
namespace func {
|
||||
template <class T>
|
||||
inline void ignore_unused_variable_warning(T const&) {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// iterator SFINAE
|
||||
|
||||
@@ -124,16 +118,33 @@ namespace boost { namespace unordered { namespace detail {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// 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, typename
|
||||
boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
|
||||
inline typename
|
||||
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
|
||||
insert_size(I i, I j)
|
||||
{
|
||||
return static_cast<std::size_t>(std::distance(i, j));
|
||||
return std::distance(i, j);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t insert_size(I, I, typename
|
||||
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
|
||||
inline typename
|
||||
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
|
||||
insert_size(I, I)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
#ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include <boost/unordered/detail/map.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
@@ -55,6 +56,7 @@ namespace unordered
|
||||
private:
|
||||
|
||||
typedef boost::unordered::detail::map<A, K, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
@@ -82,23 +84,12 @@ namespace unordered
|
||||
|
||||
// constructors
|
||||
|
||||
unordered_map();
|
||||
|
||||
explicit unordered_map(
|
||||
size_type,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(),
|
||||
const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
explicit unordered_map(
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_map(
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_map(allocator_type const&);
|
||||
|
||||
template <class InputIt>
|
||||
@@ -119,40 +110,28 @@ namespace unordered
|
||||
const key_equal&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_map(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_map(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
// copy/move constructors
|
||||
|
||||
unordered_map(unordered_map const&);
|
||||
|
||||
unordered_map(unordered_map const&, allocator_type const&);
|
||||
unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_map(BOOST_RV_REF(unordered_map) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
unordered_map(
|
||||
std::initializer_list<value_type>,
|
||||
@@ -160,20 +139,11 @@ namespace unordered
|
||||
const hasher& = hasher(),
|
||||
const key_equal&l = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
unordered_map(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
unordered_map(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
#endif
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_map() BOOST_NOEXCEPT;
|
||||
~unordered_map();
|
||||
|
||||
// Assign
|
||||
|
||||
@@ -196,7 +166,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map& operator=(unordered_map&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@@ -209,60 +179,60 @@ namespace unordered
|
||||
unordered_map& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
size_type max_size() const;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
iterator end()
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -270,9 +240,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...).first;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -311,12 +281,12 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
@@ -332,15 +302,15 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
@@ -358,17 +328,17 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
@@ -390,15 +360,15 @@ namespace unordered
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator hint, \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace_hint(hint, \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)); \
|
||||
)).first; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@@ -480,12 +450,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@@ -494,19 +464,22 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
@@ -521,8 +494,9 @@ namespace unordered
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
@@ -532,13 +506,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@@ -568,6 +542,7 @@ namespace unordered
|
||||
private:
|
||||
|
||||
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
@@ -595,23 +570,12 @@ namespace unordered
|
||||
|
||||
// constructors
|
||||
|
||||
unordered_multimap();
|
||||
|
||||
explicit unordered_multimap(
|
||||
size_type,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(),
|
||||
const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
explicit unordered_multimap(
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_multimap(
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_multimap(allocator_type const&);
|
||||
|
||||
template <class InputIt>
|
||||
@@ -632,40 +596,28 @@ namespace unordered
|
||||
const key_equal&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multimap(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multimap(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
// copy/move constructors
|
||||
|
||||
unordered_multimap(unordered_multimap const&);
|
||||
|
||||
unordered_multimap(unordered_multimap const&, allocator_type const&);
|
||||
unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
unordered_multimap(
|
||||
std::initializer_list<value_type>,
|
||||
@@ -673,20 +625,11 @@ namespace unordered
|
||||
const hasher& = hasher(),
|
||||
const key_equal&l = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
unordered_multimap(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
unordered_multimap(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
#endif
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_multimap() BOOST_NOEXCEPT;
|
||||
~unordered_multimap();
|
||||
|
||||
// Assign
|
||||
|
||||
@@ -710,7 +653,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap& operator=(unordered_multimap&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@@ -723,60 +666,60 @@ namespace unordered
|
||||
unordered_multimap& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
size_type max_size() const;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
iterator end()
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
iterator emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -784,9 +727,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -825,9 +768,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
@@ -846,11 +789,11 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
@@ -872,12 +815,12 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
@@ -904,11 +847,11 @@ namespace unordered
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator hint, \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace_hint(hint, \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
@@ -990,12 +933,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@@ -1004,19 +947,22 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
@@ -1031,8 +977,9 @@ namespace unordered
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
@@ -1042,13 +989,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@@ -1062,13 +1009,6 @@ namespace unordered
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map()
|
||||
: table_(boost::unordered::detail::default_bucket_count, hasher(),
|
||||
key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
size_type n, const hasher &hf, const key_equal &eql,
|
||||
@@ -1077,20 +1017,6 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
size_type n, const allocator_type &a)
|
||||
: table_(n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
size_type n, const hasher &hf, const allocator_type &a)
|
||||
: table_(n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
|
||||
: table_(boost::unordered::detail::default_bucket_count,
|
||||
@@ -1141,32 +1067,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
|
||||
unordered_map<K,T,H,P,A>::~unordered_map() {}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
@@ -1175,13 +1076,17 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
BOOST_RV_REF(unordered_map) other, allocator_type const& a)
|
||||
unordered_map&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1196,30 +1101,6 @@ namespace unordered
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const hasher &hf, const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>& unordered_map<K,T,H,P,A>::operator=(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1234,7 +1115,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
std::size_t unordered_map<K,T,H,P,A>::max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@@ -1334,14 +1215,14 @@ namespace unordered
|
||||
typename unordered_map<K,T,H,P,A>::iterator
|
||||
unordered_map<K,T,H,P,A>::find(const key_type& k)
|
||||
{
|
||||
return iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
typename unordered_map<K,T,H,P,A>::const_iterator
|
||||
unordered_map<K,T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1353,7 +1234,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq)
|
||||
{
|
||||
return iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1365,7 +1246,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1403,13 +1284,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
float unordered_map<K,T,H,P,A>::load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
void unordered_map<K,T,H,P,A>::max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
@@ -1461,13 +1342,6 @@ namespace unordered
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap()
|
||||
: table_(boost::unordered::detail::default_bucket_count, hasher(),
|
||||
key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
size_type n, const hasher &hf, const key_equal &eql,
|
||||
@@ -1476,20 +1350,6 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
size_type n, const allocator_type &a)
|
||||
: table_(n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
size_type n, const hasher &hf, const allocator_type &a)
|
||||
: table_(n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
|
||||
: table_(boost::unordered::detail::default_bucket_count,
|
||||
@@ -1540,32 +1400,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
|
||||
unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
@@ -1574,13 +1409,17 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
|
||||
unordered_multimap&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1595,30 +1434,6 @@ namespace unordered
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const hasher &hf, const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>& unordered_multimap<K,T,H,P,A>::operator=(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1633,7 +1448,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@@ -1712,14 +1527,14 @@ namespace unordered
|
||||
typename unordered_multimap<K,T,H,P,A>::iterator
|
||||
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
|
||||
{
|
||||
return iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
typename unordered_multimap<K,T,H,P,A>::const_iterator
|
||||
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1731,7 +1546,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq)
|
||||
{
|
||||
return iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1743,7 +1558,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1781,13 +1596,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
float unordered_multimap<K,T,H,P,A>::load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/set.hpp>
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
@@ -52,6 +54,7 @@ namespace unordered
|
||||
private:
|
||||
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
@@ -67,9 +70,9 @@ namespace unordered
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef typename table::cl_iterator const_local_iterator;
|
||||
typedef typename table::l_iterator local_iterator;
|
||||
typedef typename table::cl_iterator local_iterator;
|
||||
typedef typename table::c_iterator const_iterator;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator iterator;
|
||||
|
||||
private:
|
||||
|
||||
@@ -79,23 +82,12 @@ namespace unordered
|
||||
|
||||
// constructors
|
||||
|
||||
unordered_set();
|
||||
|
||||
explicit unordered_set(
|
||||
size_type,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(),
|
||||
const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
explicit unordered_set(
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_set(
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_set(allocator_type const&);
|
||||
|
||||
template <class InputIt>
|
||||
@@ -116,40 +108,28 @@ namespace unordered
|
||||
const key_equal&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_set(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_set(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
// copy/move constructors
|
||||
|
||||
unordered_set(unordered_set const&);
|
||||
|
||||
unordered_set(unordered_set const&, allocator_type const&);
|
||||
unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_set(BOOST_RV_REF(unordered_set) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
unordered_set(
|
||||
std::initializer_list<value_type>,
|
||||
@@ -157,20 +137,11 @@ namespace unordered
|
||||
const hasher& = hasher(),
|
||||
const key_equal&l = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
unordered_set(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
unordered_set(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
#endif
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_set() BOOST_NOEXCEPT;
|
||||
~unordered_set();
|
||||
|
||||
// Assign
|
||||
|
||||
@@ -193,7 +164,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set& operator=(unordered_set&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@@ -206,60 +177,60 @@ namespace unordered
|
||||
unordered_set& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
size_type max_size() const;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
iterator end()
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -267,9 +238,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...).first;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -308,12 +279,12 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
@@ -329,15 +300,15 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
@@ -355,17 +326,17 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
@@ -387,15 +358,15 @@ namespace unordered
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator hint, \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace_hint(hint, \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)); \
|
||||
)).first; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@@ -464,12 +435,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@@ -478,19 +449,22 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
@@ -505,8 +479,9 @@ namespace unordered
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
@@ -516,13 +491,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@@ -551,6 +526,7 @@ namespace unordered
|
||||
private:
|
||||
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
@@ -566,9 +542,9 @@ namespace unordered
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef typename table::cl_iterator const_local_iterator;
|
||||
typedef typename table::l_iterator local_iterator;
|
||||
typedef typename table::cl_iterator local_iterator;
|
||||
typedef typename table::c_iterator const_iterator;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator iterator;
|
||||
|
||||
private:
|
||||
|
||||
@@ -578,23 +554,12 @@ namespace unordered
|
||||
|
||||
// constructors
|
||||
|
||||
unordered_multiset();
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(),
|
||||
const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
explicit unordered_multiset(allocator_type const&);
|
||||
|
||||
template <class InputIt>
|
||||
@@ -615,40 +580,28 @@ namespace unordered
|
||||
const key_equal&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multiset(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
|
||||
template <class InputIt>
|
||||
unordered_multiset(
|
||||
InputIt, InputIt,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
|
||||
// copy/move constructors
|
||||
|
||||
unordered_multiset(unordered_multiset const&);
|
||||
|
||||
unordered_multiset(unordered_multiset const&, allocator_type const&);
|
||||
unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
unordered_multiset(
|
||||
std::initializer_list<value_type>,
|
||||
@@ -656,20 +609,11 @@ namespace unordered
|
||||
const hasher& = hasher(),
|
||||
const key_equal&l = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
unordered_multiset(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const hasher&,
|
||||
const allocator_type&);
|
||||
unordered_multiset(
|
||||
std::initializer_list<value_type>,
|
||||
size_type,
|
||||
const allocator_type&);
|
||||
#endif
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_multiset() BOOST_NOEXCEPT;
|
||||
~unordered_multiset();
|
||||
|
||||
// Assign
|
||||
|
||||
@@ -693,7 +637,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset& operator=(unordered_multiset&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@@ -706,60 +650,60 @@ namespace unordered
|
||||
unordered_multiset& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
bool empty() const
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
size_type size() const
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
size_type max_size() const;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
iterator end()
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
const_iterator cend() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
iterator emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -767,9 +711,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -808,9 +752,9 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
@@ -829,11 +773,11 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
@@ -855,12 +799,12 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace_hint(hint,
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
@@ -887,11 +831,11 @@ namespace unordered
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator hint, \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace_hint(hint, \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
@@ -964,12 +908,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
size_type max_bucket_count() const
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@@ -978,19 +922,22 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{
|
||||
return local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
local_iterator end(size_type)
|
||||
@@ -1005,8 +952,9 @@ namespace unordered
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{
|
||||
return const_local_iterator(
|
||||
table_.begin(n), n, table_.bucket_count_);
|
||||
return table_.size_ ? const_local_iterator(
|
||||
table_.get_start(n), n, table_.bucket_count_) :
|
||||
const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type) const
|
||||
@@ -1016,13 +964,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
float max_load_factor() const
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@@ -1036,13 +984,6 @@ namespace unordered
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set()
|
||||
: table_(boost::unordered::detail::default_bucket_count, hasher(),
|
||||
key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
size_type n, const hasher &hf, const key_equal &eql,
|
||||
@@ -1051,20 +992,6 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
size_type n, const allocator_type &a)
|
||||
: table_(n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
size_type n, const hasher &hf, const allocator_type &a)
|
||||
: table_(n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
|
||||
: table_(boost::unordered::detail::default_bucket_count,
|
||||
@@ -1115,32 +1042,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
|
||||
unordered_set<T,H,P,A>::~unordered_set() {}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
@@ -1149,13 +1051,17 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
BOOST_RV_REF(unordered_set) other, allocator_type const& a)
|
||||
unordered_set&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1170,30 +1076,6 @@ namespace unordered
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const hasher &hf, const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1208,7 +1090,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
std::size_t unordered_set<T,H,P,A>::max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@@ -1287,7 +1169,7 @@ namespace unordered
|
||||
typename unordered_set<T,H,P,A>::const_iterator
|
||||
unordered_set<T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1299,7 +1181,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1328,13 +1210,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
float unordered_set<T,H,P,A>::load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
void unordered_set<T,H,P,A>::max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
@@ -1386,13 +1268,6 @@ namespace unordered
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset()
|
||||
: table_(boost::unordered::detail::default_bucket_count, hasher(),
|
||||
key_equal(), allocator_type())
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
size_type n, const hasher &hf, const key_equal &eql,
|
||||
@@ -1401,20 +1276,6 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
size_type n, const allocator_type &a)
|
||||
: table_(n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
size_type n, const hasher &hf, const allocator_type &a)
|
||||
: table_(n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
|
||||
: table_(boost::unordered::detail::default_bucket_count,
|
||||
@@ -1465,32 +1326,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered::detail::initial_size(f, l, n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
|
||||
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
@@ -1499,13 +1335,17 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
|
||||
unordered_multiset&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1520,30 +1360,6 @@ namespace unordered
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const hasher &hf, const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
std::initializer_list<value_type> list, size_type n,
|
||||
const allocator_type &a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1558,7 +1374,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
std::size_t unordered_multiset<T,H,P,A>::max_size() const
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@@ -1637,7 +1453,7 @@ namespace unordered
|
||||
typename unordered_multiset<T,H,P,A>::const_iterator
|
||||
unordered_multiset<T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1649,7 +1465,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1678,13 +1494,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
float unordered_multiset<T,H,P,A>::load_factor() const
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_SET_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_set.hpp>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"key": "unordered",
|
||||
"name": "Unordered",
|
||||
"authors": [
|
||||
"Daniel James"
|
||||
],
|
||||
"maintainers": [
|
||||
"Daniel James <dnljms -at- gmail.com>"
|
||||
],
|
||||
"description": "Unordered associative containers.",
|
||||
"std": [
|
||||
"tr1"
|
||||
],
|
||||
"category": [
|
||||
"Containers"
|
||||
]
|
||||
}
|
||||
+2
-79
@@ -5,82 +5,5 @@
|
||||
|
||||
import testing ;
|
||||
|
||||
project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
# Would be nice to define -Wundef, but I'm getting warnings from
|
||||
# Boost.Preprocessor on trunk.
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>msvc:<cxxflags>"/wd4494"
|
||||
;
|
||||
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
alias framework : ;
|
||||
|
||||
test-suite unordered
|
||||
:
|
||||
[ run unordered/fwd_set_test.cpp ]
|
||||
[ run unordered/fwd_map_test.cpp ]
|
||||
[ run unordered/allocator_traits.cpp ]
|
||||
[ run unordered/minimal_allocator.cpp ]
|
||||
[ run unordered/compile_set.cpp ]
|
||||
[ run unordered/compile_map.cpp ]
|
||||
[ run unordered/compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
|
||||
: compile_map_unordered_allocator ]
|
||||
[ run unordered/noexcept_tests.cpp ]
|
||||
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
|
||||
[ run unordered/incomplete_test.cpp ]
|
||||
[ run unordered/simple_tests.cpp ]
|
||||
[ run unordered/equivalent_keys_tests.cpp ]
|
||||
[ run unordered/constructor_tests.cpp ]
|
||||
[ run unordered/copy_tests.cpp ]
|
||||
[ run unordered/move_tests.cpp ]
|
||||
[ run unordered/assign_tests.cpp ]
|
||||
[ run unordered/insert_tests.cpp ]
|
||||
[ run unordered/insert_stable_tests.cpp ]
|
||||
[ run unordered/insert_hint_tests.cpp ]
|
||||
[ run unordered/emplace_tests.cpp ]
|
||||
[ run unordered/unnecessary_copy_tests.cpp ]
|
||||
[ run unordered/erase_tests.cpp ]
|
||||
[ run unordered/erase_equiv_tests.cpp ]
|
||||
[ run unordered/find_tests.cpp ]
|
||||
[ run unordered/at_tests.cpp ]
|
||||
[ run unordered/bucket_tests.cpp ]
|
||||
[ run unordered/load_factor_tests.cpp ]
|
||||
[ run unordered/rehash_tests.cpp ]
|
||||
[ run unordered/equality_tests.cpp ]
|
||||
[ run unordered/swap_tests.cpp ]
|
||||
|
||||
[ run unordered/compile_set.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_set ]
|
||||
[ run unordered/compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_map ]
|
||||
[ run unordered/copy_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_copy ]
|
||||
[ run unordered/move_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_move ]
|
||||
[ run unordered/assign_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_assign ]
|
||||
;
|
||||
|
||||
test-suite unordered-exception
|
||||
:
|
||||
[ run exception/constructor_exception_tests.cpp framework ]
|
||||
[ run exception/copy_exception_tests.cpp framework ]
|
||||
[ run exception/assign_exception_tests.cpp framework ]
|
||||
[ run exception/move_assign_exception_tests.cpp framework ]
|
||||
[ run exception/insert_exception_tests.cpp framework ]
|
||||
[ run exception/erase_exception_tests.cpp framework ]
|
||||
[ run exception/rehash_exception_tests.cpp framework ]
|
||||
[ run exception/swap_exception_tests.cpp framework : : :
|
||||
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
;
|
||||
build-project unordered ;
|
||||
build-project exception ;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
# Copyright 2006-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)
|
||||
|
||||
import testing ;
|
||||
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
alias framework : ;
|
||||
|
||||
project unordered-test/exception-tests
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
#<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
test-suite unordered-exception
|
||||
:
|
||||
[ run constructor_exception_tests.cpp framework ]
|
||||
[ run copy_exception_tests.cpp framework ]
|
||||
[ run assign_exception_tests.cpp framework ]
|
||||
[ run insert_exception_tests.cpp framework ]
|
||||
[ run erase_exception_tests.cpp framework ]
|
||||
[ run rehash_exception_tests.cpp framework ]
|
||||
[ run swap_exception_tests.cpp framework : : :
|
||||
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
;
|
||||
@@ -17,7 +17,7 @@ template <class T>
|
||||
struct self_assign_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
self_assign_base(std::size_t count = 0) : values(count) {}
|
||||
self_assign_base(int count = 0) : values(count) {}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(values.begin(), values.end()); }
|
||||
@@ -38,111 +38,54 @@ struct self_assign_test2 : self_assign_base<T>
|
||||
template <class T>
|
||||
struct assign_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> x_values, y_values;
|
||||
T x,y;
|
||||
const test::random_values<T> x_values, y_values;
|
||||
const T x,y;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
|
||||
x_values(),
|
||||
y_values(),
|
||||
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
|
||||
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
|
||||
{
|
||||
x.max_load_factor(mlf1);
|
||||
y.max_load_factor(mlf2);
|
||||
}
|
||||
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
|
||||
x_values(count1),
|
||||
y_values(count2),
|
||||
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
|
||||
allocator_type(tag1)),
|
||||
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
|
||||
allocator_type(tag2))
|
||||
{}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(x); }
|
||||
void run(T& x1) const { x1 = y; }
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
|
||||
{
|
||||
test::check_equivalent_keys(x1);
|
||||
|
||||
// If the container is empty at the point of the exception, the
|
||||
// internal structure is hidden, this exposes it, at the cost of
|
||||
// messing up the data.
|
||||
if (x_values.size()) {
|
||||
T& x2 = const_cast<T&>(x1);
|
||||
x2.emplace(*x_values.begin());
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
}
|
||||
{ test::check_equivalent_keys(x1); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_values : assign_base<T>
|
||||
struct assign_test1 : assign_base<T>
|
||||
{
|
||||
assign_values(unsigned int count1, unsigned int count2,
|
||||
int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
|
||||
assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
assign_test1() : assign_base<T>(0, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test1 : assign_values<T>
|
||||
struct assign_test2 : assign_base<T>
|
||||
{
|
||||
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
|
||||
assign_test2() : assign_base<T>(60, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test2 : assign_values<T>
|
||||
struct assign_test3 : assign_base<T>
|
||||
{
|
||||
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
|
||||
assign_test3() : assign_base<T>(0, 60, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test3 : assign_values<T>
|
||||
struct assign_test4 : assign_base<T>
|
||||
{
|
||||
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
|
||||
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test4 : assign_values<T>
|
||||
{
|
||||
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test4a : assign_values<T>
|
||||
{
|
||||
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test5 : assign_values<T>
|
||||
{
|
||||
assign_test5() : assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct equivalent_test1 : assign_base<T>
|
||||
{
|
||||
equivalent_test1() :
|
||||
assign_base<T>(0, 0)
|
||||
{
|
||||
test::random_values<T> x_values2(10);
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
test::random_values<T> y_values2(10);
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(self_assign_test1)(self_assign_test2)
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test4a)(assign_test5)
|
||||
(equivalent_test1),
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -159,7 +159,7 @@ struct copy_range_construct_test : public range<T>, objects
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(construct_test1)
|
||||
(construct_test2)
|
||||
(construct_test3)
|
||||
@@ -174,4 +174,3 @@ EXCEPTION_TESTS(
|
||||
(input_range_construct_test)
|
||||
(copy_range_construct_test),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -18,13 +18,13 @@ typedef boost::unordered_multiset<
|
||||
test::exception::object,
|
||||
test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator2<test::exception::object> > test_multiset;
|
||||
test::exception::allocator<test::exception::object> > test_multiset;
|
||||
typedef boost::unordered_map<
|
||||
test::exception::object,
|
||||
test::exception::object,
|
||||
test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator2<test::exception::object> > test_map;
|
||||
test::exception::allocator<test::exception::object> > test_map;
|
||||
typedef boost::unordered_multimap<
|
||||
test::exception::object,
|
||||
test::exception::object,
|
||||
|
||||
@@ -64,7 +64,6 @@ struct copy_with_allocator_test : public test::exception_base
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -49,7 +49,6 @@ struct erase_by_key_test1 : public erase_test_base<T>
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(erase_by_key_test1),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/strong.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include <boost/utility.hpp>
|
||||
#include <cmath>
|
||||
|
||||
test::seed_t initialize_seed(747373);
|
||||
@@ -17,7 +17,7 @@ template <class T>
|
||||
struct insert_test_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
insert_test_base(unsigned int count = 5) : values(count, test::limited_range) {}
|
||||
insert_test_base(unsigned int count = 5) : values(count) {}
|
||||
|
||||
typedef T data_type;
|
||||
typedef test::strong<T> strong_type;
|
||||
@@ -37,7 +37,7 @@ struct insert_test_base : public test::exception_base
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T>
|
||||
struct emplace_test1 : public insert_test_base<T>
|
||||
@@ -112,7 +112,7 @@ struct insert_test4 : public insert_test_base<T>
|
||||
it != end; ++it)
|
||||
{
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.insert(it, test::next(it));
|
||||
x.insert(it, boost::next(it));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -130,13 +130,12 @@ struct insert_test_rehash1 : public insert_test_base<T>
|
||||
|
||||
T x;
|
||||
x.max_load_factor(0.25);
|
||||
// TODO: This doesn't really work is bucket_count is 0
|
||||
size_type bucket_count = x.bucket_count();
|
||||
size_type initial_elements = static_cast<size_type>(
|
||||
ceil((double) bucket_count * (double) x.max_load_factor()) - 1);
|
||||
ceil(bucket_count * (double) x.max_load_factor()) - 1);
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
@@ -147,7 +146,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
|
||||
BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();
|
||||
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = test::next(this->values.begin(), x.size()),
|
||||
it = boost::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count)
|
||||
{
|
||||
@@ -171,7 +170,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
|
||||
int count = 0;
|
||||
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = test::next(this->values.begin(), x.size()),
|
||||
it = boost::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count)
|
||||
{
|
||||
@@ -202,14 +201,14 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
|
||||
original_bucket_count = x.bucket_count();
|
||||
rehash_bucket_count = static_cast<size_type>(
|
||||
ceil((double) original_bucket_count * (double) x.max_load_factor())) - 1;
|
||||
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
|
||||
|
||||
size_type initial_elements =
|
||||
rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
|
||||
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(original_bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
@@ -217,8 +216,8 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
void run(T& x) const {
|
||||
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
|
||||
|
||||
x.insert(test::next(this->values.begin(), x.size()),
|
||||
test::next(this->values.begin(), x.size() + 20));
|
||||
x.insert(boost::next(this->values.begin(), x.size()),
|
||||
boost::next(this->values.begin(), x.size() + 20));
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
@@ -237,12 +236,11 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
|
||||
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#define ALL_TESTS (emplace_test1)BASIC_TESTS
|
||||
#else
|
||||
#define ALL_TESTS BASIC_TESTS
|
||||
#endif
|
||||
|
||||
|
||||
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <iostream>
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable:4512) // move_assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t initialize_seed(12847);
|
||||
|
||||
template <class T>
|
||||
struct move_assign_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> x_values, y_values;
|
||||
T x,y;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
|
||||
x_values(),
|
||||
y_values(),
|
||||
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
|
||||
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
|
||||
{
|
||||
x.max_load_factor(mlf1);
|
||||
y.max_load_factor(mlf2);
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(x); }
|
||||
void run(T& x1) const {
|
||||
test::exceptions_enable disable_exceptions(false);
|
||||
T y1 = y;
|
||||
disable_exceptions.release();
|
||||
x1 = boost::move(y1);
|
||||
}
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
|
||||
{
|
||||
test::check_equivalent_keys(x1);
|
||||
|
||||
// If the container is empty at the point of the exception, the
|
||||
// internal structure is hidden, this exposes it, at the cost of
|
||||
// messing up the data.
|
||||
if (x_values.size()) {
|
||||
T& x2 = const_cast<T&>(x1);
|
||||
x2.emplace(*x_values.begin());
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_values : move_assign_base<T>
|
||||
{
|
||||
move_assign_values(unsigned int count1, unsigned int count2,
|
||||
int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
|
||||
move_assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test1 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test2 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test3 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test4 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test4a : move_assign_values<T>
|
||||
{
|
||||
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct move_assign_test5 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct equivalent_test1 : move_assign_base<T>
|
||||
{
|
||||
equivalent_test1() :
|
||||
move_assign_base<T>(0, 0)
|
||||
{
|
||||
test::random_values<T> x_values2(10);
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
test::random_values<T> y_values2(10);
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
(move_assign_test1)(move_assign_test2)(move_assign_test3)(move_assign_test4)(move_assign_test4a)(move_assign_test5)
|
||||
(equivalent_test1),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
@@ -18,8 +18,8 @@ struct rehash_test_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
unsigned int n;
|
||||
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
|
||||
: values(count), n(n_)
|
||||
rehash_test_base(unsigned int count = 100, unsigned int n = 0)
|
||||
: values(count), n(n)
|
||||
{}
|
||||
|
||||
typedef T data_type;
|
||||
@@ -79,7 +79,7 @@ struct rehash_test4 : rehash_test_base<T>
|
||||
void run(T& x) const { x.rehash(0); }
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ template <class T>
|
||||
struct self_swap_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
self_swap_base(std::size_t count = 0) : values(count) {}
|
||||
self_swap_base(int count = 0) : values(count) {}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(values.begin(), values.end()); }
|
||||
@@ -60,20 +60,17 @@ struct swap_base : public test::exception_base
|
||||
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
|
||||
key_equal(tag1), allocator_type(tag1)),
|
||||
initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
|
||||
key_equal(tag2), allocator_type(
|
||||
T::allocator_type::propagate_on_container_swap::value ?
|
||||
tag2 : tag1))
|
||||
key_equal(tag2), allocator_type(tag2))
|
||||
{}
|
||||
|
||||
struct data_type {
|
||||
data_type(T const& x_, T const& y_)
|
||||
: x(x_), y(y_) {}
|
||||
data_type(T const& x, T const& y)
|
||||
: x(x), y(y) {}
|
||||
|
||||
T x, y;
|
||||
};
|
||||
|
||||
data_type init() const { return data_type(initial_x, initial_y); }
|
||||
|
||||
void run(data_type& d) const {
|
||||
try {
|
||||
d.x.swap(d.y);
|
||||
@@ -118,8 +115,7 @@ struct swap_test4 : swap_base<T>
|
||||
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(self_swap_test1)(self_swap_test2)
|
||||
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -69,16 +69,10 @@ namespace test {
|
||||
};
|
||||
|
||||
struct check_instances {
|
||||
int instances_;
|
||||
int constructions_;
|
||||
int instances;
|
||||
|
||||
check_instances() :
|
||||
instances_(global_object_count.instances),
|
||||
constructions_(global_object_count.constructions) {}
|
||||
~check_instances() { BOOST_TEST(global_object_count.instances == instances_); }
|
||||
|
||||
int instances() const { return global_object_count.instances - instances_; }
|
||||
int constructions() const { return global_object_count.constructions - constructions_; }
|
||||
check_instances() : instances(global_object_count.instances) {}
|
||||
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -42,15 +42,20 @@ namespace test
|
||||
}
|
||||
|
||||
struct equivalent_type {
|
||||
equivalent_type() {}
|
||||
|
||||
template <class T1, class T2>
|
||||
bool operator()(T1 const& x, T2 const& y) const {
|
||||
bool operator()(T1 const& x, T2 const& y) {
|
||||
return equivalent_impl(x, y, derived);
|
||||
}
|
||||
};
|
||||
|
||||
const equivalent_type equivalent;
|
||||
// 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;
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
class unordered_equivalence_tester
|
||||
|
||||
@@ -20,37 +20,22 @@
|
||||
fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
} \
|
||||
|
||||
# define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
|
||||
UNORDERED_AUTO_TEST(name) \
|
||||
{ \
|
||||
for (unsigned i = 0; i < n; ++i) { \
|
||||
test_func< type > fixture; \
|
||||
::test::lightweight::exception_safety( \
|
||||
fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
|
||||
|
||||
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
|
||||
|
||||
#define EXCEPTION_TESTS(test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((1))(param_seq))
|
||||
#define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
|
||||
(test_seq)(param_seq)) \
|
||||
RUN_TESTS() \
|
||||
|
||||
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((n))(param_seq))
|
||||
|
||||
#define EXCEPTION_TESTS_OP(r, product) \
|
||||
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
|
||||
#define RUN_EXCEPTION_TESTS_OP(r, product) \
|
||||
UNORDERED_EXCEPTION_TEST_CASE( \
|
||||
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product)) \
|
||||
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
|
||||
), \
|
||||
BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_SEQ_ELEM(1, product), \
|
||||
BOOST_PP_SEQ_ELEM(2, product) \
|
||||
BOOST_PP_SEQ_ELEM(1, product) \
|
||||
) \
|
||||
|
||||
#define UNORDERED_SCOPE(scope_name) \
|
||||
@@ -111,28 +96,16 @@ namespace test {
|
||||
exceptions_enable(exceptions_enable const&);
|
||||
|
||||
bool old_value_;
|
||||
bool released_;
|
||||
public:
|
||||
exceptions_enable(bool enable)
|
||||
: old_value_(exceptions_enabled), released_(false)
|
||||
: old_value_(exceptions_enabled)
|
||||
{
|
||||
exceptions_enabled = enable;
|
||||
}
|
||||
|
||||
~exceptions_enable()
|
||||
{
|
||||
if (!released_) {
|
||||
exceptions_enabled = old_value_;
|
||||
released_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (!released_) {
|
||||
exceptions_enabled = old_value_;
|
||||
released_ = true;
|
||||
}
|
||||
exceptions_enabled = old_value_;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -179,13 +152,12 @@ namespace test {
|
||||
class test_runner
|
||||
{
|
||||
Test const& test_;
|
||||
bool exception_in_check_;
|
||||
|
||||
test_runner(test_runner const&);
|
||||
test_runner& operator=(test_runner const&);
|
||||
public:
|
||||
test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
|
||||
void run() {
|
||||
test_runner(Test const& t) : test_(t) {}
|
||||
void operator()() const {
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::scope = "";
|
||||
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
|
||||
@@ -200,24 +172,14 @@ namespace test {
|
||||
>(&Test::run, test_, x, strong);
|
||||
}
|
||||
catch(...) {
|
||||
try {
|
||||
DISABLE_EXCEPTIONS;
|
||||
call_ignore_extra_parameters<
|
||||
Test,
|
||||
BOOST_DEDUCED_TYPENAME Test::data_type const,
|
||||
BOOST_DEDUCED_TYPENAME Test::strong_type const
|
||||
>(&Test::check, test_, constant(x), constant(strong));
|
||||
} catch(...) {
|
||||
exception_in_check_ = true;
|
||||
}
|
||||
call_ignore_extra_parameters<
|
||||
Test,
|
||||
BOOST_DEDUCED_TYPENAME Test::data_type const,
|
||||
BOOST_DEDUCED_TYPENAME Test::strong_type const
|
||||
>(&Test::check, test_, constant(x), constant(strong));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
void end() {
|
||||
if (exception_in_check_) {
|
||||
BOOST_ERROR("Unexcpected exception in test_runner check call.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Quick exception testing based on lightweight test
|
||||
@@ -247,30 +209,26 @@ namespace test {
|
||||
|
||||
iteration = 0;
|
||||
bool success = false;
|
||||
char const* error_msg = 0;
|
||||
do {
|
||||
++iteration;
|
||||
count = 0;
|
||||
|
||||
try {
|
||||
runner.run();
|
||||
runner();
|
||||
success = true;
|
||||
}
|
||||
catch(test_failure) {
|
||||
error_msg = "test_failure caught.";
|
||||
BOOST_ERROR("test_failure caught.");
|
||||
break;
|
||||
}
|
||||
catch(test_exception) {
|
||||
continue;
|
||||
}
|
||||
catch(...) {
|
||||
error_msg = "Unexpected exception.";
|
||||
BOOST_ERROR("Unexpected exception.");
|
||||
break;
|
||||
}
|
||||
} while(!success);
|
||||
|
||||
if (error_msg) { BOOST_ERROR(error_msg); }
|
||||
runner.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-11
@@ -10,17 +10,11 @@
|
||||
|
||||
namespace test
|
||||
{
|
||||
typedef enum {
|
||||
default_generator,
|
||||
generate_collisions,
|
||||
limited_range
|
||||
} random_generator;
|
||||
|
||||
int generate(int const*, random_generator);
|
||||
char generate(char const*, random_generator);
|
||||
signed char generate(signed char const*, random_generator);
|
||||
std::string generate(std::string const*, random_generator);
|
||||
float generate(float const*, random_generator);
|
||||
int generate(int const*);
|
||||
char generate(char const*);
|
||||
signed char generate(signed char const*);
|
||||
std::string generate(std::string*);
|
||||
float generate(float const*);
|
||||
|
||||
struct base_type {} base;
|
||||
struct derived_type : base_type {} derived;
|
||||
|
||||
+10
-30
@@ -27,32 +27,25 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
std::size_t random_value(std::size_t max) {
|
||||
using namespace std;
|
||||
return static_cast<std::size_t>(rand()) % max;
|
||||
}
|
||||
|
||||
inline int generate(int const*, random_generator g)
|
||||
inline int generate(int const*)
|
||||
{
|
||||
using namespace std;
|
||||
int value = rand();
|
||||
if (g == limited_range) { value = value % 100; }
|
||||
return value;
|
||||
return rand();
|
||||
}
|
||||
|
||||
inline char generate(char const*, random_generator)
|
||||
inline char generate(char const*)
|
||||
{
|
||||
using namespace std;
|
||||
return static_cast<char>((rand() >> 1) % (128-32) + 32);
|
||||
}
|
||||
|
||||
inline signed char generate(signed char const*, random_generator)
|
||||
inline signed char generate(signed char const*)
|
||||
{
|
||||
using namespace std;
|
||||
return static_cast<signed char>(rand());
|
||||
}
|
||||
|
||||
inline std::string generate(std::string const*, random_generator g)
|
||||
inline std::string generate(std::string const*)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
@@ -60,30 +53,17 @@ namespace test
|
||||
|
||||
std::string result;
|
||||
|
||||
if (g == limited_range) {
|
||||
std::size_t length = test::random_value(2) + 2;
|
||||
|
||||
char const* strings[] = { "'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J" };
|
||||
for (std::size_t i = 0; i < length; ++i) {
|
||||
result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::size_t length = test::random_value(10) + 1;
|
||||
for (std::size_t i = 0; i < length; ++i) {
|
||||
result += generate(char_ptr, g);
|
||||
}
|
||||
}
|
||||
int length = rand() % 10;
|
||||
for(int i = 0; i < length; ++i)
|
||||
result += generate(char_ptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float generate(float const*, random_generator g)
|
||||
float generate(float const*)
|
||||
{
|
||||
using namespace std;
|
||||
int x = 0;
|
||||
int value = generate(&x, g);
|
||||
return (float) value / (float) RAND_MAX;
|
||||
return (float) rand() / (float) RAND_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,26 +38,6 @@ namespace test
|
||||
{
|
||||
return get_key_impl<Container>::get_key(x);
|
||||
}
|
||||
|
||||
// test::next
|
||||
//
|
||||
// Increments an iterator by 1 or a given value.
|
||||
// Like boost::next, but simpler and slower.
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator next(Iterator it)
|
||||
{
|
||||
return ++it;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename IntType>
|
||||
Iterator next(Iterator it, IntType x)
|
||||
{
|
||||
for(; x > 0; --x) {
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace test
|
||||
{
|
||||
@@ -28,7 +28,7 @@ namespace test
|
||||
|
||||
template <class Iterator>
|
||||
struct input_iterator_adaptor
|
||||
: public std::iterator<
|
||||
: public boost::iterator<
|
||||
std::input_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
|
||||
std::ptrdiff_t,
|
||||
@@ -72,7 +72,7 @@ namespace test
|
||||
|
||||
template <class Iterator>
|
||||
struct copy_iterator_adaptor
|
||||
: public std::iterator<
|
||||
: public boost::iterator<
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
|
||||
|
||||
@@ -82,40 +82,16 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
// Check that size matches up.
|
||||
|
||||
// Finally, check that size matches up.
|
||||
if(x1.size() != size) {
|
||||
BOOST_ERROR("x1.size() doesn't match actual size.");
|
||||
std::cout<<x1.size()<<"/"<<size<<std::endl;
|
||||
}
|
||||
|
||||
// Check the load factor.
|
||||
|
||||
float load_factor = size == 0 ? 0 :
|
||||
float load_factor =
|
||||
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
|
||||
using namespace std;
|
||||
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
|
||||
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
|
||||
|
||||
// Check that size in the buckets matches up.
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME X::size_type
|
||||
i = 0; i < x1.bucket_count(); ++i)
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
begin2 = x1.begin(i), end2 = x1.end(i);
|
||||
begin2 != end2; ++begin2)
|
||||
{
|
||||
++bucket_size;
|
||||
}
|
||||
}
|
||||
|
||||
if(x1.size() != bucket_size) {
|
||||
BOOST_ERROR("x1.size() doesn't match bucket size.");
|
||||
std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#if !defined(UNORDERED_TEST_LIST_HEADER)
|
||||
#define UNORDERED_TEST_LIST_HEADER
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
namespace test
|
||||
@@ -83,7 +83,7 @@ namespace test
|
||||
|
||||
template <typename T>
|
||||
class list_iterator
|
||||
: public std::iterator<
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, T,
|
||||
int, T*, T&>
|
||||
{
|
||||
@@ -109,7 +109,7 @@ namespace test
|
||||
|
||||
template <typename T>
|
||||
class list_const_iterator
|
||||
: public std::iterator<
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, T,
|
||||
int, T const*, T const&>
|
||||
{
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
namespace test
|
||||
{
|
||||
@@ -20,11 +22,19 @@ namespace test
|
||||
template <class Container>
|
||||
struct has_unique_keys
|
||||
{
|
||||
static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&);
|
||||
static long flip(std::pair<BOOST_DEDUCED_TYPENAME Container::iterator, bool> const&);
|
||||
BOOST_STATIC_CONSTANT(bool, value = sizeof(long) == sizeof(
|
||||
flip(((Container*) 0)->insert(*(BOOST_DEDUCED_TYPENAME Container::value_type*) 0))
|
||||
));
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template <class V, class H, class P, class A>
|
||||
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <class K, class M, class H, class P, class A>
|
||||
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
|
||||
namespace test
|
||||
{
|
||||
typedef enum {
|
||||
default_generator,
|
||||
generate_collisions
|
||||
} random_generator;
|
||||
|
||||
template <class X>
|
||||
struct unordered_generator_set
|
||||
{
|
||||
@@ -27,15 +32,15 @@ namespace test
|
||||
template <class T>
|
||||
void fill(T& x, std::size_t len) {
|
||||
value_type* value_ptr = 0;
|
||||
len += x.size();
|
||||
int* int_ptr = 0;
|
||||
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
value_type value = generate(value_ptr, type_);
|
||||
for(std::size_t i = 0; i < len; ++i) {
|
||||
value_type value = generate(value_ptr);
|
||||
|
||||
std::size_t count = type_ == generate_collisions ?
|
||||
random_value(5) + 1 : 1;
|
||||
|
||||
for(std::size_t j = 0; j < count; ++j) {
|
||||
for(int count =
|
||||
type_ == generate_collisions ?
|
||||
generate(int_ptr) % 10 : 1;
|
||||
count; --count) {
|
||||
x.push_back(value);
|
||||
}
|
||||
}
|
||||
@@ -57,16 +62,18 @@ namespace test
|
||||
void fill(T& x, std::size_t len) {
|
||||
key_type* key_ptr = 0;
|
||||
mapped_type* mapped_ptr = 0;
|
||||
int* int_ptr = 0;
|
||||
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
key_type key = generate(key_ptr, type_);
|
||||
for(std::size_t i = 0; i < len; ++i) {
|
||||
key_type key = generate(key_ptr);
|
||||
|
||||
std::size_t count = type_ == generate_collisions ?
|
||||
random_value(5) + 1 : 1;
|
||||
|
||||
for(std::size_t j = 0; j < count; ++j) {
|
||||
x.push_back(std::pair<key_type const, mapped_type>(
|
||||
key, generate(mapped_ptr, type_)));
|
||||
for(int count =
|
||||
type_ == generate_collisions ?
|
||||
generate(int_ptr) % 10 : 1;
|
||||
count; --count) {
|
||||
x.push_back(
|
||||
std::pair<key_type const, mapped_type>(
|
||||
key, generate(mapped_ptr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,18 +103,10 @@ namespace test
|
||||
struct random_values
|
||||
: public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
|
||||
{
|
||||
random_values() {}
|
||||
|
||||
explicit random_values(std::size_t count, test::random_generator const& generator =
|
||||
random_values(int count, test::random_generator const& generator =
|
||||
test::default_generator)
|
||||
{
|
||||
fill(count, generator);
|
||||
}
|
||||
|
||||
void fill(std::size_t count, test::random_generator const& generator =
|
||||
test::default_generator)
|
||||
{
|
||||
test::unordered_generator<X> gen(generator);
|
||||
static test::unordered_generator<X> gen(generator);
|
||||
gen.fill(*this, count);
|
||||
}
|
||||
};
|
||||
|
||||
+6
-33
@@ -24,11 +24,7 @@
|
||||
void BOOST_PP_CAT(x, _type)::run() \
|
||||
|
||||
#define RUN_TESTS() int main(int, char**) \
|
||||
{ \
|
||||
::test::write_compiler_info(); \
|
||||
::test::test_list::run_tests(); \
|
||||
return boost::report_errors(); \
|
||||
}
|
||||
{ ::test::test_list::run_tests(); return boost::report_errors(); } \
|
||||
|
||||
namespace test {
|
||||
struct registered_test_base {
|
||||
@@ -70,21 +66,6 @@ namespace test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_compiler_info() {
|
||||
#if defined(BOOST_GCC_CXX11)
|
||||
char const* cpp11 = "true";
|
||||
#else
|
||||
char const* cpp11 = "false";
|
||||
#endif
|
||||
|
||||
std::cout
|
||||
<< "Compiler: " << BOOST_COMPILER << "\n"
|
||||
<< "Library: " << BOOST_STDLIB << "\n"
|
||||
<< "C++11: " << cpp11 << "\n"
|
||||
<< "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/preprocessor/seq/for_each_product.hpp>
|
||||
@@ -95,29 +76,21 @@ namespace test {
|
||||
|
||||
// Run test with every combination of the parameters (a sequence of sequences)
|
||||
#define UNORDERED_TEST(name, parameters) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, \
|
||||
((name))((1)) parameters) \
|
||||
|
||||
#define UNORDERED_TEST_REPEAT(name, n, parameters) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, \
|
||||
((name))((n)) parameters) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name)) parameters) \
|
||||
|
||||
#define UNORDERED_TEST_OP(r, product) \
|
||||
UNORDERED_TEST_OP2( \
|
||||
BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_SEQ_ELEM(1, product), \
|
||||
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product))) \
|
||||
BOOST_PP_SEQ_HEAD(product), \
|
||||
BOOST_PP_SEQ_TAIL(product)) \
|
||||
|
||||
#define UNORDERED_TEST_OP2(name, n, params) \
|
||||
#define UNORDERED_TEST_OP2(name, params) \
|
||||
UNORDERED_AUTO_TEST( \
|
||||
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
|
||||
{ \
|
||||
for (int i = 0; i < n; ++i) \
|
||||
name BOOST_PP_SEQ_TO_TUPLE(params); \
|
||||
name BOOST_PP_SEQ_TO_TUPLE(params); \
|
||||
} \
|
||||
|
||||
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
|
||||
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem)) \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+18
-25
@@ -13,6 +13,7 @@
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include "../objects/fwd.hpp"
|
||||
#include "./metafunctions.hpp"
|
||||
#include "./helpers.hpp"
|
||||
@@ -59,46 +60,38 @@ namespace test
|
||||
values2.begin(), test::equivalent));
|
||||
}
|
||||
|
||||
template <typename X,
|
||||
bool is_set = test::is_set<X>::value,
|
||||
bool has_unique_keys = test::has_unique_keys<X>::value>
|
||||
template <typename X>
|
||||
struct ordered_base;
|
||||
|
||||
template <typename X>
|
||||
struct ordered_base<X, true, true>
|
||||
template <class V, class H, class P, class A>
|
||||
struct ordered_base<boost::unordered_set<V, H, P, A> >
|
||||
{
|
||||
typedef std::set<
|
||||
BOOST_DEDUCED_TYPENAME X::value_type,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
|
||||
typedef std::set<V,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct ordered_base<X, true, false>
|
||||
template <class V, class H, class P, class A>
|
||||
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
|
||||
{
|
||||
typedef std::multiset<
|
||||
BOOST_DEDUCED_TYPENAME X::value_type,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
|
||||
typedef std::multiset<V,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct ordered_base<X, false, true>
|
||||
template <class K, class M, class H, class P, class A>
|
||||
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
|
||||
{
|
||||
typedef std::map<
|
||||
BOOST_DEDUCED_TYPENAME X::key_type,
|
||||
BOOST_DEDUCED_TYPENAME X::mapped_type,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
|
||||
typedef std::map<K, M,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct ordered_base<X, false, false>
|
||||
template <class K, class M, class H, class P, class A>
|
||||
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
|
||||
{
|
||||
typedef std::multimap<
|
||||
BOOST_DEDUCED_TYPENAME X::key_type,
|
||||
BOOST_DEDUCED_TYPENAME X::mapped_type,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
|
||||
typedef std::multimap<K, M,
|
||||
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
|
||||
type;
|
||||
};
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace test
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, void const*)
|
||||
pointer allocate(size_type n, void const* u)
|
||||
{
|
||||
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
@@ -170,7 +170,7 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<typename... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
@@ -201,11 +201,9 @@ namespace test
|
||||
public move_allocator_base<Flags>,
|
||||
Flags
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
|
||||
template <typename U> struct rebind {
|
||||
typedef cxx11_allocator<U, Flags> other;
|
||||
};
|
||||
#endif
|
||||
|
||||
explicit cxx11_allocator(int t = 0)
|
||||
: cxx11_allocator_base<T>(t)
|
||||
@@ -253,11 +251,9 @@ namespace test
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
|
||||
template <typename U> struct rebind {
|
||||
typedef cxx11_allocator<U, Flags> other;
|
||||
};
|
||||
#endif
|
||||
|
||||
explicit cxx11_allocator(int t = 0)
|
||||
: cxx11_allocator_base<T>(t)
|
||||
|
||||
+10
-195
@@ -23,7 +23,7 @@ namespace exception
|
||||
class hash;
|
||||
class equal_to;
|
||||
template <class T> class allocator;
|
||||
object generate(object const*, random_generator);
|
||||
object generate(object const*);
|
||||
|
||||
struct true_type
|
||||
{
|
||||
@@ -101,9 +101,9 @@ namespace exception
|
||||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
|
||||
}
|
||||
|
||||
friend object generate(object const*, random_generator g) {
|
||||
friend object generate(object const*) {
|
||||
int* x = 0;
|
||||
return object(::test::generate(x, g), ::test::generate(x, g));
|
||||
return object(::test::generate(x), ::test::generate(x));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, object const& o)
|
||||
@@ -146,18 +146,14 @@ namespace exception
|
||||
UNORDERED_EPOINT("Mock hash function.");
|
||||
}
|
||||
|
||||
int result;
|
||||
switch(tag_) {
|
||||
case 1:
|
||||
result = x.tag1_;
|
||||
break;
|
||||
return x.tag1_;
|
||||
case 2:
|
||||
result = x.tag2_;
|
||||
break;
|
||||
return x.tag2_;
|
||||
default:
|
||||
result = x.tag1_ + x.tag2_;
|
||||
return x.tag1_ + x.tag2_;
|
||||
}
|
||||
return static_cast<std::size_t>(result);
|
||||
}
|
||||
|
||||
friend bool operator==(hash const& x1, hash const& x2) {
|
||||
@@ -318,7 +314,7 @@ namespace exception
|
||||
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, void const*)
|
||||
pointer allocate(size_type n, void const* u)
|
||||
{
|
||||
T* ptr = 0;
|
||||
UNORDERED_SCOPE(allocator::allocate(size_type, const_pointer)) {
|
||||
@@ -352,7 +348,7 @@ namespace exception
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
@@ -405,186 +401,6 @@ namespace exception
|
||||
//}
|
||||
return x.tag_ != y.tag_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class allocator2
|
||||
{
|
||||
public:
|
||||
int tag_;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef T const* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind { typedef allocator2<U> other; };
|
||||
|
||||
explicit allocator2(int t = 0) : tag_(t)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 default constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator2(allocator<T> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator2(allocator2 const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
~allocator2() {
|
||||
test::detail::tracker.allocator_unref();
|
||||
}
|
||||
|
||||
allocator2& operator=(allocator2 const& x) {
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 assignment operator.");
|
||||
tag_ = x.tag_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If address throws, then it can't be used in erase or the
|
||||
// destructor, which is very limiting. I need to check up on
|
||||
// this.
|
||||
|
||||
pointer address(reference r) {
|
||||
//UNORDERED_SCOPE(allocator2::address(reference)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 address function.");
|
||||
//}
|
||||
return pointer(&r);
|
||||
}
|
||||
|
||||
const_pointer address(const_reference r) {
|
||||
//UNORDERED_SCOPE(allocator2::address(const_reference)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 const address function.");
|
||||
//}
|
||||
return const_pointer(&r);
|
||||
}
|
||||
|
||||
pointer allocate(size_type n) {
|
||||
T* ptr = 0;
|
||||
UNORDERED_SCOPE(allocator2::allocate(size_type)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 allocate function.");
|
||||
|
||||
using namespace std;
|
||||
ptr = (T*) malloc(n * sizeof(T));
|
||||
if(!ptr) throw std::bad_alloc();
|
||||
}
|
||||
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
return pointer(ptr);
|
||||
|
||||
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, void const*)
|
||||
{
|
||||
T* ptr = 0;
|
||||
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 allocate function.");
|
||||
|
||||
using namespace std;
|
||||
ptr = (T*) malloc(n * sizeof(T));
|
||||
if(!ptr) throw std::bad_alloc();
|
||||
}
|
||||
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
return pointer(ptr);
|
||||
|
||||
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
void deallocate(pointer p, size_type n)
|
||||
{
|
||||
//::operator delete((void*) p);
|
||||
if(p) {
|
||||
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
|
||||
using namespace std;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void construct(pointer p, T const& t) {
|
||||
UNORDERED_SCOPE(allocator2::construct(T*, T)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 construct function.");
|
||||
new(p) T(t);
|
||||
}
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 construct function.");
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy(T* p) {
|
||||
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
|
||||
p->~T();
|
||||
}
|
||||
|
||||
size_type max_size() const {
|
||||
UNORDERED_SCOPE(allocator2::construct(pointer, T)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 max_size function.");
|
||||
}
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
typedef false_type propagate_on_container_copy_assignment;
|
||||
typedef false_type propagate_on_container_move_assignment;
|
||||
typedef false_type propagate_on_container_swap;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap(allocator2<T>& x, allocator2<T>& y)
|
||||
{
|
||||
std::swap(x.tag_, y.tag_);
|
||||
}
|
||||
|
||||
// It's pretty much impossible to write a compliant swap when these
|
||||
// two can throw. So they don't.
|
||||
|
||||
template <class T>
|
||||
inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
|
||||
{
|
||||
//UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 equality operator.");
|
||||
//}
|
||||
return x.tag_ == y.tag_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
|
||||
{
|
||||
//UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 inequality operator.");
|
||||
//}
|
||||
return x.tag_ != y.tag_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,9 +408,8 @@ namespace exception
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace test
|
||||
{
|
||||
test::exception::object generate(test::exception::object const* x,
|
||||
random_generator g) {
|
||||
return test::exception::generate(x, g);
|
||||
test::exception::object generate(test::exception::object const* x) {
|
||||
return test::exception::generate(x);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+33
-66
@@ -19,12 +19,6 @@
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
|
||||
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
|
||||
#else
|
||||
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
|
||||
#endif
|
||||
|
||||
namespace test
|
||||
{
|
||||
namespace minimal
|
||||
@@ -32,12 +26,10 @@ namespace minimal
|
||||
class destructible;
|
||||
class copy_constructible;
|
||||
class copy_constructible_equality_comparable;
|
||||
class default_assignable;
|
||||
class default_copy_constructible;
|
||||
class assignable;
|
||||
|
||||
struct ampersand_operator_used {
|
||||
ampersand_operator_used() { BOOST_TEST(false); }
|
||||
};
|
||||
struct ampersand_operator_used {};
|
||||
|
||||
template <class T> class hash;
|
||||
template <class T> class equal_to;
|
||||
@@ -56,7 +48,6 @@ namespace minimal
|
||||
public:
|
||||
destructible(constructor_param const&) {}
|
||||
~destructible() {}
|
||||
void dummy_member() const {}
|
||||
private:
|
||||
destructible(destructible const&);
|
||||
destructible& operator=(destructible const&);
|
||||
@@ -68,7 +59,6 @@ namespace minimal
|
||||
copy_constructible(constructor_param const&) {}
|
||||
copy_constructible(copy_constructible const&) {}
|
||||
~copy_constructible() {}
|
||||
void dummy_member() const {}
|
||||
private:
|
||||
copy_constructible& operator=(copy_constructible const&);
|
||||
copy_constructible() {}
|
||||
@@ -88,15 +78,11 @@ namespace minimal
|
||||
{
|
||||
}
|
||||
|
||||
void dummy_member() const {}
|
||||
private:
|
||||
copy_constructible_equality_comparable& operator=(
|
||||
copy_constructible_equality_comparable const&);
|
||||
copy_constructible_equality_comparable() {}
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
bool operator==(
|
||||
@@ -113,34 +99,28 @@ namespace minimal
|
||||
return false;
|
||||
}
|
||||
|
||||
class default_assignable
|
||||
class default_copy_constructible
|
||||
{
|
||||
public:
|
||||
default_assignable(constructor_param const&) {}
|
||||
default_copy_constructible(constructor_param const&) {}
|
||||
|
||||
default_assignable()
|
||||
default_copy_constructible()
|
||||
{
|
||||
}
|
||||
|
||||
default_assignable(default_assignable const&)
|
||||
default_copy_constructible(default_copy_constructible const&)
|
||||
{
|
||||
}
|
||||
|
||||
default_assignable& operator=(default_assignable const&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
~default_assignable()
|
||||
~default_copy_constructible()
|
||||
{
|
||||
}
|
||||
|
||||
void dummy_member() const {}
|
||||
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
private:
|
||||
default_copy_constructible& operator=(
|
||||
default_copy_constructible const&);
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
class assignable
|
||||
@@ -150,13 +130,11 @@ namespace minimal
|
||||
assignable(assignable const&) {}
|
||||
assignable& operator=(assignable const&) { return *this; }
|
||||
~assignable() {}
|
||||
void dummy_member() const {}
|
||||
|
||||
private:
|
||||
assignable() {}
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
// TODO: This messes up a concept check in the tests.
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
struct movable_init {};
|
||||
@@ -170,12 +148,11 @@ namespace minimal
|
||||
movable1() {}
|
||||
explicit movable1(movable_init) {}
|
||||
movable1(BOOST_RV_REF(movable1)) {}
|
||||
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
|
||||
movable1& operator=(BOOST_RV_REF(movable1));
|
||||
~movable1() {}
|
||||
void dummy_member() const {}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
class movable2
|
||||
{
|
||||
public:
|
||||
@@ -183,8 +160,6 @@ namespace minimal
|
||||
explicit movable2(movable_init) {}
|
||||
movable2(movable2&&) {}
|
||||
~movable2() {}
|
||||
movable2& operator=(movable2&&) { return *this; }
|
||||
void dummy_member() const {}
|
||||
private:
|
||||
movable2() {}
|
||||
movable2(movable2 const&);
|
||||
@@ -205,10 +180,8 @@ namespace minimal
|
||||
~hash() {}
|
||||
|
||||
std::size_t operator()(T const&) const { return 0; }
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -222,10 +195,8 @@ namespace minimal
|
||||
~equal_to() {}
|
||||
|
||||
bool operator()(T const&, T const&) const { return true; }
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T> class ptr;
|
||||
@@ -313,10 +284,9 @@ namespace minimal
|
||||
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
private:
|
||||
// TODO:
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -351,10 +321,9 @@ namespace minimal
|
||||
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
private:
|
||||
// TODO:
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -386,7 +355,7 @@ namespace minimal
|
||||
}
|
||||
|
||||
template <class Y>
|
||||
pointer allocate(size_type n, const_ptr<Y>)
|
||||
pointer allocate(size_type n, const_ptr<Y> u)
|
||||
{
|
||||
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
@@ -398,7 +367,7 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
@@ -414,10 +383,8 @@ namespace minimal
|
||||
#else
|
||||
private: allocator& operator=(allocator const&);
|
||||
#endif
|
||||
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
#endif
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -447,7 +414,7 @@ namespace minimal
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
//template <class U> struct rebind { typedef cxx11_allocator<U> other; };
|
||||
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
|
||||
|
||||
cxx11_allocator() {}
|
||||
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
|
||||
@@ -462,7 +429,7 @@ namespace minimal
|
||||
}
|
||||
|
||||
template <class Y>
|
||||
T* allocate(std::size_t n, const_ptr<Y>) {
|
||||
T* allocate(std::size_t n, const_ptr<Y> u) {
|
||||
return static_cast<T*>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
@@ -472,7 +439,7 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
+22
-283
@@ -18,16 +18,14 @@ namespace test
|
||||
// Note that the default hash function will work for any equal_to (but not
|
||||
// very well).
|
||||
class object;
|
||||
class movable;
|
||||
class implicitly_convertible;
|
||||
class hash;
|
||||
class less;
|
||||
class equal_to;
|
||||
template <class T> class allocator1;
|
||||
template <class T> class allocator2;
|
||||
object generate(object const*, random_generator);
|
||||
movable generate(movable const*, random_generator);
|
||||
implicitly_convertible generate(implicitly_convertible const*, random_generator);
|
||||
object generate(object const*);
|
||||
implicitly_convertible generate(implicitly_convertible const*);
|
||||
|
||||
inline void ignore_variable(void const*) {}
|
||||
|
||||
@@ -58,9 +56,9 @@ namespace test
|
||||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
|
||||
}
|
||||
|
||||
friend object generate(object const*, random_generator g) {
|
||||
friend object generate(object const*) {
|
||||
int* x = 0;
|
||||
return object(generate(x, g), generate(x, g));
|
||||
return object(generate(x), generate(x));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, object const& o)
|
||||
@@ -69,81 +67,6 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
class movable : private counted_object
|
||||
{
|
||||
friend class hash;
|
||||
friend class equal_to;
|
||||
friend class less;
|
||||
int tag1_, tag2_;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(movable)
|
||||
public:
|
||||
explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
|
||||
|
||||
movable(movable const& x) :
|
||||
counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
|
||||
{
|
||||
BOOST_TEST(x.tag1_ != -1);
|
||||
}
|
||||
|
||||
movable(BOOST_RV_REF(movable) x) :
|
||||
counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
|
||||
{
|
||||
BOOST_TEST(x.tag1_ != -1);
|
||||
x.tag1_ = -1;
|
||||
x.tag2_ = -1;
|
||||
}
|
||||
|
||||
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
|
||||
{
|
||||
BOOST_TEST(x.tag1_ != -1);
|
||||
tag1_ = x.tag1_;
|
||||
tag2_ = x.tag2_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
movable& operator=(BOOST_RV_REF(movable) x) //Move assignment
|
||||
{
|
||||
BOOST_TEST(x.tag1_ != -1);
|
||||
tag1_ = x.tag1_;
|
||||
tag2_ = x.tag2_;
|
||||
x.tag1_ = -1;
|
||||
x.tag2_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~movable() {
|
||||
tag1_ = -1;
|
||||
tag2_ = -1;
|
||||
}
|
||||
|
||||
friend bool operator==(movable const& x1, movable const& x2) {
|
||||
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
|
||||
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
|
||||
}
|
||||
|
||||
friend bool operator!=(movable const& x1, movable const& x2) {
|
||||
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
|
||||
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
|
||||
}
|
||||
|
||||
friend bool operator<(movable const& x1, movable const& x2) {
|
||||
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
|
||||
return x1.tag1_ < x2.tag1_ ||
|
||||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
|
||||
}
|
||||
|
||||
friend movable generate(movable const*, random_generator g) {
|
||||
int* x = 0;
|
||||
return movable(generate(x, g), generate(x, g));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, movable const& o)
|
||||
{
|
||||
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
|
||||
}
|
||||
};
|
||||
|
||||
class implicitly_convertible : private counted_object
|
||||
{
|
||||
int tag1_, tag2_;
|
||||
@@ -158,14 +81,9 @@ namespace test
|
||||
return object(tag1_, tag2_);
|
||||
}
|
||||
|
||||
operator movable() const
|
||||
{
|
||||
return movable(tag1_, tag2_);
|
||||
}
|
||||
|
||||
friend implicitly_convertible generate(implicitly_convertible const*, random_generator g) {
|
||||
friend implicitly_convertible generate(implicitly_convertible const*) {
|
||||
int* x = 0;
|
||||
return implicitly_convertible(generate(x, g), generate(x, g));
|
||||
return implicitly_convertible(generate(x), generate(x));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, implicitly_convertible const& o)
|
||||
@@ -174,7 +92,6 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
// Note: This is a deliberately bad hash function.
|
||||
class hash
|
||||
{
|
||||
int type_;
|
||||
@@ -182,48 +99,18 @@ namespace test
|
||||
explicit hash(int t = 0) : type_(t) {}
|
||||
|
||||
std::size_t operator()(object const& x) const {
|
||||
int result;
|
||||
switch(type_) {
|
||||
case 1:
|
||||
result = x.tag1_;
|
||||
break;
|
||||
return x.tag1_;
|
||||
case 2:
|
||||
result = x.tag2_;
|
||||
break;
|
||||
return x.tag2_;
|
||||
default:
|
||||
result = x.tag1_ + x.tag2_;
|
||||
return x.tag1_ + x.tag2_;
|
||||
}
|
||||
return static_cast<std::size_t>(result);
|
||||
}
|
||||
|
||||
std::size_t operator()(movable const& x) const {
|
||||
int result;
|
||||
switch(type_) {
|
||||
case 1:
|
||||
result = x.tag1_;
|
||||
break;
|
||||
case 2:
|
||||
result = x.tag2_;
|
||||
break;
|
||||
default:
|
||||
result = x.tag1_ + x.tag2_;
|
||||
}
|
||||
return static_cast<std::size_t>(result);
|
||||
}
|
||||
|
||||
std::size_t operator()(int x) const {
|
||||
int result;
|
||||
switch(type_) {
|
||||
case 1:
|
||||
result = x;
|
||||
break;
|
||||
case 2:
|
||||
result = x * 7;
|
||||
break;
|
||||
default:
|
||||
result = x * 256;
|
||||
}
|
||||
return static_cast<std::size_t>(result);
|
||||
return x;
|
||||
}
|
||||
|
||||
friend bool operator==(hash const& x1, hash const& x2) {
|
||||
@@ -239,10 +126,6 @@ namespace test
|
||||
return hash()(x);
|
||||
}
|
||||
|
||||
std::size_t hash_value(test::movable const& x) {
|
||||
return hash()(x);
|
||||
}
|
||||
|
||||
class less
|
||||
{
|
||||
int type_;
|
||||
@@ -260,17 +143,6 @@ namespace test
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(movable const& x1, movable const& x2) const {
|
||||
switch(type_) {
|
||||
case 1:
|
||||
return x1.tag1_ < x2.tag1_;
|
||||
case 2:
|
||||
return x1.tag2_ < x2.tag2_;
|
||||
default:
|
||||
return x1 < x2;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t operator()(int x1, int x2) const {
|
||||
return x1 < x2;
|
||||
}
|
||||
@@ -297,17 +169,6 @@ namespace test
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(movable const& x1, movable const& x2) const {
|
||||
switch(type_) {
|
||||
case 1:
|
||||
return x1.tag1_ == x2.tag1_;
|
||||
case 2:
|
||||
return x1.tag2_ == x2.tag2_;
|
||||
default:
|
||||
return x1 == x2;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t operator()(int x1, int x2) const {
|
||||
return x1 == x2;
|
||||
}
|
||||
@@ -325,8 +186,9 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
// allocator1 and allocator2 are pretty similar.
|
||||
// allocator1 only has the old fashioned 'construct' method and has
|
||||
// a few less typedefs. allocator2 uses a custom pointer class.
|
||||
// a few less typedefs
|
||||
|
||||
template <class T>
|
||||
class allocator1
|
||||
@@ -366,7 +228,7 @@ namespace test
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T* allocate(std::size_t n, void const*)
|
||||
T* allocate(std::size_t n, void const* u)
|
||||
{
|
||||
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
@@ -411,127 +273,6 @@ namespace test
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> class ptr;
|
||||
template <class T> class const_ptr;
|
||||
|
||||
struct void_ptr
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename T>
|
||||
friend class ptr;
|
||||
private:
|
||||
#endif
|
||||
|
||||
void* ptr_;
|
||||
|
||||
public:
|
||||
void_ptr() : ptr_(0) {}
|
||||
|
||||
template <typename T>
|
||||
explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
|
||||
|
||||
// I'm not using the safe bool idiom because the containers should be
|
||||
// able to cope with bool conversions.
|
||||
operator bool() const { return !!ptr_; }
|
||||
|
||||
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
|
||||
};
|
||||
|
||||
class void_const_ptr
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename T>
|
||||
friend class const_ptr;
|
||||
private:
|
||||
#endif
|
||||
|
||||
void* ptr_;
|
||||
|
||||
public:
|
||||
void_const_ptr() : ptr_(0) {}
|
||||
|
||||
template <typename T>
|
||||
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) {}
|
||||
|
||||
// I'm not using the safe bool idiom because the containers should be
|
||||
// able to cope with bool conversions.
|
||||
operator bool() const { return !!ptr_; }
|
||||
|
||||
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ptr
|
||||
{
|
||||
friend class allocator2<T>;
|
||||
friend class const_ptr<T>;
|
||||
friend struct void_ptr;
|
||||
|
||||
T* ptr_;
|
||||
|
||||
ptr(T* x) : ptr_(x) {}
|
||||
public:
|
||||
ptr() : ptr_(0) {}
|
||||
explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {}
|
||||
|
||||
T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
ptr& operator++() { ++ptr_; return *this; }
|
||||
ptr operator++(int) { ptr tmp(*this); ++ptr_; return tmp; }
|
||||
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
|
||||
friend ptr operator+(std::ptrdiff_t s, ptr p)
|
||||
{ return ptr<T>(s + p.ptr_); }
|
||||
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
|
||||
bool operator!() const { return !ptr_; }
|
||||
|
||||
// I'm not using the safe bool idiom because the containers should be
|
||||
// able to cope with bool conversions.
|
||||
operator bool() const { return !!ptr_; }
|
||||
|
||||
bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
|
||||
bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
|
||||
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class const_ptr
|
||||
{
|
||||
friend class allocator2<T>;
|
||||
friend struct const_void_ptr;
|
||||
|
||||
T const* ptr_;
|
||||
|
||||
const_ptr(T const* ptr) : ptr_(ptr) {}
|
||||
public:
|
||||
const_ptr() : ptr_(0) {}
|
||||
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
|
||||
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
|
||||
|
||||
T const& operator*() const { return *ptr_; }
|
||||
T const* operator->() const { return ptr_; }
|
||||
const_ptr& operator++() { ++ptr_; return *this; }
|
||||
const_ptr operator++(int) { const_ptr tmp(*this); ++ptr_; return tmp; }
|
||||
const_ptr operator+(std::ptrdiff_t s) const
|
||||
{ return const_ptr(ptr_ + s); }
|
||||
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
|
||||
{ return ptr<T>(s + p.ptr_); }
|
||||
T const& operator[](int s) const { return ptr_[s]; }
|
||||
bool operator!() const { return !ptr_; }
|
||||
operator bool() const { return !!ptr_; }
|
||||
|
||||
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
|
||||
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
|
||||
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class allocator2
|
||||
{
|
||||
@@ -544,10 +285,8 @@ namespace test
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef void_ptr void_pointer;
|
||||
typedef void_const_ptr const_void_pointer;
|
||||
typedef ptr<T> pointer;
|
||||
typedef const_ptr<T> const_pointer;
|
||||
typedef T* pointer;
|
||||
typedef T const* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T value_type;
|
||||
@@ -587,12 +326,12 @@ namespace test
|
||||
}
|
||||
|
||||
pointer allocate(size_type n) {
|
||||
pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
detail::tracker.track_allocate((void*) p.ptr_, n, sizeof(T), tag_);
|
||||
return p;
|
||||
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, void const*)
|
||||
pointer allocate(size_type n, void const* u)
|
||||
{
|
||||
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
@@ -601,8 +340,8 @@ namespace test
|
||||
|
||||
void deallocate(pointer p, size_type n)
|
||||
{
|
||||
detail::tracker.track_deallocate((void*) p.ptr_, n, sizeof(T), tag_);
|
||||
::operator delete((void*) p.ptr_);
|
||||
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
|
||||
::operator delete((void*) p);
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t) {
|
||||
@@ -610,7 +349,7 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
# Copyright 2006-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)
|
||||
|
||||
import testing ;
|
||||
|
||||
project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
# Would be nice to define -Wundef, but I'm getting warnings from
|
||||
# Boost.Preprocessor on trunk.
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
|
||||
#<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
;
|
||||
|
||||
test-suite unordered
|
||||
:
|
||||
[ run fwd_set_test.cpp ]
|
||||
[ run fwd_map_test.cpp ]
|
||||
[ run allocator_traits.cpp ]
|
||||
[ run minimal_allocator.cpp ]
|
||||
[ run compile_set.cpp ]
|
||||
[ run compile_map.cpp ]
|
||||
[ run link_test_1.cpp link_test_2.cpp ]
|
||||
[ run incomplete_test.cpp ]
|
||||
[ run simple_tests.cpp ]
|
||||
[ run equivalent_keys_tests.cpp ]
|
||||
[ run constructor_tests.cpp ]
|
||||
[ run copy_tests.cpp ]
|
||||
[ run move_tests.cpp ]
|
||||
[ run assign_tests.cpp ]
|
||||
[ run insert_tests.cpp ]
|
||||
[ run insert_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
: insert_deprecated ]
|
||||
[ run insert_stable_tests.cpp ]
|
||||
[ run unnecessary_copy_tests.cpp ]
|
||||
[ run erase_tests.cpp ]
|
||||
[ run erase_equiv_tests.cpp ]
|
||||
[ run find_tests.cpp ]
|
||||
[ run at_tests.cpp ]
|
||||
[ run bucket_tests.cpp ]
|
||||
[ run load_factor_tests.cpp ]
|
||||
[ run rehash_tests.cpp ]
|
||||
[ run equality_tests.cpp ]
|
||||
[ run equality_deprecated.cpp ]
|
||||
[ run swap_tests.cpp ]
|
||||
|
||||
[ run compile_set.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_set ]
|
||||
[ run compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_map ]
|
||||
[ run copy_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_copy ]
|
||||
[ run move_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_move ]
|
||||
[ run assign_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_assign ]
|
||||
;
|
||||
@@ -22,9 +22,9 @@
|
||||
T const* address(T const& r) { return &r; } \
|
||||
T* allocate(std::size_t n) \
|
||||
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
|
||||
T* allocate(std::size_t n, void const*) \
|
||||
T* allocate(std::size_t n, void const* u) \
|
||||
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
|
||||
void deallocate(T* p, std::size_t) { ::operator delete((void*) p); } \
|
||||
void deallocate(T* p, std::size_t n) { ::operator delete((void*) p); } \
|
||||
void construct(T* p, T const& t) { new(p) T(t); } \
|
||||
void destroy(T* p) { p->~T(); } \
|
||||
std::size_t max_size() const \
|
||||
@@ -44,9 +44,9 @@
|
||||
const_pointer address(T const& r) { return &r; } \
|
||||
pointer allocate(std::size_t n) \
|
||||
{ return pointer(::operator new(n * sizeof(T))); } \
|
||||
pointer allocate(std::size_t n, void const*) \
|
||||
pointer allocate(std::size_t n, void const* u) \
|
||||
{ return pointer(::operator new(n * sizeof(T))); } \
|
||||
void deallocate(pointer p, std::size_t) \
|
||||
void deallocate(pointer p, std::size_t n) \
|
||||
{ ::operator delete((void*) p); } \
|
||||
void construct(T* p, T const& t) { new(p) T(t); } \
|
||||
void destroy(T* p) { p->~T(); } \
|
||||
|
||||
@@ -25,7 +25,8 @@ namespace assign_tests {
|
||||
test::seed_t initialize_seed(96785);
|
||||
|
||||
template <class T>
|
||||
void assign_tests1(T*, test::random_generator generator)
|
||||
void assign_tests1(T*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf;
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq;
|
||||
@@ -62,12 +63,12 @@ void assign_tests1(T*, test::random_generator generator)
|
||||
tracker.compare(y);
|
||||
BOOST_TEST(x.max_load_factor() == mlf);
|
||||
BOOST_TEST(y.max_load_factor() == mlf);
|
||||
BOOST_TEST(y.load_factor() <= y.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void assign_tests2(T*, test::random_generator generator)
|
||||
void assign_tests2(T*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
|
||||
@@ -77,21 +78,7 @@ void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
std::cerr<<"assign_tests2.0 - empty container\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x1(0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
test::check_container(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
std::cerr<<"assign_tests2.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
@@ -100,31 +87,9 @@ void assign_tests2(T*, test::random_generator generator)
|
||||
T x1(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
test::check_container(x1, v);
|
||||
test::check_container(x2, v);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.1a\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(0, generator);
|
||||
test::random_values<T> v2(1000, generator);
|
||||
T x1(0, hf2, eq2);
|
||||
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.2\n";
|
||||
@@ -145,55 +110,7 @@ void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.3\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(100, generator), v2(1000, generator);
|
||||
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
|
||||
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
if (allocator_type::is_propagate_on_assign) {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.4\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(1000, generator), v2(100, generator);
|
||||
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
|
||||
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
if (allocator_type::is_propagate_on_assign) {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +167,6 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
template <typename T>
|
||||
bool is_propagate(T*)
|
||||
@@ -271,7 +187,7 @@ UNORDERED_TEST(assign_tests1, (
|
||||
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
|
||||
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(assign_tests2, (
|
||||
@@ -279,7 +195,7 @@ UNORDERED_TEST(assign_tests2, (
|
||||
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
|
||||
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
@@ -16,6 +16,7 @@ UNORDERED_AUTO_TEST(at_tests) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
|
||||
|
||||
boost::unordered_map<std::string, int> x;
|
||||
typedef boost::unordered_map<std::string, int>::iterator iterator;
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace bucket_tests {
|
||||
test::seed_t initialize_seed(54635);
|
||||
|
||||
template <class X>
|
||||
void tests(X*, test::random_generator generator)
|
||||
void tests(X* = 0, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -34,10 +34,8 @@ void tests(X*, test::random_generator generator)
|
||||
|
||||
X x(v.begin(), v.end());
|
||||
|
||||
BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
|
||||
if (!(x.bucket_count() <= x.max_bucket_count())) {
|
||||
std::cerr<<x.bucket_count()<<"<="<<x.max_bucket_count()<<"\n";
|
||||
}
|
||||
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
|
||||
it = v.begin(), end = v.end(); it != end; ++it)
|
||||
@@ -45,7 +43,7 @@ void tests(X*, test::random_generator generator)
|
||||
size_type bucket = x.bucket(test::get_key<X>(*it));
|
||||
|
||||
BOOST_TEST(bucket < x.bucket_count());
|
||||
if(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
|
||||
@@ -87,14 +85,7 @@ boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator2<test::object> >* test_multimap;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(tests,
|
||||
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
UNORDERED_TEST(tests, ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)))
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,21 +24,21 @@ template class boost::unordered_map<
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<std::pair<int const, int> > >;
|
||||
template class boost::unordered_multimap<
|
||||
int const,
|
||||
int const,
|
||||
int,
|
||||
int,
|
||||
boost::hash<int>,
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<std::pair<int const, int> > >;
|
||||
|
||||
template class boost::unordered_map<
|
||||
test::minimal::assignable const,
|
||||
test::minimal::default_assignable const,
|
||||
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::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
@@ -48,7 +48,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::assignable> value_type;
|
||||
test::minimal::copy_constructible> value_type;
|
||||
value_type value(x, x);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
@@ -62,7 +62,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > map;
|
||||
@@ -82,7 +82,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > multimap;
|
||||
@@ -95,7 +95,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
UNORDERED_AUTO_TEST(equality_tests) {
|
||||
typedef std::pair<
|
||||
test::minimal::copy_constructible_equality_comparable const,
|
||||
test::minimal::copy_constructible_equality_comparable> value_type;
|
||||
test::minimal::copy_constructible> value_type;
|
||||
|
||||
boost::unordered_map<int, int> int_map;
|
||||
|
||||
@@ -187,47 +187,45 @@ UNORDERED_AUTO_TEST(test2)
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::assignable> map_value_type;
|
||||
map_value_type map_value(assignable, assignable);
|
||||
test::minimal::copy_constructible> map_value_type;
|
||||
map_value_type map_value(assignable, copy_constructible);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > map;
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, assignable, assignable);
|
||||
unordered_map_test(map, assignable, copy_constructible);
|
||||
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
|
||||
unordered_map_member_test(map, map_value);
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::default_assignable,
|
||||
test::minimal::default_copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > map2;
|
||||
|
||||
test::minimal::default_assignable default_assignable;
|
||||
test::minimal::default_copy_constructible default_copy_constructible;
|
||||
|
||||
unordered_map_functions(map2, assignable, default_assignable);
|
||||
unordered_map_functions(map2, assignable, default_copy_constructible);
|
||||
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > multimap;
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, assignable, assignable);
|
||||
unordered_map_test(multimap, assignable, copy_constructible);
|
||||
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
|
||||
unordered_map_member_test(multimap, map_value);
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -23,13 +23,13 @@ template class boost::unordered_set<
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multiset<
|
||||
int const,
|
||||
int,
|
||||
boost::hash<int>,
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
|
||||
template class boost::unordered_set<
|
||||
test::minimal::assignable const,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
@@ -183,7 +183,6 @@ UNORDERED_AUTO_TEST(test2)
|
||||
unordered_unique_test(set, assignable);
|
||||
unordered_set_test(set, assignable);
|
||||
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
|
||||
unordered_set_member_test(set, assignable);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
@@ -196,7 +195,6 @@ UNORDERED_AUTO_TEST(test2)
|
||||
unordered_equivalent_test(multiset, assignable);
|
||||
unordered_set_test(multiset, assignable);
|
||||
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
|
||||
unordered_set_member_test(multiset, assignable);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(movable1_tests)
|
||||
|
||||
@@ -89,9 +89,8 @@ void container_test(X& r, T const&)
|
||||
|
||||
// size_type can represent any non-negative value type of difference_type
|
||||
// I'm not sure about either of these tests...
|
||||
size_type max_diff = static_cast<size_type>(
|
||||
(std::numeric_limits<difference_type>::max)());
|
||||
difference_type converted_diff(static_cast<difference_type>(max_diff));
|
||||
size_type max_diff((std::numeric_limits<difference_type>::max)());
|
||||
difference_type converted_diff(max_diff);
|
||||
BOOST_TEST((std::numeric_limits<difference_type>::max)()
|
||||
== converted_diff);
|
||||
|
||||
@@ -101,18 +100,7 @@ void container_test(X& r, T const&)
|
||||
static_cast<comparison_type>(
|
||||
(std::numeric_limits<difference_type>::max)()));
|
||||
|
||||
// Constructors
|
||||
|
||||
// I don't test the runtime post-conditions here.
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
// It isn't specified in the container requirements that the no argument
|
||||
// constructor is implicit, but it is defined that way in the concrete
|
||||
// container specification.
|
||||
X u_implicit = {};
|
||||
sink(u_implicit);
|
||||
#endif
|
||||
|
||||
X u;
|
||||
BOOST_TEST(u.size() == 0);
|
||||
BOOST_TEST(X().size() == 0);
|
||||
@@ -123,8 +111,6 @@ void container_test(X& r, T const&)
|
||||
sink(X(a));
|
||||
X u2(a);
|
||||
X u3 = a;
|
||||
X u4(rvalue(a_const));
|
||||
X u5 = rvalue(a_const);
|
||||
|
||||
a.swap(b);
|
||||
boost::swap(a, b);
|
||||
@@ -134,25 +120,12 @@ void container_test(X& r, T const&)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
|
||||
allocator_type m = a.get_allocator();
|
||||
sink(X(m));
|
||||
X c(m);
|
||||
sink(X(a_const, m));
|
||||
X c2(a_const, m);
|
||||
sink(X(rvalue(a_const), m));
|
||||
X c3(rvalue(a_const), m);
|
||||
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
sink(u);
|
||||
sink(u2);
|
||||
sink(u3);
|
||||
sink(u4);
|
||||
sink(u5);
|
||||
sink(c);
|
||||
sink(c2);
|
||||
sink(c3);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
@@ -164,7 +137,7 @@ void unordered_destructible_test(X&)
|
||||
|
||||
X x1;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
X x2(rvalue_default<X>());
|
||||
X x3 = rvalue_default<X>();
|
||||
// This can only be done if propagate_on_container_move_assignment::value
|
||||
@@ -175,7 +148,6 @@ void unordered_destructible_test(X&)
|
||||
X* ptr = new X();
|
||||
X& a1 = *ptr;
|
||||
(&a1)->~X();
|
||||
::operator delete((void*)(&a1));
|
||||
|
||||
X a,b;
|
||||
X const a_const;
|
||||
@@ -208,28 +180,6 @@ void unordered_set_test(X&, Key const&)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
|
||||
|
||||
// iterator pointer / const_pointer_type
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<iterator>::type iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<const_iterator>::type
|
||||
const_iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<const_local_iterator>::type
|
||||
const_local_iterator_pointer;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
|
||||
}
|
||||
|
||||
template <class X, class Key, class T>
|
||||
@@ -241,30 +191,6 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<value_type, std::pair<key_type const, T> >::value));
|
||||
|
||||
// iterator pointer / const_pointer_type
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<iterator>::type iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<const_iterator>::type
|
||||
const_iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_pointer<const_local_iterator>::type
|
||||
const_local_iterator_pointer;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
|
||||
|
||||
// Calling functions
|
||||
|
||||
r.insert(std::pair<Key const, T>(k, v));
|
||||
|
||||
Key k_lvalue(k);
|
||||
@@ -273,9 +199,6 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
r.emplace(k, v);
|
||||
r.emplace(k_lvalue, v_lvalue);
|
||||
r.emplace(rvalue(k), rvalue(v));
|
||||
|
||||
r.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(k), boost::make_tuple(v));
|
||||
}
|
||||
|
||||
template <class X>
|
||||
@@ -384,7 +307,6 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::iterator_reference<const_local_iterator>::type
|
||||
const_local_iterator_reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
|
||||
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
|
||||
@@ -417,13 +339,8 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
|
||||
const_iterator_reference>::value));
|
||||
|
||||
X a;
|
||||
allocator_type m = a.get_allocator();
|
||||
|
||||
// Constructors
|
||||
|
||||
X(10, hf, eq);
|
||||
X a1(10, hf, eq);
|
||||
X a(10, hf, eq);
|
||||
X(10, hf);
|
||||
X a2(10, hf);
|
||||
X(10);
|
||||
@@ -431,15 +348,6 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
X();
|
||||
X a4;
|
||||
|
||||
X(10, hf, eq, m);
|
||||
X a1a(10, hf, eq, m);
|
||||
X(10, hf, m);
|
||||
X a2a(10, hf, m);
|
||||
X(10, m);
|
||||
X a3a(10, m);
|
||||
(X(m));
|
||||
X a4a(m);
|
||||
|
||||
test::check_return_type<size_type>::equals(a.erase(k));
|
||||
|
||||
const_iterator q1 = a.cbegin(), q2 = a.cend();
|
||||
@@ -482,14 +390,9 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
sink(a);
|
||||
sink(a1);
|
||||
sink(a2);
|
||||
sink(a3);
|
||||
sink(a4);
|
||||
sink(a1a);
|
||||
sink(a2a);
|
||||
sink(a3a);
|
||||
sink(a4a);
|
||||
}
|
||||
|
||||
template <class X, class Key, class T, class Hash, class Pred>
|
||||
@@ -499,17 +402,14 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
|
||||
X a;
|
||||
allocator_type m = a.get_allocator();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
|
||||
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
|
||||
|
||||
// Constructors
|
||||
|
||||
X(i, j, 10, hf, eq);
|
||||
|
||||
X a5(i, j, 10, hf, eq);
|
||||
X(i, j, 10, hf);
|
||||
X a6(i, j, 10, hf);
|
||||
@@ -518,55 +418,17 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
X(i, j);
|
||||
X a8(i, j);
|
||||
|
||||
X(i, j, 10, hf, eq, m);
|
||||
X a5a(i, j, 10, hf, eq, m);
|
||||
X(i, j, 10, hf, m);
|
||||
X a6a(i, j, 10, hf, m);
|
||||
X(i, j, 10, m);
|
||||
X a7a(i, j, 10, m);
|
||||
|
||||
// Not specified for some reason (maybe ambiguity with another constructor?)
|
||||
//X(i, j, m);
|
||||
//X a8a(i, j, m);
|
||||
//sink(a8a);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
std::size_t min_buckets = 10;
|
||||
X({t});
|
||||
X({t}, min_buckets);
|
||||
X({t}, min_buckets, hf);
|
||||
X({t}, min_buckets, hf, eq);
|
||||
//X({t}, m);
|
||||
X({t}, min_buckets, m);
|
||||
X({t}, min_buckets, hf, m);
|
||||
X({t}, min_buckets, hf, eq, m);
|
||||
#endif
|
||||
|
||||
X const b;
|
||||
sink(X(b));
|
||||
X a9(b);
|
||||
a = b;
|
||||
|
||||
sink(X(b, m));
|
||||
X a9a(b, m);
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
|
||||
|
||||
a.insert(i, j);
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
std::initializer_list<T> list = {t};
|
||||
a.insert(list);
|
||||
a.insert({t,t,t});
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
||||
a.insert({});
|
||||
a.insert({t});
|
||||
a.insert({t,t});
|
||||
#endif
|
||||
#endif
|
||||
|
||||
X a10;
|
||||
a10.insert(t);
|
||||
@@ -581,10 +443,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
sink(a7);
|
||||
sink(a8);
|
||||
sink(a9);
|
||||
sink(a5a);
|
||||
sink(a6a);
|
||||
sink(a7a);
|
||||
sink(a9a);
|
||||
}
|
||||
|
||||
template <class X, class Key, class T, class Hash, class Pred>
|
||||
@@ -594,23 +452,17 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
X x1(rvalue_default<X>());
|
||||
X x2(boost::move(x1));
|
||||
x1 = rvalue_default<X>();
|
||||
x2 = boost::move(x1);
|
||||
#endif
|
||||
|
||||
X a;
|
||||
allocator_type m = a.get_allocator();
|
||||
|
||||
test::minimal::constructor_param* i = 0;
|
||||
test::minimal::constructor_param* j = 0;
|
||||
|
||||
// Constructors
|
||||
|
||||
X(i, j, 10, hf, eq);
|
||||
X a5(i, j, 10, hf, eq);
|
||||
X(i, j, 10, hf);
|
||||
@@ -620,17 +472,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
||||
X(i, j);
|
||||
X a8(i, j);
|
||||
|
||||
X(i, j, 10, hf, eq, m);
|
||||
X a5a(i, j, 10, hf, eq, m);
|
||||
X(i, j, 10, hf, m);
|
||||
X a6a(i, j, 10, hf, m);
|
||||
X(i, j, 10, m);
|
||||
X a7a(i, j, 10, m);
|
||||
|
||||
// Not specified for some reason (maybe ambiguity with another constructor?)
|
||||
//X(i, j, m);
|
||||
//X a8a(i, j, m);
|
||||
//sink(a8a);
|
||||
X a;
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
|
||||
@@ -664,28 +506,5 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
||||
sink(a6);
|
||||
sink(a7);
|
||||
sink(a8);
|
||||
sink(a5a);
|
||||
sink(a6a);
|
||||
sink(a7a);
|
||||
sink(a10);
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
void unordered_set_member_test(X& x, T& t)
|
||||
{
|
||||
X x1(x);
|
||||
x1.insert(t);
|
||||
x1.begin()->dummy_member();
|
||||
x1.cbegin()->dummy_member();
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
void unordered_map_member_test(X& x, T& t)
|
||||
{
|
||||
X x1(x);
|
||||
x1.insert(t);
|
||||
x1.begin()->first.dummy_member();
|
||||
x1.cbegin()->first.dummy_member();
|
||||
x1.begin()->second.dummy_member();
|
||||
x1.cbegin()->second.dummy_member();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace constructor_tests {
|
||||
test::seed_t initialize_seed(356730);
|
||||
|
||||
template <class T>
|
||||
void constructor_tests1(T*, test::random_generator generator)
|
||||
void constructor_tests1(T*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf;
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq;
|
||||
@@ -172,7 +173,8 @@ void constructor_tests1(T*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void constructor_tests2(T*, test::random_generator const& generator)
|
||||
void constructor_tests2(T*,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf;
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
|
||||
@@ -381,7 +383,8 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void map_constructor_test(T*, test::random_generator const& generator)
|
||||
void map_constructor_test(T* = 0,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"map_constructor_test\n";
|
||||
|
||||
@@ -418,21 +421,19 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(constructor_tests1,
|
||||
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(constructor_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(map_constructor_test,
|
||||
((test_map_std_alloc)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
@@ -22,7 +22,8 @@ namespace copy_tests
|
||||
{
|
||||
|
||||
template <class T>
|
||||
void copy_construct_tests1(T*, test::random_generator const& generator)
|
||||
void copy_construct_tests1(T*,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
@@ -81,8 +82,11 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void copy_construct_tests2(T*, test::random_generator const& generator)
|
||||
void copy_construct_tests2(T* ptr,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
copy_construct_tests1(ptr);
|
||||
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
|
||||
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
|
||||
@@ -198,14 +202,12 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(copy_construct_tests1, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
|
||||
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(copy_construct_tests2, (
|
||||
@@ -213,7 +215,7 @@ UNORDERED_TEST(copy_construct_tests2, (
|
||||
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
|
||||
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,436 +0,0 @@
|
||||
//
|
||||
// Copyright 2016 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 "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/functional/hash/hash.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/count.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
// Test that various emplace methods work with different numbers of
|
||||
// arguments.
|
||||
|
||||
namespace emplace_tests {
|
||||
// Constructible with 2 to 10 arguments
|
||||
struct emplace_value : private test::counted_object {
|
||||
typedef int A0;
|
||||
typedef std::string A1;
|
||||
typedef char A2;
|
||||
typedef int A3;
|
||||
typedef int A4;
|
||||
typedef int A5;
|
||||
typedef int A6;
|
||||
typedef int A7;
|
||||
typedef int A8;
|
||||
typedef int A9;
|
||||
|
||||
int arg_count;
|
||||
|
||||
A0 a0;
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
A6 a6;
|
||||
A7 a7;
|
||||
A8 a8;
|
||||
A9 a9;
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1) :
|
||||
arg_count(2),
|
||||
a0(b0), a1(b1) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2) :
|
||||
arg_count(3),
|
||||
a0(b0), a1(b1), a2(b2) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3) :
|
||||
arg_count(4),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4) :
|
||||
arg_count(5),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4, A5 const& b5) :
|
||||
arg_count(6),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
|
||||
a5(b5) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4, A5 const& b5, A6 const& b6) :
|
||||
arg_count(7),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
|
||||
a5(b5), a6(b6) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7) :
|
||||
arg_count(8),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
|
||||
a5(b5), a6(b6), a7(b7) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7,
|
||||
A8 const& b8) :
|
||||
arg_count(9),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
|
||||
a5(b5), a6(b6), a7(b7), a8(b8) {}
|
||||
|
||||
emplace_value(
|
||||
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
|
||||
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7,
|
||||
A8 const& b8, A9 const& b9) :
|
||||
arg_count(10),
|
||||
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
|
||||
a5(b5), a6(b6), a7(b7), a8(b8), a9(b9) {}
|
||||
|
||||
|
||||
friend std::size_t hash_value(emplace_value const& x) {
|
||||
std::size_t r1 = 23894278u;
|
||||
if (x.arg_count >= 1) boost::hash_combine(r1, x.a0);
|
||||
if (x.arg_count >= 2) boost::hash_combine(r1, x.a1);
|
||||
if (x.arg_count >= 3) boost::hash_combine(r1, x.a2);
|
||||
if (x.arg_count >= 4) boost::hash_combine(r1, x.a3);
|
||||
if (x.arg_count >= 5) boost::hash_combine(r1, x.a4);
|
||||
if (x.arg_count >= 6) boost::hash_combine(r1, x.a5);
|
||||
if (x.arg_count >= 7) boost::hash_combine(r1, x.a6);
|
||||
if (x.arg_count >= 8) boost::hash_combine(r1, x.a7);
|
||||
if (x.arg_count >= 9) boost::hash_combine(r1, x.a8);
|
||||
if (x.arg_count >= 10) boost::hash_combine(r1, x.a9);
|
||||
return r1;
|
||||
}
|
||||
|
||||
friend bool operator==(emplace_value const& x, emplace_value const& y) {
|
||||
if (x.arg_count != y.arg_count) { return false; }
|
||||
if (x.arg_count >= 1 && x.a0 != y.a0) { return false; }
|
||||
if (x.arg_count >= 2 && x.a1 != y.a1) { return false; }
|
||||
if (x.arg_count >= 3 && x.a2 != y.a2) { return false; }
|
||||
if (x.arg_count >= 4 && x.a3 != y.a3) { return false; }
|
||||
if (x.arg_count >= 5 && x.a4 != y.a4) { return false; }
|
||||
if (x.arg_count >= 6 && x.a5 != y.a5) { return false; }
|
||||
if (x.arg_count >= 7 && x.a6 != y.a6) { return false; }
|
||||
if (x.arg_count >= 8 && x.a7 != y.a7) { return false; }
|
||||
if (x.arg_count >= 9 && x.a8 != y.a8) { return false; }
|
||||
if (x.arg_count >= 10 && x.a9 != y.a9) { return false; }
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
emplace_value();
|
||||
emplace_value(emplace_value const&);
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(emplace_set) {
|
||||
test::check_instances check_;
|
||||
|
||||
typedef boost::unordered_set<emplace_value,
|
||||
boost::hash<emplace_value> > container;
|
||||
typedef container::iterator iterator;
|
||||
typedef std::pair<iterator, bool> return_type;
|
||||
container x(10);
|
||||
iterator i1;
|
||||
return_type r1,r2;
|
||||
|
||||
// 2 args
|
||||
|
||||
emplace_value v1(10, "x");
|
||||
r1 = x.emplace(10, std::string("x"));
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST(r1.second);
|
||||
BOOST_TEST(*r1.first == v1);
|
||||
BOOST_TEST(r1.first == x.find(v1));
|
||||
BOOST_TEST_EQ(check_.instances(), 2);
|
||||
BOOST_TEST_EQ(check_.constructions(), 2);
|
||||
|
||||
// 3 args
|
||||
|
||||
emplace_value v2(3, "foo", 'a');
|
||||
r1 = x.emplace(3, "foo", 'a');
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST(r1.second);
|
||||
BOOST_TEST(*r1.first == v2);
|
||||
BOOST_TEST(r1.first == x.find(v2));
|
||||
BOOST_TEST_EQ(check_.instances(), 4);
|
||||
BOOST_TEST_EQ(check_.constructions(), 4);
|
||||
|
||||
// 7 args with hint + duplicate
|
||||
|
||||
emplace_value v3(25, "something", 'z', 4, 5, 6, 7);
|
||||
i1 = x.emplace_hint(r1.first, 25, "something", 'z', 4, 5, 6, 7);
|
||||
BOOST_TEST_EQ(x.size(), 3u);
|
||||
BOOST_TEST(*i1 == v3);
|
||||
BOOST_TEST(i1 == x.find(v3));
|
||||
BOOST_TEST_EQ(check_.instances(), 6);
|
||||
BOOST_TEST_EQ(check_.constructions(), 6);
|
||||
|
||||
r2 = x.emplace(25, "something", 'z', 4, 5, 6, 7);
|
||||
BOOST_TEST_EQ(x.size(), 3u);
|
||||
BOOST_TEST(!r2.second);
|
||||
BOOST_TEST(i1 == r2.first);
|
||||
// The container has to construct an object in order to check
|
||||
// whether it can emplace, so there's an extra cosntruction
|
||||
// here.
|
||||
BOOST_TEST_EQ(check_.instances(), 6);
|
||||
BOOST_TEST_EQ(check_.constructions(), 7);
|
||||
|
||||
// 10 args + hint duplicate
|
||||
|
||||
std::string s1;
|
||||
emplace_value v4(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10);
|
||||
r1 = x.emplace(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10);
|
||||
BOOST_TEST_EQ(x.size(), 4u);
|
||||
BOOST_TEST(r1.second);
|
||||
BOOST_TEST(*r1.first == v4);
|
||||
BOOST_TEST(r1.first == x.find(v4));
|
||||
BOOST_TEST_EQ(check_.instances(), 8);
|
||||
BOOST_TEST_EQ(check_.constructions(), 9);
|
||||
|
||||
BOOST_TEST(r1.first ==
|
||||
x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
|
||||
BOOST_TEST(r1.first ==
|
||||
x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
|
||||
BOOST_TEST(r1.first ==
|
||||
x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
|
||||
BOOST_TEST_EQ(check_.instances(), 8);
|
||||
BOOST_TEST_EQ(check_.constructions(), 12);
|
||||
|
||||
BOOST_TEST_EQ(x.size(), 4u);
|
||||
BOOST_TEST(x.count(v1) == 1);
|
||||
BOOST_TEST(x.count(v2) == 1);
|
||||
BOOST_TEST(x.count(v3) == 1);
|
||||
BOOST_TEST(x.count(v4) == 1);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(emplace_multiset) {
|
||||
test::check_instances check_;
|
||||
|
||||
typedef boost::unordered_multiset<emplace_value,
|
||||
boost::hash<emplace_value> > container;
|
||||
typedef container::iterator iterator;
|
||||
container x(10);
|
||||
iterator i1, i2;
|
||||
|
||||
// 2 args.
|
||||
|
||||
emplace_value v1(10, "x");
|
||||
i1 = x.emplace(10, std::string("x"));
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST(i1 == x.find(v1));
|
||||
BOOST_TEST_EQ(check_.instances(), 2);
|
||||
BOOST_TEST_EQ(check_.constructions(), 2);
|
||||
|
||||
// 4 args + duplicate
|
||||
|
||||
emplace_value v2(4, "foo", 'a', 15);
|
||||
i1 = x.emplace(4, "foo", 'a', 15);
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST(i1 == x.find(v2));
|
||||
BOOST_TEST_EQ(check_.instances(), 4);
|
||||
BOOST_TEST_EQ(check_.constructions(), 4);
|
||||
|
||||
i2 = x.emplace(4, "foo", 'a', 15);
|
||||
BOOST_TEST_EQ(x.size(), 3u);
|
||||
BOOST_TEST(i1 != i2);
|
||||
BOOST_TEST(*i1 == *i2);
|
||||
BOOST_TEST(x.count(*i1) == 2);
|
||||
BOOST_TEST_EQ(check_.instances(), 5);
|
||||
BOOST_TEST_EQ(check_.constructions(), 5);
|
||||
|
||||
// 7 args + duplicate using hint.
|
||||
|
||||
emplace_value v3(7, "", 'z', 4, 5, 6, 7);
|
||||
i1 = x.emplace(7, "", 'z', 4, 5, 6, 7);
|
||||
BOOST_TEST_EQ(x.size(), 4u);
|
||||
BOOST_TEST_EQ(i1->a2, 'z');
|
||||
BOOST_TEST(x.count(*i1) == 1);
|
||||
BOOST_TEST(i1 == x.find(v3));
|
||||
BOOST_TEST_EQ(check_.instances(), 7);
|
||||
BOOST_TEST_EQ(check_.constructions(), 7);
|
||||
|
||||
i2 = x.emplace_hint(i1, 7, "", 'z', 4, 5, 6, 7);
|
||||
BOOST_TEST_EQ(x.size(), 5u);
|
||||
BOOST_TEST(*i1 == *i2);
|
||||
BOOST_TEST(i1 != i2);
|
||||
BOOST_TEST(x.count(*i1) == 2);
|
||||
BOOST_TEST_EQ(check_.instances(), 8);
|
||||
BOOST_TEST_EQ(check_.constructions(), 8);
|
||||
|
||||
// 10 args with bad hint + duplicate
|
||||
|
||||
emplace_value v4(10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
|
||||
i1 = x.emplace_hint(i2, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
|
||||
BOOST_TEST_EQ(x.size(), 6u);
|
||||
BOOST_TEST_EQ(i1->arg_count, 10);
|
||||
BOOST_TEST(i1 == x.find(v4));
|
||||
BOOST_TEST_EQ(check_.instances(), 10);
|
||||
BOOST_TEST_EQ(check_.constructions(), 10);
|
||||
|
||||
i2 = x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
|
||||
BOOST_TEST_EQ(x.size(), 7u);
|
||||
BOOST_TEST(*i1 == *i2);
|
||||
BOOST_TEST(i1 != i2);
|
||||
BOOST_TEST(x.count(*i1) == 2);
|
||||
BOOST_TEST_EQ(check_.instances(), 11);
|
||||
BOOST_TEST_EQ(check_.constructions(), 11);
|
||||
|
||||
BOOST_TEST_EQ(x.count(v1), 1u);
|
||||
BOOST_TEST_EQ(x.count(v2), 2u);
|
||||
BOOST_TEST_EQ(x.count(v3), 2u);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(emplace_map) {
|
||||
test::check_instances check_;
|
||||
|
||||
typedef boost::unordered_map<emplace_value, emplace_value,
|
||||
boost::hash<emplace_value> > container;
|
||||
typedef container::iterator iterator;
|
||||
typedef std::pair<iterator, bool> return_type;
|
||||
container x(10);
|
||||
return_type r1, r2;
|
||||
|
||||
// 5/8 args + duplicate
|
||||
|
||||
emplace_value k1(5, "", 'b', 4, 5);
|
||||
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
|
||||
r1 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(5, "", 'b', 4, 5),
|
||||
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST(r1.second);
|
||||
BOOST_TEST(x.find(k1) == r1.first);
|
||||
BOOST_TEST(x.find(k1)->second == m1);
|
||||
BOOST_TEST_EQ(check_.instances(), 4);
|
||||
BOOST_TEST_EQ(check_.constructions(), 4);
|
||||
|
||||
r2 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(5, "", 'b', 4, 5),
|
||||
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST(!r2.second);
|
||||
BOOST_TEST(r1.first == r2.first);
|
||||
BOOST_TEST(x.find(k1)->second == m1);
|
||||
BOOST_TEST_EQ(check_.instances(), 4);
|
||||
// constructions could possibly be 5 if the implementation only
|
||||
// constructed the key.
|
||||
BOOST_TEST_EQ(check_.constructions(), 6);
|
||||
|
||||
// 9/3 args + duplicates with hints, different mapped value.
|
||||
|
||||
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
|
||||
emplace_value m2(3, "aaa", 'm');
|
||||
r1 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(3, "aaa", 'm'));
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST(r1.second);
|
||||
BOOST_TEST(r1.first->first.arg_count == 9);
|
||||
BOOST_TEST(r1.first->second.arg_count == 3);
|
||||
BOOST_TEST(x.find(k2) == r1.first);
|
||||
BOOST_TEST(x.find(k2)->second == m2);
|
||||
BOOST_TEST_EQ(check_.instances(), 8);
|
||||
BOOST_TEST_EQ(check_.constructions(), 10);
|
||||
|
||||
BOOST_TEST(r1.first == x.emplace_hint(r1.first,
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(15, "jkjk")));
|
||||
BOOST_TEST(r1.first == x.emplace_hint(r2.first,
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(275, "xxx", 'm', 6)));
|
||||
BOOST_TEST(r1.first == x.emplace_hint(x.end(),
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(-10, "blah blah", '\0')));
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST(x.find(k2)->second == m2);
|
||||
BOOST_TEST_EQ(check_.instances(), 8);
|
||||
BOOST_TEST_EQ(check_.constructions(), 16);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(emplace_multimap) {
|
||||
test::check_instances check_;
|
||||
|
||||
typedef boost::unordered_multimap<emplace_value, emplace_value,
|
||||
boost::hash<emplace_value> > container;
|
||||
typedef container::iterator iterator;
|
||||
container x(10);
|
||||
iterator i1, i2, i3, i4;
|
||||
|
||||
// 5/8 args + duplicate
|
||||
|
||||
emplace_value k1(5, "", 'b', 4, 5);
|
||||
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
|
||||
i1 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(5, "", 'b', 4, 5),
|
||||
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST(x.find(k1) == i1);
|
||||
BOOST_TEST(x.find(k1)->second == m1);
|
||||
BOOST_TEST_EQ(check_.instances(), 4);
|
||||
BOOST_TEST_EQ(check_.constructions(), 4);
|
||||
|
||||
emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8);
|
||||
i2 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(5, "", 'b', 4, 5),
|
||||
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST(i1 != i2);
|
||||
BOOST_TEST(i1->second == m1);
|
||||
BOOST_TEST(i2->second == m1a);
|
||||
BOOST_TEST_EQ(check_.instances(), 7);
|
||||
BOOST_TEST_EQ(check_.constructions(), 7);
|
||||
|
||||
// 9/3 args + duplicates with hints, different mapped value.
|
||||
|
||||
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
|
||||
emplace_value m2(3, "aaa", 'm');
|
||||
i1 = x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(3, "aaa", 'm'));
|
||||
BOOST_TEST_EQ(x.size(), 3u);
|
||||
BOOST_TEST(i1->first.arg_count == 9);
|
||||
BOOST_TEST(i1->second.arg_count == 3);
|
||||
BOOST_TEST_EQ(check_.instances(), 11);
|
||||
BOOST_TEST_EQ(check_.constructions(), 11);
|
||||
|
||||
emplace_value m2a(15, "jkjk");
|
||||
i2 = x.emplace_hint(i2,
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(15, "jkjk"));
|
||||
emplace_value m2b(275, "xxx", 'm', 6);
|
||||
i3 = x.emplace_hint(i1,
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(275, "xxx", 'm', 6));
|
||||
emplace_value m2c(-10, "blah blah", '\0');
|
||||
i4 = x.emplace_hint(x.end(),
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
|
||||
boost::make_tuple(-10, "blah blah", '\0'));
|
||||
BOOST_TEST_EQ(x.size(), 6u);
|
||||
BOOST_TEST(x.find(k2)->second == m2);
|
||||
BOOST_TEST_EQ(check_.instances(), 20);
|
||||
BOOST_TEST_EQ(check_.constructions(), 20);
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -0,0 +1,174 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#define BOOST_UNORDERED_DEPRECATED_EQUALITY
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/preprocessor/seq.hpp>
|
||||
#include <list>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int operator()(int x) const
|
||||
{
|
||||
return alt_hash_ ? x % 250 : (x + 5) % 250;
|
||||
}
|
||||
};
|
||||
|
||||
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
|
||||
#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));
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_size_tests)
|
||||
{
|
||||
boost::unordered_set<int> x1, x2;
|
||||
BOOST_TEST(x1 == x2);
|
||||
BOOST_TEST(!(x1 != x2));
|
||||
|
||||
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_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_AUTO_TEST(equality_predicate_test)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -25,11 +25,9 @@ namespace equality_tests
|
||||
return x % 1000 == y % 1000;
|
||||
}
|
||||
|
||||
std::size_t operator()(int x) const
|
||||
int operator()(int x) const
|
||||
{
|
||||
return alt_hash_ ?
|
||||
static_cast<std::size_t>(x % 250) :
|
||||
static_cast<std::size_t>((x + 5) % 250);
|
||||
return alt_hash_ ? x % 250 : (x + 5) % 250;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/list.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
|
||||
@@ -43,19 +42,13 @@ void write_container(Container const& x)
|
||||
// Make everything collide - for testing erase in a single bucket.
|
||||
struct collision_hash
|
||||
{
|
||||
std::size_t operator()(int) const { return 0; }
|
||||
int operator()(int) const { return 0; }
|
||||
};
|
||||
|
||||
// For testing erase in 2 buckets.
|
||||
struct collision2_hash
|
||||
{
|
||||
std::size_t operator()(int x) const { return static_cast<std::size_t>(x & 1); }
|
||||
};
|
||||
|
||||
// For testing erase in lots of buckets.
|
||||
struct collision3_hash
|
||||
{
|
||||
std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
|
||||
int operator()(int x) const { return x & 1; }
|
||||
};
|
||||
|
||||
typedef boost::unordered_multimap<int, int,
|
||||
@@ -64,9 +57,6 @@ typedef boost::unordered_multimap<int, int,
|
||||
typedef boost::unordered_multimap<int, int,
|
||||
collision2_hash, std::equal_to<int>,
|
||||
test::allocator2<std::pair<int const, int> > > collide_map2;
|
||||
typedef boost::unordered_multimap<int, int,
|
||||
collision3_hash, std::equal_to<int>,
|
||||
test::allocator2<std::pair<int const, int> > > collide_map3;
|
||||
typedef collide_map::value_type collide_value;
|
||||
typedef test::list<collide_value> collide_list;
|
||||
|
||||
@@ -76,7 +66,6 @@ UNORDERED_AUTO_TEST(empty_range_tests)
|
||||
x.erase(x.begin(), x.end());
|
||||
x.erase(x.begin(), x.begin());
|
||||
x.erase(x.end(), x.end());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(single_item_tests)
|
||||
@@ -87,13 +76,10 @@ UNORDERED_AUTO_TEST(single_item_tests)
|
||||
collide_map x(init.begin(), init.end());
|
||||
x.erase(x.begin(), x.begin());
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
|
||||
test::check_equivalent_keys(x);
|
||||
x.erase(x.end(), x.end());
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
|
||||
test::check_equivalent_keys(x);
|
||||
x.erase(x.begin(), x.end());
|
||||
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
|
||||
@@ -106,25 +92,22 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
|
||||
collide_map x(init.begin(), init.end());
|
||||
x.erase(x.begin(), x.end());
|
||||
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
{
|
||||
collide_map x(init.begin(), init.end());
|
||||
int value = test::next(x.begin())->second;
|
||||
x.erase(x.begin(), test::next(x.begin()));
|
||||
int value = boost::next(x.begin())->second;
|
||||
x.erase(x.begin(), boost::next(x.begin()));
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
|
||||
x.begin()->first == 1 && x.begin()->second == value);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
{
|
||||
collide_map x(init.begin(), init.end());
|
||||
int value = x.begin()->second;
|
||||
x.erase(test::next(x.begin()), x.end());
|
||||
x.erase(boost::next(x.begin()), x.end());
|
||||
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
|
||||
x.begin()->first == 1 && x.begin()->second == value);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,11 +127,8 @@ template <class Container>
|
||||
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
|
||||
{
|
||||
collide_list l(x.begin(), x.end());
|
||||
|
||||
l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
|
||||
x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
|
||||
x.erase(boost::next(x.begin(), start), boost::next(x.begin(), end));
|
||||
return compare(l, x);
|
||||
}
|
||||
|
||||
@@ -211,11 +191,4 @@ UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
|
||||
{
|
||||
std::cout<<"exhaustive_collide3_tests:\n";
|
||||
exhaustive_erase_tests((collide_map3*) 0, 8, 4);
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace erase_tests
|
||||
{
|
||||
@@ -25,18 +24,15 @@ namespace erase_tests
|
||||
test::seed_t initialize_seed(85638);
|
||||
|
||||
template <class Container>
|
||||
void erase_tests1(Container*, test::random_generator generator)
|
||||
void erase_tests1(Container*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
|
||||
|
||||
std::cerr<<"Erase by key.\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
int iterations = 0;
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
|
||||
it = v.begin(); it != v.end(); ++it)
|
||||
{
|
||||
@@ -46,7 +42,6 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
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());
|
||||
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,18 +52,17 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type
|
||||
key = test::get_key<Container>(*x.begin());
|
||||
std::size_t count = x.count(key);
|
||||
iterator pos = x.erase(x.begin());
|
||||
BOOST_DEDUCED_TYPENAME Container::iterator
|
||||
pos = x.erase(x.begin());
|
||||
--size;
|
||||
BOOST_TEST(pos == x.begin());
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
@@ -80,34 +74,29 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
std::size_t index = test::random_value(x.size());
|
||||
c_iterator prev, pos, next;
|
||||
using namespace std;
|
||||
int index = rand() % (int) x.size();
|
||||
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
|
||||
if(index == 0) {
|
||||
prev = pos = x.begin();
|
||||
}
|
||||
else {
|
||||
prev = test::next(x.begin(), index - 1);
|
||||
pos = test::next(prev);
|
||||
prev = boost::next(x.begin(), index - 1);
|
||||
pos = boost::next(prev);
|
||||
}
|
||||
next = test::next(pos);
|
||||
next = boost::next(pos);
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type
|
||||
key = test::get_key<Container>(*pos);
|
||||
std::size_t count = x.count(key);
|
||||
BOOST_TEST(count > 0);
|
||||
BOOST_TEST(next == x.erase(pos));
|
||||
--size;
|
||||
if(size > 0)
|
||||
BOOST_TEST(index == 0 ? next == x.begin() :
|
||||
next == test::next(prev));
|
||||
next == boost::next(prev));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
if (x.count(key) != count - 1) {
|
||||
std::cerr << count << " => " << x.count(key) << std::endl;
|
||||
}
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
@@ -128,54 +117,12 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
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);
|
||||
test::check_equivalent_keys(x);
|
||||
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
test::check_equivalent_keys(x);
|
||||
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"erase(random ranges).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
Container x;
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
test::random_values<Container> v(1000, generator);
|
||||
x.insert(v.begin(), v.end());
|
||||
|
||||
// Note that erase only invalidates the erased iterators.
|
||||
std::vector<c_iterator> iterators;
|
||||
for(c_iterator it = x.cbegin(); it != x.cend(); ++it) {
|
||||
iterators.push_back(it);
|
||||
}
|
||||
iterators.push_back(x.cend());
|
||||
|
||||
while(iterators.size() > 1) {
|
||||
std::size_t start = test::random_value(iterators.size());
|
||||
std::size_t length = test::random_value(iterators.size() - start);
|
||||
x.erase(iterators[start], iterators[start + length]);
|
||||
iterators.erase(
|
||||
test::next(iterators.begin(), start),
|
||||
test::next(iterators.begin(), start + length));
|
||||
|
||||
BOOST_TEST(x.size() == iterators.size() - 1);
|
||||
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator
|
||||
i2 = iterators.begin();
|
||||
for(c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
|
||||
BOOST_TEST(i1 == *i2);
|
||||
++i2;
|
||||
}
|
||||
BOOST_TEST(x.cend() == *i2);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr<<"quick_erase(begin()).\n";
|
||||
@@ -185,7 +132,6 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type
|
||||
@@ -195,7 +141,6 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
--size;
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
@@ -207,34 +152,29 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
std::size_t index = test::random_value(x.size());
|
||||
using namespace std;
|
||||
int index = rand() % (int) x.size();
|
||||
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
|
||||
if(index == 0) {
|
||||
prev = pos = x.begin();
|
||||
}
|
||||
else {
|
||||
prev = test::next(x.begin(), index - 1);
|
||||
pos = test::next(prev);
|
||||
prev = boost::next(x.begin(), index - 1);
|
||||
pos = boost::next(prev);
|
||||
}
|
||||
next = test::next(pos);
|
||||
next = boost::next(pos);
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type
|
||||
key = test::get_key<Container>(*pos);
|
||||
std::size_t count = x.count(key);
|
||||
BOOST_TEST(count > 0);
|
||||
x.quick_erase(pos);
|
||||
--size;
|
||||
if(size > 0)
|
||||
BOOST_TEST(index == 0 ? next == x.begin() :
|
||||
next == test::next(prev));
|
||||
next == boost::next(prev));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
if (x.count(key) != count - 1) {
|
||||
std::cerr << count << " => " << x.count(key) << std::endl;
|
||||
}
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
@@ -269,11 +209,10 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(erase_tests1,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace find_tests
|
||||
test::seed_t initialize_seed(78937);
|
||||
|
||||
template <class X>
|
||||
void find_tests1(X*, test::random_generator generator)
|
||||
void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
@@ -37,15 +37,13 @@ void find_tests1(X*, test::random_generator generator)
|
||||
tracker.begin(); it1 != tracker.end(); ++it1)
|
||||
{
|
||||
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);
|
||||
iterator pos = x.find(key);
|
||||
BOOST_TEST(const_pos != x_const.end());
|
||||
BOOST_TEST(const_pos != x_const.end() &&
|
||||
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
|
||||
BOOST_TEST(pos != x.end());
|
||||
BOOST_TEST(pos != x.end() &&
|
||||
x.key_eq()(key, test::get_key<X>(*pos)));
|
||||
BOOST_TEST(const_pos != x_const.end() &&
|
||||
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
|
||||
|
||||
BOOST_TEST(x.count(key) == tracker.count(key));
|
||||
|
||||
@@ -117,8 +115,10 @@ struct compatible_predicate
|
||||
};
|
||||
|
||||
template <class X>
|
||||
void find_compatible_keys_test(X*, test::random_generator generator)
|
||||
void find_compatible_keys_test(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
|
||||
value_iterator;
|
||||
test::random_values<X> v(500, generator);
|
||||
@@ -155,15 +155,14 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(find_tests1,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
UNORDERED_TEST(find_compatible_keys_test,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
|
||||
// Copyright 2016 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 "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_hint
|
||||
{
|
||||
UNORDERED_AUTO_TEST(insert_hint_empty) {
|
||||
typedef boost::unordered_multiset<int> container;
|
||||
container x;
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_empty2) {
|
||||
typedef boost::unordered_multimap<std::string, int> container;
|
||||
container x;
|
||||
x.emplace_hint(x.cbegin(), "hello", 50);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count("hello"), 1u);
|
||||
BOOST_TEST_EQ(x.find("hello")->second, 50);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_single) {
|
||||
typedef boost::unordered_multiset<std::string> container;
|
||||
container x;
|
||||
x.insert("equal");
|
||||
x.insert(x.cbegin(), "equal");
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count("equal"), 2u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_single2) {
|
||||
typedef boost::unordered_multimap<int, std::string> container;
|
||||
container x;
|
||||
x.emplace(10, "one");
|
||||
x.emplace_hint(x.cbegin(), 10, "two");
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count(10), 2u);
|
||||
|
||||
container::iterator it = x.find(10);
|
||||
std::string v0 = (it++)->second;
|
||||
std::string v1 = (it++)->second;
|
||||
|
||||
BOOST_TEST(v0 == "one" || v0 == "two");
|
||||
BOOST_TEST(v1 == "one" || v1 == "two");
|
||||
BOOST_TEST(v0 != v1);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_multiple) {
|
||||
for (unsigned int size = 0; size < 10; ++size) {
|
||||
for (unsigned int offset = 0; offset <= size; ++offset) {
|
||||
typedef boost::unordered_multiset<std::string> container;
|
||||
container x;
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i) { x.insert("multiple"); }
|
||||
|
||||
BOOST_TEST_EQ(x.size(), size);
|
||||
|
||||
container::const_iterator position = x.cbegin();
|
||||
for (unsigned int i = 0; i < offset; ++i) { ++position; }
|
||||
|
||||
x.insert(position, "multiple");
|
||||
|
||||
BOOST_TEST_EQ(x.size(), size + 1u);
|
||||
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_unique) {
|
||||
typedef boost::unordered_set<int> container;
|
||||
container x;
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_unique_single) {
|
||||
typedef boost::unordered_set<int> container;
|
||||
container x;
|
||||
x.insert(10);
|
||||
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
|
||||
x.insert(x.cbegin(), 20);
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
BOOST_TEST_EQ(x.count(20), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -49,8 +49,6 @@ UNORDERED_AUTO_TEST(stable_insert_test1) {
|
||||
x.insert(insert_stable::member(1,2));
|
||||
x.insert(insert_stable::member(1,3));
|
||||
|
||||
BOOST_TEST(x.count(insert_stable::member(1,4)) == 3);
|
||||
|
||||
boost::unordered_multiset<insert_stable::member>::const_iterator
|
||||
it = x.begin(), end = x.end();
|
||||
BOOST_TEST(it != end);
|
||||
@@ -68,11 +66,10 @@ UNORDERED_AUTO_TEST(stable_insert_test2) {
|
||||
boost::unordered_multimap<insert_stable::member, int>::const_iterator
|
||||
iterator;
|
||||
|
||||
iterator it = x.emplace(insert_stable::member(1,1), 1);
|
||||
it = x.emplace(insert_stable::member(1,2), 2);
|
||||
it = x.emplace(insert_stable::member(1,3), 3);
|
||||
|
||||
BOOST_TEST(x.count(insert_stable::member(1,4)) == 3);
|
||||
iterator it
|
||||
= x.insert(x.end(), std::make_pair(insert_stable::member(1,1), 1));
|
||||
it = x.insert(it, std::make_pair(insert_stable::member(1,2), 2));
|
||||
it = x.insert(it, std::make_pair(insert_stable::member(1,3), 3));
|
||||
|
||||
it = x.begin();
|
||||
iterator end = x.end();
|
||||
|
||||
+62
-256
@@ -9,13 +9,13 @@
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace insert_tests {
|
||||
test::seed_t initialize_seed(243432);
|
||||
|
||||
template <class X>
|
||||
void unique_insert_tests1(X*, test::random_generator generator)
|
||||
void unique_insert_tests1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -54,7 +55,7 @@ void unique_insert_tests1(X*, test::random_generator generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@@ -62,7 +63,8 @@ void unique_insert_tests1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void equivalent_insert_tests1(X*, test::random_generator generator)
|
||||
void equivalent_insert_tests1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
|
||||
|
||||
@@ -87,7 +89,7 @@ void equivalent_insert_tests1(X*, test::random_generator generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@@ -95,7 +97,8 @@ void equivalent_insert_tests1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void insert_tests2(X*, test::random_generator generator)
|
||||
void insert_tests2(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME test::ordered<X> tracker_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
@@ -123,11 +126,10 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@@ -153,11 +155,10 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@@ -183,11 +184,10 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
BOOST_TEST(*pos == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@@ -207,15 +207,14 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
x.insert(it, test::next(it));
|
||||
x.insert(it, boost::next(it));
|
||||
tracker.insert(*it);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@@ -233,24 +232,6 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert range with rehash tests.\n";
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
|
||||
x.insert(*v.begin());
|
||||
x.clear();
|
||||
|
||||
x.insert(v.begin(), v.end());
|
||||
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert input iterator range tests.\n";
|
||||
|
||||
{
|
||||
@@ -280,61 +261,13 @@ void insert_tests2(X*, test::random_generator generator)
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert copy iterator range test 2.\n";
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v1(500, generator);
|
||||
test::random_values<X> v2(500, generator);
|
||||
x.insert(test::copy_iterator(v1.begin()), test::copy_iterator(v1.end()));
|
||||
x.insert(test::copy_iterator(v2.begin()), test::copy_iterator(v2.end()));
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert various ranges.\n";
|
||||
|
||||
{
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
|
||||
it = v.begin(); it != v.end();)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
|
||||
next = it;
|
||||
for (std::size_t j = test::random_value(20); j > 0; ++j) {
|
||||
++next;
|
||||
if (next == v.end()) { break; }
|
||||
}
|
||||
|
||||
x.insert(it, next);
|
||||
tracker.insert(it, next);
|
||||
it = next;
|
||||
|
||||
tracker.compare(x); // Slow, but I can't see any other way.
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class X>
|
||||
void unique_emplace_tests1(X*, test::random_generator generator)
|
||||
void unique_emplace_tests1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef test::ordered<X> ordered;
|
||||
@@ -362,16 +295,16 @@ void unique_emplace_tests1(X*, test::random_generator generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void equivalent_emplace_tests1(X*, test::random_generator generator)
|
||||
void equivalent_emplace_tests1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"emplace(value) tests for containers with equivalent keys.\n";
|
||||
|
||||
@@ -393,83 +326,17 @@ void equivalent_emplace_tests1(X*, test::random_generator generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void move_emplace_tests(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
|
||||
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
typename X::value_type value = *it;
|
||||
x.emplace(boost::move(value));
|
||||
tracker.insert(*it);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void default_emplace_tests(X*, test::random_generator)
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
std::cerr<<"emplace() tests.\n";
|
||||
bool is_unique = test::has_unique_keys<X>::value;
|
||||
|
||||
X x;
|
||||
|
||||
x.emplace();
|
||||
BOOST_TEST(x.size() == 1);
|
||||
x.emplace();
|
||||
BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
|
||||
x.emplace();
|
||||
BOOST_TEST(x.size() == (is_unique ? 1u : 3u));
|
||||
|
||||
typename X::value_type y;
|
||||
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 3u));
|
||||
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
|
||||
|
||||
x.emplace(y);
|
||||
BOOST_TEST(x.size() == (is_unique ? 1u : 4u));
|
||||
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 4u));
|
||||
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
|
||||
|
||||
x.clear();
|
||||
BOOST_TEST(x.empty());
|
||||
x.emplace(y);
|
||||
BOOST_TEST(x.size() == 1);
|
||||
x.emplace(y);
|
||||
BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
|
||||
|
||||
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
|
||||
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void map_tests(X*, test::random_generator generator)
|
||||
void map_tests(X*, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"map tests.\n";
|
||||
|
||||
@@ -488,11 +355,10 @@ void map_tests(X*, test::random_generator generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
@@ -500,7 +366,8 @@ void map_tests(X*, test::random_generator generator)
|
||||
// value type.
|
||||
|
||||
template <class X>
|
||||
void map_insert_range_test1(X*, test::random_generator generator)
|
||||
void map_insert_range_test1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"map_insert_range_test1\n";
|
||||
|
||||
@@ -521,7 +388,8 @@ void map_insert_range_test1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void map_insert_range_test2(X*, test::random_generator generator)
|
||||
void map_insert_range_test2(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
std::cerr<<"map_insert_range_test2\n";
|
||||
|
||||
@@ -540,9 +408,9 @@ void map_insert_range_test2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
boost::unordered_set<test::movable,
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
std::allocator<test::movable> >* test_set_std_alloc;
|
||||
std::allocator<test::object> >* test_set_std_alloc;
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
std::allocator<test::object> >* test_multimap_std_alloc;
|
||||
@@ -550,89 +418,63 @@ boost::unordered_multimap<test::object, test::object,
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::movable,
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_multiset;
|
||||
boost::unordered_map<test::movable, test::movable,
|
||||
test::allocator2<test::object> >* test_multiset;
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_map;
|
||||
test::allocator2<test::object> >* test_map;
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_multimap;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(unique_insert_tests1,
|
||||
((test_set_std_alloc)(test_set)(test_map))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(equivalent_insert_tests1,
|
||||
((test_multimap_std_alloc)(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(insert_tests2,
|
||||
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
UNORDERED_TEST(unique_emplace_tests1,
|
||||
((test_set_std_alloc)(test_set)(test_map))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(equivalent_emplace_tests1,
|
||||
((test_multimap_std_alloc)(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(move_emplace_tests,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
|
||||
(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(default_emplace_tests,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
|
||||
(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
#endif
|
||||
|
||||
UNORDERED_TEST(map_tests,
|
||||
((test_map))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(map_insert_range_test1,
|
||||
((test_multimap_std_alloc)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(map_insert_range_test2,
|
||||
((test_multimap_std_alloc)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
struct initialize_from_two_ints
|
||||
{
|
||||
int a, b;
|
||||
|
||||
friend std::size_t hash_value(initialize_from_two_ints const& x)
|
||||
{
|
||||
return static_cast<std::size_t>(x.a + x.b);
|
||||
}
|
||||
|
||||
bool operator==(initialize_from_two_ints const& x) const
|
||||
{
|
||||
return a == x.a && b == x.b;
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
{
|
||||
boost::unordered_set<int> set;
|
||||
@@ -640,38 +482,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
BOOST_TEST_EQ(set.size(), 3u);
|
||||
BOOST_TEST(set.find(1) != set.end());
|
||||
BOOST_TEST(set.find(4) == set.end());
|
||||
|
||||
boost::unordered_set<initialize_from_two_ints> set2;
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
|
||||
set2.insert({{1, 2}});
|
||||
#else
|
||||
set2.insert({1, 2});
|
||||
#endif
|
||||
BOOST_TEST(set2.size() == 1);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({2,1}) == set2.end());
|
||||
|
||||
set2.insert({{3,4},{5,6},{7,8}});
|
||||
BOOST_TEST(set2.size() == 4);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({3,4}) != set2.end());
|
||||
BOOST_TEST(set2.find({5,6}) != set2.end());
|
||||
BOOST_TEST(set2.find({7,8}) != set2.end());
|
||||
BOOST_TEST(set2.find({8,7}) == set2.end());
|
||||
|
||||
set2.insert({{2, 1}, {3,4}});
|
||||
BOOST_TEST(set2.size() == 5);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({2,1}) != set2.end());
|
||||
BOOST_TEST(set2.find({3,4}) != set2.end());
|
||||
BOOST_TEST(set2.find({5,6}) != set2.end());
|
||||
BOOST_TEST(set2.find({7,8}) != set2.end());
|
||||
BOOST_TEST(set2.find({8,7}) == set2.end());
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
|
||||
{
|
||||
boost::unordered_multiset<std::string> multiset;
|
||||
@@ -688,8 +500,6 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
|
||||
BOOST_TEST_EQ(multiset.count("c"), 0u);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_map)
|
||||
{
|
||||
boost::unordered_map<std::string, std::string> map;
|
||||
@@ -713,8 +523,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
|
||||
|
||||
struct overloaded_constructor
|
||||
{
|
||||
overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
|
||||
: x1(x1_), x2(x2_), x3(x3_), x4(x4_) {}
|
||||
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
|
||||
: x1(x1), x2(x2), x3(x3), x4(x4) {}
|
||||
|
||||
int x1, x2, x3, x4;
|
||||
|
||||
@@ -747,6 +557,20 @@ UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
|
||||
#if defined (BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
x.emplace(1);
|
||||
BOOST_TEST(x.find(1) != x.end() &&
|
||||
x.find(1)->second == overloaded_constructor());
|
||||
|
||||
x.emplace(4, 5, 6);
|
||||
BOOST_TEST(x.find(4) != x.end() &&
|
||||
x.find(4)->second == overloaded_constructor(5, 6));
|
||||
|
||||
x.emplace(7, 8, 9, 10);
|
||||
BOOST_TEST(x.find(7) != x.end() &&
|
||||
x.find(7)->second == overloaded_constructor(8, 9, 10));
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
@@ -780,19 +604,6 @@ UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
}
|
||||
|
||||
struct derived_from_piecewise_construct_t :
|
||||
boost::unordered::piecewise_construct_t {};
|
||||
|
||||
derived_from_piecewise_construct_t piecewise_rvalue() {
|
||||
return derived_from_piecewise_construct_t();
|
||||
}
|
||||
|
||||
struct convertible_to_piecewise {
|
||||
operator boost::unordered::piecewise_construct_t() const {
|
||||
return boost::unordered::piecewise_construct;
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test2)
|
||||
{
|
||||
boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
|
||||
@@ -801,18 +612,13 @@ UNORDERED_AUTO_TEST(map_emplace_test2)
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second == overloaded_constructor());
|
||||
|
||||
x.emplace(convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second == overloaded_constructor());
|
||||
|
||||
x.emplace(piecewise_rvalue(), boost::make_tuple(2,3), boost::make_tuple(4,5,6));
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(2,3), boost::make_tuple(4,5,6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, boost::make_tuple(9,3,1), boost::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9,3,1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9,3,1))->second == overloaded_constructor(10));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test2)
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace load_factor_tests
|
||||
test::seed_t initialize_seed(783656);
|
||||
|
||||
template <class X>
|
||||
void set_load_factor_tests(X*)
|
||||
void set_load_factor_tests(X* = 0)
|
||||
{
|
||||
X x;
|
||||
|
||||
@@ -37,7 +37,8 @@ void set_load_factor_tests(X*)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void insert_test(X*, float mlf, test::random_generator generator)
|
||||
void insert_test(X*, float mlf,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
X x;
|
||||
x.max_load_factor(mlf);
|
||||
@@ -51,24 +52,22 @@ void insert_test(X*, float mlf, test::random_generator generator)
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
|
||||
old_bucket_count = x.bucket_count();
|
||||
x.insert(*it);
|
||||
if(static_cast<double>(old_size + 1) <= b * static_cast<double>(old_bucket_count))
|
||||
if(static_cast<double>(old_size + 1) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void load_factor_insert_tests(X* ptr, test::random_generator generator)
|
||||
void load_factor_insert_tests(X* ptr = 0)
|
||||
{
|
||||
insert_test(ptr, 1.0f, generator);
|
||||
insert_test(ptr, 0.1f, generator);
|
||||
insert_test(ptr, 100.0f, generator);
|
||||
insert_test(ptr, 1.0f);
|
||||
insert_test(ptr, 0.1f);
|
||||
insert_test(ptr, 100.0f);
|
||||
|
||||
insert_test(ptr, (std::numeric_limits<float>::min)(),
|
||||
generator);
|
||||
insert_test(ptr, (std::numeric_limits<float>::min)());
|
||||
|
||||
if(std::numeric_limits<float>::has_infinity)
|
||||
insert_test(ptr, std::numeric_limits<float>::infinity(),
|
||||
generator);
|
||||
insert_test(ptr, std::numeric_limits<float>::infinity());
|
||||
}
|
||||
|
||||
boost::unordered_set<int>* int_set_ptr;
|
||||
@@ -76,17 +75,12 @@ boost::unordered_multiset<int>* int_multiset_ptr;
|
||||
boost::unordered_map<int, int>* int_map_ptr;
|
||||
boost::unordered_multimap<int, int>* int_multimap_ptr;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(set_load_factor_tests,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(load_factor_insert_tests,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ struct SimpleAllocator
|
||||
{
|
||||
}
|
||||
|
||||
template <class T> SimpleAllocator(const SimpleAllocator<T>&)
|
||||
template <class T> SimpleAllocator(const SimpleAllocator<T>& other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace move_tests
|
||||
{
|
||||
test::seed_t initialize_seed(98624);
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#define BOOST_UNORDERED_TEST_MOVING 1
|
||||
#else
|
||||
#define BOOST_UNORDERED_TEST_MOVING 0
|
||||
@@ -57,7 +57,8 @@ namespace move_tests
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void move_construct_tests1(T* ptr, test::random_generator const& generator)
|
||||
void move_construct_tests1(T* ptr,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf;
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq;
|
||||
@@ -90,7 +91,8 @@ namespace move_tests
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void move_assign_tests1(T*, test::random_generator const& generator)
|
||||
void move_assign_tests1(T*,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
@@ -108,7 +110,8 @@ namespace move_tests
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void move_construct_tests2(T*, test::random_generator const& generator)
|
||||
void move_construct_tests2(T*,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
|
||||
@@ -154,21 +157,17 @@ namespace move_tests
|
||||
|
||||
test::random_values<T> v(25, generator);
|
||||
T y(create(v, count, hf, eq, al, 1.0), al);
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
#elif defined(BOOST_HAS_NRVO)
|
||||
BOOST_TEST(
|
||||
static_cast<std::size_t>(test::global_object_count.constructions
|
||||
- count.constructions) <=
|
||||
(test::is_set<T>::value ? 1 : 2) *
|
||||
(test::has_unique_keys<T>::value ? 25 : v.size()));
|
||||
test::global_object_count.constructions - count.constructions <=
|
||||
(test::is_set<T>::value ? 25 : 50));
|
||||
BOOST_TEST(count.instances == test::global_object_count.instances);
|
||||
#else
|
||||
BOOST_TEST(
|
||||
static_cast<std::size_t>(test::global_object_count.constructions
|
||||
- count.constructions) <=
|
||||
(test::is_set<T>::value ? 2 : 4) *
|
||||
(test::has_unique_keys<T>::value ? 25 : v.size()));
|
||||
test::global_object_count.constructions - count.constructions <=
|
||||
(test::is_set<T>::value ? 50 : 100));
|
||||
BOOST_TEST(count.instances == test::global_object_count.instances);
|
||||
#endif
|
||||
test::check_container(y, v);
|
||||
@@ -181,7 +180,8 @@ namespace move_tests
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void move_assign_tests2(T*, test::random_generator const& generator)
|
||||
void move_assign_tests2(T*,
|
||||
test::random_generator const& generator = test::default_generator)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
|
||||
@@ -369,7 +369,6 @@ boost::unordered_multimap<test::object, test::object,
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(move_construct_tests1, (
|
||||
(test_map_std_alloc)
|
||||
@@ -377,7 +376,6 @@ boost::unordered_multimap<test::object, test::object,
|
||||
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
|
||||
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
UNORDERED_TEST(move_assign_tests1, (
|
||||
(test_map_std_alloc)
|
||||
@@ -385,21 +383,19 @@ boost::unordered_multimap<test::object, test::object,
|
||||
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
|
||||
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
UNORDERED_TEST(move_construct_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
|
||||
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
UNORDERED_TEST(move_assign_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
|
||||
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
|
||||
// Copyright 2013 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 "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
namespace noexcept_tests
|
||||
{
|
||||
// Test the noexcept is set correctly for the move constructor.
|
||||
|
||||
struct hash_possible_exception : boost::hash<int>
|
||||
{
|
||||
hash_possible_exception(hash_possible_exception const&) {}
|
||||
};
|
||||
|
||||
struct equal_to_possible_exception : std::equal_to<int>
|
||||
{
|
||||
equal_to_possible_exception(equal_to_possible_exception const&) {}
|
||||
};
|
||||
|
||||
// Test that the move constructor does actually move without throwing
|
||||
// an exception when it claims to.
|
||||
|
||||
struct test_exception {};
|
||||
|
||||
bool throwing_test_exception = false;
|
||||
void test_throw(char const* name) {
|
||||
if (throwing_test_exception) {
|
||||
std::cerr << "Throw exception in: " << name << std::endl;
|
||||
throw test_exception();
|
||||
}
|
||||
}
|
||||
|
||||
class hash_nothrow_move : boost::hash<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
|
||||
|
||||
typedef boost::hash<int> base;
|
||||
public:
|
||||
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
|
||||
BOOST_NOEXCEPT {}
|
||||
|
||||
hash_nothrow_move() { test_throw("Constructor"); }
|
||||
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
|
||||
hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
|
||||
{ test_throw("Assign"); return *this; }
|
||||
hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
|
||||
{ test_throw("Move Assign"); return *this; }
|
||||
std::size_t operator()(int x) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
|
||||
};
|
||||
|
||||
class equal_to_nothrow_move : std::equal_to<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
|
||||
|
||||
typedef std::equal_to<int> base;
|
||||
public:
|
||||
equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
|
||||
BOOST_NOEXCEPT {}
|
||||
equal_to_nothrow_move() { test_throw("Constructor"); }
|
||||
equal_to_nothrow_move(equal_to_nothrow_move const&)
|
||||
{ test_throw("Copy"); }
|
||||
equal_to_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move))
|
||||
{ test_throw("Assign"); return *this; }
|
||||
equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move))
|
||||
{ test_throw("Move Assign"); return *this; }
|
||||
std::size_t operator()(int x, int y) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
|
||||
};
|
||||
|
||||
bool have_is_nothrow_move = false;
|
||||
|
||||
UNORDERED_AUTO_TEST(check_is_nothrow_move)
|
||||
{
|
||||
BOOST_TEST(!boost::is_nothrow_move_constructible<hash_possible_exception>::value);
|
||||
have_is_nothrow_move = boost::is_nothrow_move_constructible<hash_nothrow_move>::value;
|
||||
|
||||
// Copied from boost::is_nothrow_move_constructible implementation
|
||||
// to make sure this does actually detect it when expected.
|
||||
//
|
||||
// The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT
|
||||
// is defined (for some versions of Visual C++?) but detects 'throw()',
|
||||
// not noexcept.
|
||||
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
|
||||
BOOST_TEST(have_is_nothrow_move);
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(test_noexcept)
|
||||
{
|
||||
if (have_is_nothrow_move) {
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_set<int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multiset<int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_map<int, int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multimap<int, int> >::value));
|
||||
}
|
||||
|
||||
BOOST_TEST((!boost::is_nothrow_move_constructible<
|
||||
boost::unordered_set<int, hash_possible_exception>
|
||||
>::value));
|
||||
BOOST_TEST((!boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multiset<int, boost::hash<int>,
|
||||
equal_to_possible_exception>
|
||||
>::value));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
|
||||
{
|
||||
typedef boost::unordered_set<int,
|
||||
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
|
||||
|
||||
if (have_is_nothrow_move)
|
||||
{
|
||||
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
|
||||
|
||||
throwing_test_exception = false;
|
||||
|
||||
throwing_set x1;
|
||||
x1.insert(10);
|
||||
x1.insert(50);
|
||||
|
||||
try {
|
||||
throwing_test_exception = true;
|
||||
|
||||
throwing_set x2 = boost::move(x1);
|
||||
BOOST_TEST(x2.size() == 2);
|
||||
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
|
||||
} catch(test_exception) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
throwing_test_exception = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/metafunctions.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
|
||||
namespace rehash_tests
|
||||
{
|
||||
@@ -22,13 +20,13 @@ test::seed_t initialize_seed(2974);
|
||||
template <class X>
|
||||
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
|
||||
{
|
||||
return static_cast<double>(x.bucket_count()) >=
|
||||
return static_cast<double>(x.bucket_count()) >
|
||||
static_cast<double>(x.size()) / x.max_load_factor() &&
|
||||
x.bucket_count() >= n;
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void rehash_empty_test1(X*)
|
||||
void rehash_empty_test1(X* = 0)
|
||||
{
|
||||
X x;
|
||||
|
||||
@@ -37,13 +35,11 @@ void rehash_empty_test1(X*)
|
||||
|
||||
x.rehash(0);
|
||||
BOOST_TEST(postcondition(x, 0));
|
||||
|
||||
x.rehash(10000000);
|
||||
BOOST_TEST(postcondition(x, 10000000));
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void rehash_empty_test2(X*, test::random_generator generator)
|
||||
void rehash_empty_test2(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::random_values<X> v(1000, generator);
|
||||
test::ordered<X> tracker;
|
||||
@@ -58,14 +54,11 @@ void rehash_empty_test2(X*, test::random_generator generator)
|
||||
tracker.compare(x);
|
||||
|
||||
BOOST_TEST(postcondition(x, 10000));
|
||||
|
||||
x.rehash(10000000);
|
||||
tracker.compare(x);
|
||||
BOOST_TEST(postcondition(x, 10000000));
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void rehash_empty_test3(X*, test::random_generator generator)
|
||||
void rehash_empty_test3(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::random_values<X> v(1000, generator);
|
||||
test::ordered<X> tracker;
|
||||
@@ -82,8 +75,10 @@ void rehash_empty_test3(X*, test::random_generator generator)
|
||||
BOOST_TEST(postcondition(x, 0));
|
||||
}
|
||||
|
||||
|
||||
template <class X>
|
||||
void rehash_test1(X*, test::random_generator generator)
|
||||
void rehash_test1(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::random_values<X> v(1000, generator);
|
||||
test::ordered<X> tracker;
|
||||
@@ -106,40 +101,12 @@ void rehash_test1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_empty_test1(X*)
|
||||
{
|
||||
X x;
|
||||
|
||||
x.reserve(10000);
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
|
||||
x.reserve(0);
|
||||
|
||||
x.reserve(10000000);
|
||||
BOOST_TEST(x.bucket_count() >= 10000000);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_empty_test2(X*)
|
||||
{
|
||||
X x;
|
||||
x.max_load_factor(0.25);
|
||||
|
||||
x.reserve(10000);
|
||||
BOOST_TEST(x.bucket_count() >= 40000);
|
||||
|
||||
x.reserve(0);
|
||||
|
||||
x.reserve(10000000);
|
||||
BOOST_TEST(x.bucket_count() >= 40000000);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_test1(X*, test::random_generator generator)
|
||||
void reserve_test1(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
|
||||
{
|
||||
for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13)
|
||||
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
|
||||
{
|
||||
test::random_values<X> v(i, generator);
|
||||
|
||||
@@ -149,7 +116,11 @@ void reserve_test1(X*, test::random_generator generator)
|
||||
X x;
|
||||
x.max_load_factor(random_mlf ?
|
||||
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
|
||||
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
|
||||
|
||||
// For the current standard this should reserve i+1, I've
|
||||
// submitted a defect report and will assume it's a defect
|
||||
// for now.
|
||||
x.reserve(i);
|
||||
|
||||
// Insert an element before the range insert, otherwise there are
|
||||
// no iterators to invalidate in the range insert, and it can
|
||||
@@ -167,11 +138,12 @@ void reserve_test1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_test2(X*, test::random_generator generator)
|
||||
void reserve_test2(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
|
||||
{
|
||||
for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13)
|
||||
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
|
||||
{
|
||||
test::random_values<X> v(i, generator);
|
||||
|
||||
@@ -182,9 +154,9 @@ void reserve_test2(X*, test::random_generator generator)
|
||||
x.max_load_factor(random_mlf ?
|
||||
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
|
||||
|
||||
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
|
||||
|
||||
x.reserve(i);
|
||||
std::size_t bucket_count = x.bucket_count();
|
||||
|
||||
for (typename test::random_values<X>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
@@ -198,46 +170,27 @@ void reserve_test2(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
boost::unordered_set<int>* int_set_ptr;
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator2<test::object> >* test_multiset_ptr;
|
||||
boost::unordered_map<test::movable, test::movable,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_map_ptr;
|
||||
boost::unordered_multiset<int>* int_multiset_ptr;
|
||||
boost::unordered_map<int, int>* int_map_ptr;
|
||||
boost::unordered_multimap<int, int>* int_multimap_ptr;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_TEST(rehash_empty_test1,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_empty_test2,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_empty_test3,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(rehash_test1,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
UNORDERED_TEST(reserve_empty_test1,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(reserve_empty_test2,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(reserve_test1,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(reserve_test2,
|
||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void swap_test_impl(X& x1, X& x2)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void swap_tests1(X*, test::random_generator generator)
|
||||
void swap_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
@@ -76,9 +76,10 @@ void swap_tests1(X*, test::random_generator generator)
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void swap_tests2(X* ptr, test::random_generator generator)
|
||||
void swap_tests2(X* ptr = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
swap_tests1(ptr, generator);
|
||||
swap_tests1(ptr);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
|
||||
@@ -204,10 +205,6 @@ bool is_propagate(T*)
|
||||
return T::allocator_type::is_propagate_on_swap;
|
||||
}
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_AUTO_TEST(check_traits)
|
||||
{
|
||||
BOOST_TEST(!is_propagate(test_set));
|
||||
@@ -216,21 +213,17 @@ UNORDERED_AUTO_TEST(check_traits)
|
||||
}
|
||||
|
||||
UNORDERED_TEST(swap_tests1, (
|
||||
(test_map_std_alloc)
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
(test_map_std_alloc)
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
))
|
||||
|
||||
UNORDERED_TEST(swap_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
)
|
||||
((default_generator)(generate_collisions)(limited_range))
|
||||
)
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
))
|
||||
|
||||
}
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -20,17 +20,8 @@ namespace unnecessary_copy_tests
|
||||
public:
|
||||
static int copies;
|
||||
static int moves;
|
||||
static int id_count;
|
||||
|
||||
count_copies() : tag_(0), id_(++id_count) {
|
||||
++copies;
|
||||
trace_op("Default construct");
|
||||
}
|
||||
|
||||
explicit count_copies(int tag) : tag_(tag), id_(++id_count) {
|
||||
++copies;
|
||||
trace_op("Tag construct");
|
||||
}
|
||||
count_copies() : tag_(0) { ++copies; }
|
||||
explicit count_copies(int tag) : tag_(tag) { ++copies; }
|
||||
|
||||
// This bizarre constructor is an attempt to confuse emplace.
|
||||
//
|
||||
@@ -42,30 +33,17 @@ namespace unnecessary_copy_tests
|
||||
// The second emplace should use the single argument contructor for
|
||||
// the key, and this constructor for the value.
|
||||
count_copies(count_copies const&, count_copies const& x)
|
||||
: tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Pair construct");
|
||||
}
|
||||
: tag_(x.tag_) { ++copies; }
|
||||
|
||||
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Copy construct");
|
||||
}
|
||||
|
||||
count_copies(BOOST_RV_REF(count_copies) x) :
|
||||
tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
|
||||
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_) {
|
||||
x.tag_ = -1; ++moves;
|
||||
trace_op("Move construct");
|
||||
}
|
||||
|
||||
count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++copies;
|
||||
trace_op("Copy assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -73,21 +51,10 @@ namespace unnecessary_copy_tests
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++moves;
|
||||
trace_op("Move assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
~count_copies() {
|
||||
trace_op("Destruct");
|
||||
}
|
||||
|
||||
void trace_op(char const* str) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_
|
||||
<< " (#" << id_ << ")" <<std::endl;
|
||||
}
|
||||
|
||||
int tag_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
bool operator==(count_copies const& x, count_copies const& y) {
|
||||
@@ -102,9 +69,6 @@ namespace unnecessary_copy_tests
|
||||
void reset() {
|
||||
count_copies::copies = 0;
|
||||
count_copies::moves = 0;
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
||||
<< "\nReset\n" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,24 +79,10 @@ namespace unnecessary_copy_tests
|
||||
#endif
|
||||
{
|
||||
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x) {
|
||||
return static_cast<std::size_t>(x.tag_);
|
||||
return x.tag_;
|
||||
}
|
||||
}
|
||||
|
||||
// Boost.Move doesn't seem to work very well on this compiler.
|
||||
// For example for:
|
||||
//
|
||||
// T x;
|
||||
//
|
||||
// It will default construct T, and then move it in.
|
||||
// For 'T const' it seems to copy.
|
||||
|
||||
#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
|
||||
#define EXTRA_CONSTRUCT_COST 1
|
||||
#else
|
||||
#define EXTRA_CONSTRUCT_COST 0
|
||||
#endif
|
||||
|
||||
#define COPY_COUNT(n) \
|
||||
if(::unnecessary_copy_tests::count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
@@ -164,19 +114,14 @@ namespace unnecessary_copy_tests
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_EXTRA(a, b) \
|
||||
COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
#define MOVE_COUNT_EXTRA(a, b) \
|
||||
MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
|
||||
namespace unnecessary_copy_tests
|
||||
{
|
||||
int count_copies::copies;
|
||||
int count_copies::moves;
|
||||
int count_copies::id_count;
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_insert_test(T*)
|
||||
@@ -213,7 +158,7 @@ namespace unnecessary_copy_tests
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT(2);
|
||||
@@ -225,9 +170,9 @@ namespace unnecessary_copy_tests
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_std_move_test(T*)
|
||||
void unnecessary_copy_emplace_move_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
@@ -237,29 +182,10 @@ namespace unnecessary_copy_tests
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_std_move_test,
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_boost_move_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#else
|
||||
// Since std::pair isn't movable, move only works for sets.
|
||||
COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_boost_move_set_test(T*)
|
||||
{
|
||||
@@ -281,10 +207,10 @@ namespace unnecessary_copy_tests
|
||||
T x;
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(2); MOVE_COUNT_EXTRA(0, 1);
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#endif
|
||||
@@ -319,8 +245,8 @@ namespace unnecessary_copy_tests
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#else
|
||||
@@ -344,16 +270,14 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
x.emplace(std::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0); MOVE_COUNT(1);
|
||||
#endif
|
||||
|
||||
// Use a new value for cases where a did get moved...
|
||||
// Just in case a did get moved...
|
||||
count_copies b;
|
||||
|
||||
// The container will have to create a copy in order to compare with
|
||||
@@ -398,7 +322,7 @@ namespace unnecessary_copy_tests
|
||||
// TODO: Run tests for pairs without const etc.
|
||||
std::pair<count_copies const, count_copies> a;
|
||||
x.emplace(a);
|
||||
COPY_COUNT_EXTRA(4, 1); MOVE_COUNT_EXTRA(0, 1);
|
||||
COPY_COUNT(4); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 0 arguments
|
||||
@@ -408,16 +332,7 @@ namespace unnecessary_copy_tests
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
|
||||
// This is a little odd, Visual C++ 11 seems to move the pair, which
|
||||
// results in one copy (for the const key) and one move (for the
|
||||
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
|
||||
// has the normal result, it must be some odd consequence of how
|
||||
// Visual C++ 11 handles calling move for default arguments.
|
||||
COPY_COUNT(3); MOVE_COUNT(1);
|
||||
# else
|
||||
COPY_COUNT_EXTRA(2, 1); MOVE_COUNT_EXTRA(0, 1);
|
||||
# endif
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
#endif
|
||||
|
||||
reset();
|
||||
@@ -441,8 +356,9 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
|
||||
|
||||
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
|
||||
!(defined(_MSC_VER) && _MSC_VER < 1600)
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || \
|
||||
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
|
||||
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
@@ -451,12 +367,16 @@ namespace unnecessary_copy_tests
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
|
||||
// No move should take place.
|
||||
// (since a is already in the container)
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
x.emplace(std::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
@@ -509,9 +429,8 @@ namespace unnecessary_copy_tests
|
||||
COPY_COUNT(tuple_copy_cost);
|
||||
MOVE_COUNT(tuple_move_cost);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
|
||||
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
|
||||
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
|
||||
#if defined(__GNUC__) && __GNUC__ > 4 || \
|
||||
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::forward_as_tuple(b.first),
|
||||
|
||||
Reference in New Issue
Block a user