Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Clow 34868c50ca Release 1.52.0
[SVN r81201]
2012-11-05 15:31:58 +00:00
103 changed files with 14375 additions and 22323 deletions
-1
View File
@@ -1 +0,0 @@
/doc/html/
-64
View File
@@ -1,64 +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: |
label="gcc C++03";
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror --std=c++03 ;"
enable_coverage=1
- compiler: gcc
env: |
label="gcc C++11";
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror --std=c++11 ;"
enable_coverage=1
- compiler: gcc
env: |
label="gcc 32 bit C++11";
user_config="using gcc : : g++-4.8 -m32 -fsanitize=address -Werror --std=c++11 ;"
- compiler: clang
env: |
label="clang C++11";
user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++11 ;"
# sanitized=address not available for 32-bit clang on travis.
- compiler: clang
env: |
label="clang 32 bit";
user_config="using clang : : clang++ -m32 -Werror --std=c++03 ;"
before_install:
- if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi
before_script:
- cd ${TRAVIS_BUILD_DIR}
- touch Jamroot.jam
- cd $HOME
- echo $user_config > ~/user-config.jam
- cat ~/user-config.jam
- wget -O boost.tar.bz2 https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2
- tar -xjf boost.tar.bz2
- mv boost_1_64_0 boost
- rm -r boost/boost/unordered
after_success:
if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi
script:
- cd ${TRAVIS_BUILD_DIR}/test
- bjam -q include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
-37
View File
@@ -1,37 +0,0 @@
# Copyright 2017 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Using clang format 3.8
# http://llvm.org/releases/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html
# Becuase you have to start somewhere.
BasedOnStyle: LLVM
# Basic settings
ColumnLimit: 80
ContinuationIndentWidth: 4
IndentWidth: 4
UseTab: Never
Language: Cpp
Standard: Cpp03
# Code layout
AlignAfterOpenBracket: DontAlign
AlignTrailingComments: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterNamespace: false
AfterClass: true
AfterStruct: true
AfterUnion: true
AfterEnum: true
AfterFunction: true
AfterControlStatement: false
BeforeCatch: false
BeforeElse: false
PointerAlignment: Left
# Boost specific stuff
ForEachMacros: [ BOOST_FOREACH ]
-9
View File
@@ -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 ;
+4 -104
View File
@@ -47,7 +47,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
@@ -99,7 +99,7 @@ First official release.
has been rewritten to use templates instead of macros for the implementation
classes.
* The container object is now smaller thanks to using `boost::compressed_pair`
* The container objcet is now smaller thanks to using `boost::compressed_pair`
for EBO and a slightly different function buffer - now using a bool instead
of a member pointer.
@@ -170,7 +170,7 @@ C++11 support has resulted in some breaking changes:
longer does so. It does emulate the new `piecewise_construct`
pair constructors - only you need to use
`boost::piecewise_construct`. To use the old emulation of
the variadic constructors define
the variadic consturctors define
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
[h2 Boost 1.49.0]
@@ -207,7 +207,7 @@ C++11 support has resulted in some breaking changes:
* 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 support g++ 3.4 ([ticket 7175]).
* Adjust SFINAE use to try to supprt g++ 3.4 ([ticket 7175]).
* Updated to use the new config macros.
[h2 Boost 1.52.0]
@@ -220,104 +220,4 @@ C++11 support has resulted in some breaking changes:
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
supported up to 9.
[h2 Boost 1.64.0]
* Initial support for new C++17 member functions:
`insert_or_assign` and `try_emplace` in `unordered_map`,
* Initial support for `merge` and `extract`.
Does not include transferring nodes between
`unordered_map` and `unordered_multimap` or between `unordered_set` and
`unordered_multiset` yet. That will hopefully be in the next version of
Boost.
[h2 Boost 1.65.0]
* Add deprecated attributes to `quick_erase` and `erase_return_void`.
I really will remove them in a future version this time.
* Small standards compliance fixes:
* `noexpect` specs for `swap` free functions.
* Add missing `insert(P&&)` methods.
[endsect]
+19 -36
View File
@@ -2,24 +2,17 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[section:compliance Standard Compliance]
The intent of Boost.Unordered is to implement a close (but inperfect)
implementation of the C++17 standard, that will work with C++98 upwards.
The wide compatibility does mean some comprimises have to be made.
With a compiler and library that fully support C++11, the differences should
be minor.
[section:compliance C++11 Compliance]
[section:move Move emulation]
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
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]
@@ -57,32 +50,23 @@ Due to imperfect move emulation, some assignments might check
`propagate_on_container_copy_assignment` on some compilers and
`propagate_on_container_move_assignment` on others.
[endsect]
The use of the allocator's construct and destruct methods might be a bit
surprising.
Nodes are constructed and destructed using the allocator, but the elements
are stored in aligned space within the node and constructed and destructed
by calling the constructor and destructor directly.
[section:construction Construction/Destruction using allocators]
In C++11 the allocator's construct function has the signature:
The following support is required for full use of C++11 style
construction/destruction:
template <class U, class... Args>
void construct(U* p, Args&&... args);
* Variadic templates.
* Piecewise construction of `std::pair`.
* Either `std::allocator_traits` or expression SFINAE.
This is detected using Boost.Config. The macro
`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0
otherwise.
When this is the case `allocator_traits::construct` and
`allocator_traits::destroy` will always be used, apart from when piecewise
constructing a `std::pair` using `boost::tuple` (see [link
unordered.compliance.pairs below]), but that should be easily avoided.
When support is not available `allocator_traits::construct` and
`allocator_traits::destroy` are never called.
[endsect]
[section:pointer_traits Pointer Traits]
which supports calling `construct` for the contained object, but
most existing allocators don't support this. If member function detection
was good enough then with old allocators it would fall back to calling
the element's constructor directly but in general, detection isn't good
enough to do this which is why Boost.Unordered just calls the constructor
directly every time. In most cases this will work okay.
`pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators, this can cause problems if the allocator can't be
@@ -92,7 +76,6 @@ is used to obtain a const pointer.
[endsect]
[#unordered.compliance.pairs]
[section:pairs Pairs]
Since the containers use `std::pair` they're limited to the version
+2 -2
View File
@@ -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]``;
}
+9 -14
View File
@@ -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]
@@ -13,7 +13,7 @@ containers in the draft standard, so the interface was fixed. But there are
still some implementation decisions to make. The priorities are
conformance to the standard and portability.
The [@http://en.wikipedia.org/wiki/Hash_table Wikipedia article on hash tables]
The [@http://en.wikipedia.org/wiki/Hash_table wikipedia article on hash tables]
has a good summary of the implementation issues for hash tables in general.
[h2 Data Structure]
@@ -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 architectures, where prime number
modulus can be expensive. Although this varies depending on the architecture,
so I probably should revisit it.
I'm also thinking of introducing a mechanism whereby a hash function can
indicate that it's safe to be used directly with power of 2 buckets, in
which case a faster plain power of 2 implementation can be used.
So, this implementation uses a prime number for the hash table size.
[endsect]
+16 -582
View File
@@ -7,10 +7,6 @@ function echo_unordered_docs(
$name = 'unordered_'.
($equivalent_keys ? 'multi' : '').
($map ? 'map' : 'set');
// For merge....
$node_partner = 'unordered_'.
($equivalent_keys ? '' : 'multi').
($map ? 'map' : 'set');
if ($map)
{
@@ -193,36 +189,10 @@ EOL;
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<typedef name="node_type">
<type><emphasis>implementation-defined</emphasis></type>
<description>
<para>See <classname>node_handle_<?php echo $map ? 'map' : 'set'; ?></classname> for details.</para>
</description>
</typedef>
<?php if (!$equivalent_keys): ?>
<typedef name="insert_return_type">
<type><emphasis>implementation-defined</emphasis></type>
<description>
Structure returned by inserting <code>node_type</code>.
</description>
</typedef>
<?php endif; ?>
<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&amp;</paramtype>
@@ -276,12 +246,7 @@ 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
@@ -345,168 +310,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; ?> &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</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&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</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&amp;</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&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</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&amp;</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&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</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>
@@ -555,21 +358,6 @@ EOL;
</para>
</requires>
</method>
<method name="operator=">
<parameter>
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<type><?php echo $name; ?>&amp;</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>
@@ -661,6 +449,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">
@@ -707,6 +499,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">
@@ -851,54 +647,6 @@ EOL;
<paramtype>InputIterator</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>
<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&lt;value_type&gt;</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>
<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&lt;value_type&gt;</paramtype>
</parameter>
<type>void</type>
<description>
<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>
@@ -914,138 +662,6 @@ EOL;
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="extract">
<parameter name="position">
<paramtype>const_iterator</paramtype>
</parameter>
<type>node_type</type>
<description>
<para>Removes the element pointed to by <code>position</code>.</para>
</description>
<returns>
<para>A <code>node_type</code> owning the element.</para>
</returns>
<notes>
<para>
In C++17 a node extracted using this method can be inserted into a compatible <code><?php echo $node_partner; ?></code>,
but that is not supported yet.
</para>
</notes>
</method>
<method name="extract">
<parameter name="k">
<paramtype>key_type const&amp;</paramtype>
</parameter>
<type>node_type</type>
<description>
<para>Removes an element with key equivalent to <code>k</code>.</para>
</description>
<returns>
<para>A <code>node_type</code> owning the element if found, otherwise an empty <code>node_type</code>.</para>
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
</throws>
<notes>
<para>
In C++17 a node extracted using this method can be inserted into a compatible <code><?php echo $node_partner; ?></code>,
but that is not supported yet.
</para>
</notes>
</method>
<method name="insert">
<parameter name="nh">
<paramtype>node_type&amp;&amp;</paramtype>
</parameter>
<type><?php echo $equivalent_keys ? 'iterator' : 'insert_return_type' ?></type>
<description>
<para>If <code>nh</code> is empty, has no affect.</para>
<?php if ($equivalent_keys): ?>
<para>Otherwise inserts the element owned by <code>nh</code></para>
<?php else: ?>
<para>Otherwise inserts the element owned by <code>nh</code>
if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
</para>
<?php endif ?>
</description>
<requires>
<para><code>nh</code> is empty or <code>nh.get_allocator()</code> is equal to the container's allocator.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>If <code>nh</code> was empty, returns <code>end()</code>.</para>
<para>Otherwise returns an iterator pointing to the newly inserted element.</para>
<?php else: ?>
<para>If <code>nh</code> was empty, returns an <code>insert_return_type</code> with:
<code>inserted</code> equal to <code>false</code>,
<code>position</code> equal to <code>end()</code> and
<code>node</code> empty.</para>
<para>Otherwise if there was already an element with an equivalent key, returns an <code>insert_return_type</code> with:
<code>inserted</code> equal to <code>false</code>,
<code>position</code> pointing to a matching element and
<code>node</code> contains the node from <code>nh</code>.</para>
<para>Otherwise if the insertion succeeded, returns an <code>insert_return_type</code> with:
<code>inserted</code> equal to <code>true</code>,
<code>position</code> pointing to the newly inserted element and
<code>node</code> empty.</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>
<para>In C++17 this can be used to insert a node extracted from a compatible <code><?php echo $node_partner; ?></code>,
but that is not supported yet.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="nh">
<paramtype>node_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>If <code>nh</code> is empty, has no affect.</para>
<?php if ($equivalent_keys): ?>
<para>Otherwise inserts the element owned by <code>nh</code></para>
<?php else: ?>
<para>Otherwise inserts the element owned by <code>nh</code>
if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
</para>
<para>If there is already an element in the container with an equivalent <?php echo $key_name; ?>
has no effect on <code>nh</code> (i.e. <code>nh</code> still contains the node.)</para>
<?php endif ?>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>nh</code> is empty or <code>nh.get_allocator()</code> is equal to the container's allocator.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>If <code>nh</code> was empty, returns <code>end()</code>.</para>
<para>Otherwise returns an iterator pointing to the newly inserted element.</para>
<?php else: ?>
<para>If <code>nh</code> was empty returns <code>end()</code>.</para>
<para>If there was already an element in the container with an equivalent <?php echo $key_name; ?>
returns an iterator pointing to that.</para>
<para>Otherwise returns an iterator pointing to the newly inserted element.</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>
<para>In C++17 this can be used to insert a node extracted from a compatible <code><?php echo $node_partner; ?></code>,
but that is not supported yet.</para>
</notes>
</method>
<method name="erase">
<parameter name="position">
<paramtype>const_iterator</paramtype>
@@ -1177,74 +793,6 @@ EOL;
the equality predieate and hash function are swapped using their copy constructors.</para>
</notes>
</method>
<method name="merge">
<template>
<template-type-parameter name="H2">
</template-type-parameter>
<template-type-parameter name="P2">
</template-type-parameter>
</template>
<parameter name="source">
<?php if ($map): ?>
<paramtype><?php echo $name; ?>&lt;Key, Mapped, H2, P2, Alloc&gt;&amp;</paramtype>
<?php else: ?>
<paramtype><?php echo $name; ?>&lt;Value, H2, P2, Alloc&gt;&amp;</paramtype>
<?php endif; ?>
</parameter>
<notes>
<para>Does not support merging with a compatible <code><?php echo $node_partner; ?></code> yet.</para>
</notes>
</method>
<method name="merge">
<template>
<template-type-parameter name="H2">
</template-type-parameter>
<template-type-parameter name="P2">
</template-type-parameter>
</template>
<parameter name="source">
<?php if ($map): ?>
<paramtype><?php echo $name; ?>&lt;Key, Mapped, H2, P2, Alloc&gt;&amp;&amp;</paramtype>
<?php else: ?>
<paramtype><?php echo $name; ?>&lt;Value, H2, P2, Alloc&gt;&amp;&amp;</paramtype>
<?php endif; ?>
</parameter>
<notes>
<para>Does not support merging with a compatible <code><?php echo $node_partner; ?></code> yet.</para>
</notes>
</method>
<?php /*
<method name="merge">
<template>
<template-type-parameter name="H2">
</template-type-parameter>
<template-type-parameter name="P2">
</template-type-parameter>
</template>
<parameter name="source">
<?php if ($map): ?>
<paramtype><?php echo $node_partner; ?>&lt;Key, Mapped, H2, P2, Alloc&gt;&amp;</paramtype>
<?php else: ?>
<paramtype><?php echo $node_partner; ?>&lt;Value, H2, P2, Alloc&gt;&amp;</paramtype>
<?php endif; ?>
</parameter>
</method>
<method name="merge">
<template>
<template-type-parameter name="H2">
</template-type-parameter>
<template-type-parameter name="P2">
</template-type-parameter>
</template>
<parameter name="source">
<?php if ($map): ?>
<paramtype><?php echo $node_partner; ?>&lt;Key, Mapped, H2, P2, Alloc&gt;&amp;&amp;</paramtype>
<?php else: ?>
<paramtype><?php echo $node_partner; ?>&lt;Value, H2, P2, Alloc&gt;&amp;&amp;</paramtype>
<?php endif; ?>
</parameter>
</method>
*/ ?>
</method-group>
<method-group name="observers">
<method name="hash_function" cv="const">
@@ -1566,7 +1114,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>
@@ -1607,7 +1157,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>
@@ -1654,122 +1206,6 @@ EOL;
<?php
}
function echo_node_handle_docs($map)
{
$type = $map ? 'map' : 'set';
$name = 'node_handle_'.$type;
$full_type = "{$name}&lt;ImplementationDefined&gt;";
?>
<namespace name="unordered">
<class name="<?php echo $name ?>">
<template pack="true">
<template-type-parameter name="ImplementationDefined"/>
</template>
<purpose>
<para>
An object that owns a single element extracted from an
<classname>unordered_<?php echo $type ?></classname> or an
<classname>unordered_multi<?php echo $type ?></classname>, that
can then be inserted into a compatible container type.
</para>
<notes>
<para>
The name and template parameters of this type is implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
<para>
In this version of Boost, <code>node_type</code> is different
for <?php echo $map ?
'<code>unordered_map</code> and <code>unordered_multimap</code>,' :
'<code>unordered_set</code> and <code>unordered_multiset</code>,';
?> this will be fixed in a future version of Boost.
</para>
</notes>
</purpose>
<?php if ($map): ?>
<typedef name="key_type">
<type>typename Container::key_type</type>
</typedef>
<typedef name="mapped_type">
<type>typename Container::mapped_type</type>
</typedef>
<?php else: ?>
<typedef name="value_type">
<type>typename Container::value_type></type>
</typedef>
<?php endif ?>
<typedef name="allocator_type">
<type>typename Container::allocator_type></type>
</typedef>
<constructor specifiers="constexpr" cv="noexcept">
</constructor>
<destructor/>
<constructor cv="noexcept">
<parameter>
<paramtype><?php echo $name; ?> &amp;&amp;</paramtype>
</parameter>
</constructor>
<method name="operator=">
<parameter>
<paramtype><?php echo $name; ?>&amp;&amp;</paramtype>
</parameter>
<type><?php echo $name; ?>&amp;</type>
</method>
<?php if ($map): ?>
<method name="key" cv="const">
<type>key_type&amp;</type>
</method>
<method name="mapped" cv="const">
<type>mapped_type&amp;</type>
</method>
<?php else: ?>
<method name="value" cv="const">
<type>value_type&amp;</type>
</method>
<?php endif; ?>
<method name="get_allocator" cv="const">
<type>allocator_type</type>
</method>
<method name="operator bool" specifiers="explicit" cv="const noexcept">
</method>
<method name="empty" cv="const noexcept">
<type>bool</type>
</method>
<method name="swap" cv="noexcept(ator_traits::propagate_on_container_swap::value)">
<parameter>
<paramtype><?php echo $name; ?>&amp;</paramtype>
</parameter>
<type>void</type>
<notes>
<para>
In C++17 is also <code>noexcept</code> if <code>ator_traits::is_always_equal::value</code> is true.
But we don't support that trait yet.
</para>
</notes>
</method>
<free-function-group name="swap" cv="noexcept(noexcept(x.swap(y)))">
<function name="swap">
<template pack="true">
<template-type-parameter name="ImplementationDefined"/>
</template>
<parameter name="x">
<paramtype><?php echo $full_type; ?>&amp;</paramtype>
</parameter>
<parameter name="y">
<paramtype><?php echo $full_type; ?>&amp;</paramtype>
</parameter>
<type>void</type>
<effects>
<para><code>x.swap(y)</code></para>
</effects>
</function>
</free-function-group>
</class>
</namespace>
<?php
}
?>
<!--
Copyright Daniel James 2006-2009
@@ -1781,7 +1217,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<?php
echo_unordered_docs(false, false);
echo_unordered_docs(false, true);
echo_node_handle_docs(false);
?>
</namespace>
</header>
@@ -1790,7 +1225,6 @@ echo_node_handle_docs(false);
<?php
echo_unordered_docs(true, false);
echo_unordered_docs(true, true);
echo_node_handle_docs(true);
?>
</namespace>
</header>
+64 -1706
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -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
{
+1
View File
@@ -18,6 +18,7 @@
}
struct point_hash
: std::unary_function<point, std::size_t>
{
std::size_t operator()(point const& p) const
{
+2
View File
@@ -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
+799
View File
@@ -0,0 +1,799 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename Types> struct table;
template <typename NodePointer> struct bucket;
struct ptr_bucket;
template <typename Types> struct table_impl;
template <typename Types> struct grouped_table_impl;
}}}
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
// Iterators
//
// all no throw
template <typename NodePointer, typename Value> struct iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value> struct c_iterator;
template <typename NodePointer, typename Value, typename Policy>
struct l_iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value, typename Policy> struct cl_iterator;
// Local Iterators
//
// all no throw
template <typename NodePointer, typename Value, typename Policy>
struct l_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename ConstNodePointer, typename NodePointer2,
typename Value2, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
l_iterator() : ptr_() {}
l_iterator(iterator x, std::size_t b, std::size_t c)
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
Value& operator*() const {
return ptr_->value();
}
Value* operator->() const {
return ptr_->value_ptr();
}
l_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
!= bucket_)
ptr_ = node_pointer();
return *this;
}
l_iterator operator++(int) {
l_iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(l_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(l_iterator x) const {
return ptr_ != x.ptr_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value,
typename Policy>
struct cl_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
<NodePointer, Value, Policy>;
private:
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
cl_iterator() : ptr_() {}
cl_iterator(iterator x, std::size_t b, std::size_t c) :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
NodePointer, Value, Policy> const& x) :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
Value const&
operator*() const {
return ptr_->value();
}
Value const* operator->() const {
return ptr_->value_ptr();
}
cl_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
!= bucket_)
ptr_ = node_pointer();
return *this;
}
cl_iterator operator++(int) {
cl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ == y.ptr_;
}
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ != y.ptr_;
}
};
template <typename NodePointer, typename Value>
struct iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename, typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
typedef NodePointer node_pointer;
node_pointer node_;
public:
iterator() : node_() {}
explicit iterator(node_pointer const& x) : node_(x) {}
Value& operator*() const {
return node_->value();
}
Value* operator->() const {
return &node_->value();
}
iterator& operator++() {
node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
iterator operator++(int) {
iterator tmp(node_);
node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
bool operator==(iterator const& x) const {
return node_ == x.node_;
}
bool operator!=(iterator const& x) const {
return node_ != x.node_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value>
struct c_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::iterator<
NodePointer, Value>;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
friend struct boost::unordered::detail::table;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer node_;
public:
c_iterator() : node_() {}
explicit c_iterator(node_pointer const& x) : node_(x) {}
c_iterator(boost::unordered::iterator_detail::iterator<
NodePointer, Value> const& x) : node_(x.node_) {}
Value const& operator*() const {
return node_->value();
}
Value const* operator->() const {
return &node_->value();
}
c_iterator& operator++() {
node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
c_iterator operator++(int) {
c_iterator tmp(node_);
node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
friend bool operator==(c_iterator const& x, c_iterator const& y) {
return x.node_ == y.node_;
}
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
return x.node_ != y.node_;
}
};
}}}
namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
//
// Node construction
template <typename NodeAlloc>
struct node_constructor
{
private:
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
protected:
node_allocator& alloc_;
private:
node_pointer node_;
bool node_constructed_;
bool value_constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false),
value_constructed_(false)
{
}
~node_constructor();
void construct();
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
construct();
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
}
template <typename A0>
void construct_with_value2(BOOST_FWD_REF(A0) a0)
{
construct();
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
value_constructed_ = true;
}
value_type const& value() const {
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
return node_->value();
}
// no throw
node_pointer release()
{
BOOST_ASSERT(node_ && node_constructed_);
node_pointer p = node_;
node_ = node_pointer();
return p;
}
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
template <typename Alloc>
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (value_constructed_) {
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
}
if (node_constructed_) {
node_allocator_traits::destroy(alloc_,
boost::addressof(*node_));
}
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
template <typename Alloc>
void node_constructor<Alloc>::construct()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
node_allocator_traits::construct(alloc_,
boost::addressof(*node_), node());
node_->init(static_cast<typename node::link_pointer>(node_));
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_);
if (value_constructed_)
{
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
value_constructed_ = false;
}
}
}
///////////////////////////////////////////////////////////////////
//
// Node Holder
//
// Temporary store for nodes. Deletes any that aren't used.
template <typename NodeAlloc>
struct node_holder : private node_constructor<NodeAlloc>
{
private:
typedef node_constructor<NodeAlloc> base;
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
typedef typename node::link_pointer link_pointer;
typedef boost::unordered::iterator_detail::
iterator<node_pointer, value_type> iterator;
node_pointer nodes_;
public:
template <typename Table>
explicit node_holder(Table& b) :
base(b.node_alloc()),
nodes_()
{
if (b.size_) {
typename Table::previous_pointer prev = b.get_previous_start();
nodes_ = static_cast<node_pointer>(prev->next_);
prev->next_ = link_pointer();
b.size_ = 0;
}
}
~node_holder();
template <typename T>
inline void assign_impl(T const& v) {
nodes_->value() = v;
}
template <typename T1, typename T2>
inline void assign_impl(std::pair<T1 const, T2> const& v) {
const_cast<T1&>(nodes_->value().first) = v.first;
nodes_->value().second = v.second;
}
template <typename T>
inline void move_assign_impl(T& v) {
nodes_->value() = boost::move(v);
}
template <typename T1, typename T2>
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
// TODO: Move key as well?
const_cast<T1&>(nodes_->value().first) =
boost::move(const_cast<T1&>(v.first));
nodes_->value().second = boost::move(v.second);
}
node_pointer copy_of(value_type const& v)
{
if (nodes_) {
assign_impl(v);
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
p->init(static_cast<typename node::link_pointer>(p));
p->next_ = link_pointer();
return p;
}
else {
this->construct_with_value2(v);
return base::release();
}
}
node_pointer move_copy_of(value_type& v)
{
if (nodes_) {
move_assign_impl(v);
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
p->init(static_cast<typename node::link_pointer>(p));
p->next_ = link_pointer();
return p;
}
else {
this->construct_with_value2(boost::move(v));
return base::release();
}
}
iterator begin() const
{
return iterator(nodes_);
}
};
template <typename Alloc>
node_holder<Alloc>::~node_holder()
{
while (nodes_) {
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::destroy_value_impl(this->alloc_,
p->value_ptr());
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1);
}
}
///////////////////////////////////////////////////////////////////
//
// Bucket
template <typename NodePointer>
struct bucket
{
typedef NodePointer previous_pointer;
previous_pointer next_;
bucket() : next_() {}
previous_pointer first_from_start()
{
return next_;
}
enum { extra_node = true };
};
struct ptr_bucket
{
typedef ptr_bucket* previous_pointer;
previous_pointer next_;
ptr_bucket() : next_(0) {}
previous_pointer first_from_start()
{
return this;
}
enum { extra_node = false };
};
///////////////////////////////////////////////////////////////////
//
// Hash Policy
//
// Don't really want table to derive from this, but will for now.
template <typename SizeT>
struct prime_policy
{
template <typename Hash, typename T>
static inline SizeT apply_hash(Hash const& hf, T const& x) {
return hf(x);
}
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
return hash % bucket_count;
}
static inline SizeT new_bucket_count(SizeT min) {
return boost::unordered::detail::next_prime(min);
}
static inline SizeT prev_bucket_count(SizeT max) {
return boost::unordered::detail::prev_prime(max);
}
};
template <typename SizeT>
struct mix64_policy
{
template <typename Hash, typename T>
static inline SizeT apply_hash(Hash const& hf, T const& x) {
SizeT key = hf(x);
key = (~key) + (key << 21); // key = (key << 21) - key - 1;
key = key ^ (key >> 24);
key = (key + (key << 3)) + (key << 8); // key * 265
key = key ^ (key >> 14);
key = (key + (key << 2)) + (key << 4); // key * 21
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
return hash & (bucket_count - 1);
}
static inline SizeT new_bucket_count(SizeT min) {
if (min <= 4) return 4;
--min;
min |= min >> 1;
min |= min >> 2;
min |= min >> 4;
min |= min >> 8;
min |= min >> 16;
min |= min >> 32;
return min + 1;
}
static inline SizeT prev_bucket_count(SizeT max) {
max |= max >> 1;
max |= max >> 2;
max |= max >> 4;
max |= max >> 8;
max |= max >> 16;
max |= max >> 32;
return (max >> 1) + 1;
}
};
template <int digits, int radix>
struct pick_policy_impl {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy_impl<64, 2> {
typedef mix64_policy<std::size_t> type;
};
struct pick_policy :
pick_policy_impl<
std::numeric_limits<std::size_t>::digits,
std::numeric_limits<std::size_t>::radix> {};
////////////////////////////////////////////////////////////////////////////
// Functions
// Assigning and swapping the equality and hash function objects
// needs strong exception safety. To implement that normally we'd
// require one of them to be known to not throw and the other to
// guarantee strong exception safety. Unfortunately they both only
// have basic exception safety. So to acheive strong exception
// safety we have storage space for two copies, and assign the new
// copies to the unused space. Then switch to using that to use
// them. This is implemented in 'set_hash_functions' which
// atomically assigns the new function objects in a strongly
// exception safe manner.
template <class H, class P> class set_hash_functions;
template <class H, class P>
class functions
{
friend class boost::unordered::detail::set_hash_functions<H, P>;
functions& operator=(functions const&);
typedef compressed<H, P> function_pair;
typedef typename boost::aligned_storage<
sizeof(function_pair),
boost::alignment_of<function_pair>::value>::type aligned_function;
bool current_; // The currently active functions.
aligned_function funcs_[2];
function_pair const& current() const {
return *static_cast<function_pair const*>(
static_cast<void const*>(&funcs_[current_]));
}
void construct(bool which, H const& hf, P const& eq)
{
new((void*) &funcs_[which]) function_pair(hf, eq);
}
void construct(bool which, function_pair const& f)
{
new((void*) &funcs_[which]) function_pair(f);
}
void destroy(bool which)
{
boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
}
public:
functions(H const& hf, P const& eq)
: current_(false)
{
construct(current_, hf, eq);
}
functions(functions const& bf)
: current_(false)
{
construct(current_, bf.current());
}
~functions() {
this->destroy(current_);
}
H const& hash_function() const {
return current().first();
}
P const& key_eq() const {
return current().second();
}
};
template <class H, class P>
class set_hash_functions
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
functions<H,P>& functions_;
bool tmp_functions_;
public:
set_hash_functions(functions<H,P>& f, H const& h, P const& p)
: functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, h, p);
}
set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
: functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, other.current());
}
~set_hash_functions()
{
functions_.destroy(tmp_functions_);
}
void commit()
{
functions_.current_ = tmp_functions_;
tmp_functions_ = !tmp_functions_;
}
};
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
#if !defined(BOOST_NO_RVALUE_REFERENCES)
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
#else
struct please_ignore_this_overload {
typedef please_ignore_this_overload type;
};
template <typename T>
struct rv_ref_impl {
typedef BOOST_RV_REF(T) type;
};
template <typename T>
struct rv_ref :
boost::detail::if_true<
boost::is_class<T>::value
>::BOOST_NESTED_TEMPLATE then <
boost::unordered::detail::rv_ref_impl<T>,
please_ignore_this_overload
>::type
{};
# define BOOST_UNORDERED_RV_REF(T) \
typename boost::unordered::detail::rv_ref<T>::type
#endif
}}}
#endif
@@ -0,0 +1,781 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T> struct grouped_node;
template <typename T> struct grouped_ptr_node;
template <typename Types> struct grouped_table_impl;
template <typename A, typename T>
struct grouped_node :
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, grouped_node<A, T> >::type::pointer link_pointer;
link_pointer next_;
link_pointer group_prev_;
std::size_t hash_;
grouped_node() :
next_(),
group_prev_(),
hash_(0)
{}
void init(link_pointer self)
{
group_prev_ = self;
}
private:
grouped_node& operator=(grouped_node const&);
};
template <typename T>
struct grouped_ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef ptr_bucket* link_pointer;
link_pointer group_prev_;
std::size_t hash_;
grouped_ptr_node() :
bucket_base(),
group_prev_(0),
hash_(0)
{}
void init(link_pointer self)
{
group_prev_ = self;
}
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
// If the allocator uses raw pointers use grouped_ptr_node
// Otherwise use grouped_node.
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_grouped_node2
{
typedef boost::unordered::detail::grouped_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
>::pointer node_pointer;
typedef boost::unordered::detail::bucket<node_pointer> bucket;
typedef node_pointer link_pointer;
};
template <typename A, typename T>
struct pick_grouped_node2<A, T,
boost::unordered::detail::grouped_ptr_node<T>*,
boost::unordered::detail::ptr_bucket*>
{
typedef boost::unordered::detail::grouped_ptr_node<T> node;
typedef boost::unordered::detail::ptr_bucket bucket;
typedef bucket* link_pointer;
};
template <typename A, typename T>
struct pick_grouped_node
{
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::grouped_ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_grouped_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
};
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 boost::unordered::detail::pick_policy::type policy;
};
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 boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
struct grouped_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::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::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
// Constructors
grouped_table_impl(std::size_t n,
hasher const& hf,
key_equal const& eq,
node_allocator const& a)
: table(n, hf, eq, a)
{}
grouped_table_impl(grouped_table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
grouped_table_impl(grouped_table_impl const& x,
node_allocator const& a)
: table(x, a)
{
this->init(x);
}
grouped_table_impl(grouped_table_impl& x,
boost::unordered::detail::move_tag m)
: table(x, m)
{}
grouped_table_impl(grouped_table_impl& x,
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n.node_) return n;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
}
n = iterator(static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_));
}
}
std::size_t count(key_type const& k) const
{
iterator n = this->find_node(k);
if (!n.node_) return 0;
std::size_t x = 0;
node_pointer it = n.node_;
do {
it = static_cast<node_pointer>(it->group_prev_);
++x;
} while(it != n.node_);
return x;
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
return std::make_pair(
n, n.node_ ? iterator(
static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_
)) : n);
}
// Equality
bool equals(grouped_table_impl const& other) const
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_;)
{
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(static_cast<node_pointer>(
static_cast<node_pointer>(n1.node_->group_prev_)->next_));
iterator end2(static_cast<node_pointer>(
static_cast<node_pointer>(n2.node_->group_prev_)->next_));
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
return true;
}
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if (*n1 != *n2) break;
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(iterator n1a = n1, n2a = n2;;)
{
++n1a;
++n2a;
if (n1a == end1)
{
if (n2a == end2) break;
else return false;
}
if (n2a == end2) return false;
}
iterator start = n1;
for(;n1 != end1; ++n1)
{
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
}
return true;
}
static bool find(iterator n, iterator end, value_type const& v)
{
for(;n != end; ++n)
if (*n == v)
return true;
return false;
}
static std::size_t count_equal(iterator n, iterator end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; ++n)
if (*n == v) ++count;
return count;
}
#else
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if(!extractor::compare_mapped(*n1, *n2))
return false;
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
}
#endif
// Emplace/Insert
static inline void add_after_node(
node_pointer n,
node_pointer pos)
{
n->next_ = static_cast<node_pointer>(pos->group_prev_)->next_;
n->group_prev_ = pos->group_prev_;
static_cast<node_pointer>(pos->group_prev_)->next_ =
static_cast<link_pointer>(n);
pos->group_prev_ = static_cast<link_pointer>(n);
}
inline iterator add_node(
node_constructor& a,
std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
std::size_t next_bucket = policy::to_bucket(
this->bucket_count_,
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket !=
policy::to_bucket(this->bucket_count_, key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(
policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
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_ = static_cast<link_pointer>(n);
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
}
}
++this->size_;
return iterator(n);
}
iterator emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a, key_hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return iterator(emplace_impl(a));
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
// if hash function throws, or inserting > 1 element, basic exception
// safety. Strong otherwise
template <class I>
typename boost::unordered::detail::enable_if_forward<I, void>::type
insert_range(I i, I j)
{
if(i == j) return;
std::size_t distance = boost::unordered::detail::distance(i, j);
if(distance == 1) {
node_constructor a(this->node_alloc());
a.construct_with_value2(*i);
emplace_impl(a);
}
else {
// Only require basic exception safety here
this->reserve_for_insert(this->size_ + distance);
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
}
}
}
template <class I>
typename boost::unordered::detail::disable_if_forward<I, void>::type
insert_range(I i, I j)
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl(a);
}
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
std::size_t erase_key(key_type const& k)
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
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 =
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(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
}
node_pointer pos = static_cast<node_pointer>(prev->next_);
link_pointer end1 =
static_cast<node_pointer>(pos->group_prev_)->next_;
node_pointer end = static_cast<node_pointer>(end1);
prev->next_ = end1;
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_);
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_);
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_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
{
node_pointer next = static_cast<node_pointer>(n->next_);
previous_pointer prev =
static_cast<previous_pointer>(n->group_prev_);
if(prev->next_ != n) {
// The node is at the beginning of a group.
// Find the previous node pointer:
prev = b.next_;
while(prev->next_ != n) {
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
}
// Remove from group
if (next && next->group_prev_ == static_cast<link_pointer>(n))
{
next->group_prev_ = n->group_prev_;
}
}
else if (next && next->group_prev_ == static_cast<link_pointer>(n))
{
// The deleted node is not at the end of the group, so
// change the link from the next node.
next->group_prev_ = n->group_prev_;
}
else {
// The deleted node is at the end of the group, so the
// first node in the group is pointing to it.
// Find that to change its pointer.
node_pointer x = static_cast<node_pointer>(n->group_prev_);
while(x->group_prev_ != static_cast<link_pointer>(n)) {
x = static_cast<node_pointer>(x->group_prev_);
}
x->group_prev_ = n->group_prev_;
}
prev->next_ = static_cast<link_pointer>(next);
return prev;
}
static previous_pointer unlink_nodes(bucket& b,
node_pointer begin, node_pointer end)
{
previous_pointer prev = static_cast<previous_pointer>(
begin->group_prev_);
if(prev->next_ != static_cast<link_pointer>(begin)) {
// The node is at the beginning of a group.
// Find the previous node pointer:
prev = b.next_;
while(prev->next_ != static_cast<link_pointer>(begin))
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
if (end) split_group(end);
}
else {
node_pointer group1 = split_group(begin);
if (end) {
node_pointer group2 = split_group(end);
if(begin == group2) {
link_pointer end1 = group1->group_prev_;
link_pointer end2 = end->group_prev_;
group1->group_prev_ = end2;
end->group_prev_ = end1;
}
}
}
prev->next_ = static_cast<link_pointer>(end);
return prev;
}
// Break a ciruclar list into two, with split as the beginning
// of the second group (if split is at the beginning then don't
// split).
static node_pointer split_group(node_pointer split)
{
// Find first node in group.
node_pointer first = split;
while (static_cast<node_pointer>(first->group_prev_)->next_ ==
static_cast<link_pointer>(first))
first = static_cast<node_pointer>(first->group_prev_);
if(first == split) return split;
link_pointer last = first->group_prev_;
first->group_prev_ = split->group_prev_;
split->group_prev_ = last;
return first;
}
////////////////////////////////////////////////////////////////////////
// fill_buckets
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(
static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_
));
node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = key_hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for (++n; n != group_end; ++n)
{
end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
prev = place_in_bucket(dst, prev, end);
}
}
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
BOOST_ASSERT(this->buckets_);
this->create_buckets(num_buckets);
previous_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev,
static_cast<node_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_));
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static previous_pointer place_in_bucket(table& dst,
previous_pointer prev, node_pointer end)
{
bucket_pointer b = dst.get_bucket(policy::to_bucket(
dst.bucket_count_, end->hash_));
if (!b->next_) {
b->next_ = static_cast<node_pointer>(prev);
return static_cast<previous_pointer>(end);
}
else {
link_pointer next = end->next_;
end->next_ = b->next_->next_;
b->next_->next_ = prev->next_;
prev->next_ = next;
return prev;
}
}
};
}}}
#endif
@@ -0,0 +1,206 @@
// Copyright (C) 2005-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_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/unordered/detail/table.hpp>
namespace boost {
namespace unordered {
namespace detail {
// key extractors
//
// no throw
//
// 'extract_key' is called with the emplace parameters to return a
// key if available or 'no_key' is one isn't and will need to be
// constructed. This could be done by overloading the emplace implementation
// for the different cases, but that's a bit tricky on compilers without
// variadic templates.
struct no_key {
no_key() {}
template <class T> no_key(T const&) {}
};
template <typename Key, typename T>
struct is_key {
template <typename T2>
static choice1::type test(T2 const&);
static choice2::type test(Key const&);
enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
sizeof(choice2::type) };
typedef typename boost::detail::if_true<value>::
BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
};
template <class ValueType>
struct set_extractor
{
typedef ValueType value_type;
typedef ValueType key_type;
static key_type const& extract(key_type const& v)
{
return v;
}
static no_key extract()
{
return no_key();
}
#if !defined(BOOST_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();
}
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>
struct map_extractor
{
typedef ValueType value_type;
typedef typename boost::remove_const<Key>::type key_type;
static key_type const& extract(value_type const& v)
{
return v.first;
}
static key_type const& extract(key_type const& v)
{
return v;
}
template <class Second>
static key_type const& extract(std::pair<key_type, Second> const& v)
{
return v.first;
}
template <class Second>
static key_type const& extract(
std::pair<key_type const, Second> const& v)
{
return v.first;
}
#if !defined(BOOST_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&)
{
return k;
}
static no_key extract()
{
return no_key();
}
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
{
return no_key();
}
#endif
#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&, BOOST_FWD_REF(T2)) \
{ \
return no_key(); \
} \
\
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
}
#else
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&) \
{ \
return no_key(); \
} \
\
template <typename T> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
}
#endif
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
#endif
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;
}
};
}}}
#endif
+8 -44
View File
@@ -1,58 +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
// TODO: Use piecewise construction by default? Is it safe to assume that an
// unknown library has it?
#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
namespace boost
{
};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
namespace unordered
{
struct piecewise_construct_t {};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
}
}
File diff suppressed because it is too large Load Diff
-64
View File
@@ -1,64 +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/detail/implementation.hpp>
#include <boost/unordered/unordered_map_fwd.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 std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K const const_key_type;
typedef typename ::boost::unordered::detail::rebind_wrap<A,
value_type>::type value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, 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<types> table;
typedef boost::unordered::detail::map_extractor<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> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
typedef boost::unordered::insert_return_type_map<node, K, M, A>
insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map
{
typedef boost::unordered_map<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap
{
typedef boost::unordered_multimap<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
-63
View File
@@ -1,63 +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/detail/implementation.hpp>
#include <boost/unordered/unordered_set_fwd.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 T value_type;
typedef H hasher;
typedef P key_equal;
typedef T const const_key_type;
typedef typename ::boost::unordered::detail::rebind_wrap<A,
value_type>::type value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, 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<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> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type;
typedef boost::unordered::insert_return_type_set<node, T, A>
insert_return_type;
};
template <typename T, typename H, typename P, typename A> class instantiate_set
{
typedef boost::unordered_set<T, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename T, typename H, typename P, typename A>
class instantiate_multiset
{
typedef boost::unordered_multiset<T, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
+907
View File
@@ -0,0 +1,907 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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_DETAIL_ALL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#include <boost/unordered/detail/buckets.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cmath>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// convert double to std::size_t
inline std::size_t double_to_size(double f)
{
return f >= static_cast<double>(
(std::numeric_limits<std::size_t>::max)()) ?
(std::numeric_limits<std::size_t>::max)() :
static_cast<std::size_t>(f);
}
// The space used to store values in a node.
template <typename ValueType>
struct value_base
{
typedef ValueType value_type;
typename boost::aligned_storage<
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
void* address() {
return this;
}
value_type& value() {
return *(ValueType*) this;
}
value_type* value_ptr() {
return (ValueType*) this;
}
private:
value_base& operator=(value_base const&);
};
template <typename NodeAlloc>
struct copy_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type const& v)
{
constructor.construct_with_value2(v);
return constructor.release();
}
};
template <typename NodeAlloc>
struct move_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit move_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type& v)
{
constructor.construct_with_value2(boost::move(v));
return constructor.release();
}
};
template <typename Buckets>
struct assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type const& v)
{
return holder.copy_of(v);
}
};
template <typename Buckets>
struct move_assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit move_assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type& v)
{
return holder.move_copy_of(v);
}
};
template <typename Types>
struct table :
Types::policy,
boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal>
{
private:
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;
typedef typename Types::extractor extractor;
typedef typename Types::value_type value_type;
typedef typename Types::table table_impl;
typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy;
typedef boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal> 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 typename bucket::previous_pointer
previous_pointer;
typedef boost::unordered::detail::node_constructor<node_allocator>
node_constructor;
typedef boost::unordered::iterator_detail::
iterator<node_pointer, value_type> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node_pointer, value_type, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<const_node_pointer, node_pointer, value_type, policy>
cl_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_;
////////////////////////////////////////////////////////////////////////
// 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);
}
previous_pointer get_previous_start() const
{
return get_bucket(bucket_count_)->first_from_start();
}
previous_pointer get_previous_start(std::size_t bucket_index) const
{
return get_bucket(bucket_index)->next_;
}
iterator begin() const
{
return size_ ? iterator(static_cast<node_pointer>(
get_previous_start()->next_)) : iterator();
}
iterator begin(std::size_t bucket_index) const
{
if (!size_) return iterator();
previous_pointer prev = get_previous_start(bucket_index);
return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
iterator();
}
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
{
iterator it = begin(index);
if (!it.node_) return 0;
std::size_t count = 0;
while(it.node_ && policy::to_bucket(
bucket_count_, it.node_->hash_) == index)
{
++count;
++it;
}
return count;
}
////////////////////////////////////////////////////////////////////////
// Load methods
std::size_t max_size() const
{
using namespace std;
// size < mlf_ * count
return boost::unordered::detail::double_to_size(ceil(
static_cast<double>(mlf_) *
static_cast<double>(max_bucket_count())
)) - 1;
}
void recalculate_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;
}
void max_load_factor(float z)
{
BOOST_ASSERT(z > 0);
mlf_ = (std::max)(z, minimum_max_load_factor);
recalculate_max_load();
}
std::size_t min_buckets_for_size(std::size_t size) const
{
BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
using namespace std;
// From 6.3.1/13:
// size < mlf_ * count
// => count > size / mlf_
//
// Or from rehash post-condition:
// count > size / mlf_
return policy::new_bucket_count(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_))) + 1);
}
////////////////////////////////////////////////////////////////////////
// Constructors
table(std::size_t num_buckets,
hasher const& hf,
key_equal const& eq,
node_allocator const& a) :
functions(hf, eq),
allocators_(a,a),
bucket_count_(policy::new_bucket_count(num_buckets)),
size_(0),
mlf_(1.0f),
max_load_(0),
buckets_()
{}
table(table const& x, node_allocator const& a) :
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),
allocators_(x.allocators_, m),
bucket_count_(x.bucket_count_),
size_(x.size_),
mlf_(x.mlf_),
max_load_(x.max_load_),
buckets_(x.buckets_)
{
x.buckets_ = bucket_pointer();
x.size_ = 0;
x.max_load_ = 0;
}
table(table& x, node_allocator const& a,
boost::unordered::detail::move_tag) :
functions(x),
allocators_(a, a),
bucket_count_(x.bucket_count_),
size_(0),
mlf_(x.mlf_),
max_load_(x.max_load_),
buckets_()
{}
////////////////////////////////////////////////////////////////////////
// Initialisation.
void init(table const& x)
{
if (x.size_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
void move_init(table& x)
{
if(node_alloc() == x.node_alloc()) {
move_buckets_from(x);
}
else if(x.size_) {
// TODO: Could pick new bucket size?
create_buckets(bucket_count_);
move_nodes<node_allocator> move(node_alloc());
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, move);
}
}
////////////////////////////////////////////////////////////////////////
// Create buckets
void create_buckets(std::size_t new_count)
{
boost::unordered::detail::array_constructor<bucket_allocator>
constructor(bucket_alloc());
// Creates an extra bucket to act as the start node.
constructor.construct(bucket(), new_count + 1);
if (buckets_)
{
// Copy the nodes to the new buckets, including the dummy
// node if there is one.
(constructor.get() +
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.construct();
(constructor.get() +
static_cast<std::ptrdiff_t>(new_count))->next_ =
a.release();
}
bucket_count_ = new_count;
buckets_ = constructor.release();
recalculate_max_load();
}
////////////////////////////////////////////////////////////////////////
// Swap and Move
void swap_allocators(table& other, false_type)
{
// 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)
{
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.
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();
}
void move_buckets_from(table& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
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(c_iterator n)
{
boost::unordered::detail::destroy_value_impl(node_alloc(),
n.node_->value_ptr());
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n.node_));
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
--size_;
}
std::size_t delete_nodes(c_iterator begin, c_iterator end)
{
std::size_t count = 0;
while(begin != end) {
c_iterator n = begin;
++begin;
delete_node(n);
++count;
}
return count;
}
void delete_buckets()
{
if(buckets_) {
delete_nodes(begin(), iterator());
if (bucket::extra_node) {
node_pointer n = static_cast<node_pointer>(
get_bucket(bucket_count_)->next_);
node_allocator_traits::destroy(node_alloc(),
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(begin(), iterator());
get_previous_start()->next_ = 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)
{
bucket_allocator_traits::destroy(bucket_alloc(),
boost::addressof(*it));
}
bucket_allocator_traits::deallocate(bucket_alloc(),
buckets_, bucket_count_ + 1);
}
////////////////////////////////////////////////////////////////////////
// Fix buckets after erase
// This is called after erasing a node or group of nodes to fix up
// the bucket pointers.
void fix_buckets(bucket_pointer this_bucket,
previous_pointer prev, node_pointer next)
{
if (!next)
{
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
}
else
{
bucket_pointer next_bucket = get_bucket(
policy::to_bucket(bucket_count_, next->hash_));
if (next_bucket != this_bucket)
{
next_bucket->next_ = prev;
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
}
}
}
// This is called after erasing a range of nodes to fix any bucket
// pointers into that range.
void fix_buckets_range(std::size_t bucket_index,
previous_pointer prev, node_pointer begin, node_pointer end)
{
node_pointer n = begin;
// If we're not at the start of the current bucket, then
// go to the start of the next bucket.
if (get_bucket(bucket_index)->next_ != prev)
{
for(;;) {
n = static_cast<node_pointer>(n->next_);
if (n == end) {
if (n) {
std::size_t new_bucket_index =
policy::to_bucket(bucket_count_, n->hash_);
if (bucket_index != new_bucket_index) {
get_bucket(new_bucket_index)->next_ = prev;
}
}
return;
}
std::size_t new_bucket_index =
policy::to_bucket(bucket_count_, n->hash_);
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
break;
}
}
}
// Iterate through the remaining nodes, clearing out the bucket
// pointers.
get_bucket(bucket_index)->next_ = previous_pointer();
for(;;) {
n = static_cast<node_pointer>(n->next_);
if (n == end) break;
std::size_t new_bucket_index =
policy::to_bucket(bucket_count_, n->hash_);
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
get_bucket(bucket_index)->next_ = previous_pointer();
}
};
// Finally fix the bucket containing the trailing node.
if (n) {
get_bucket(
policy::to_bucket(bucket_count_, n->hash_))->next_
= prev;
}
}
////////////////////////////////////////////////////////////////////////
// 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>());
}
}
void assign(table const& x, false_type)
{
// Strong exception safety.
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
if (!size_ && !x.size_) return;
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
}
else {
clear_buckets();
}
// assign_nodes takes ownership of the container's elements,
// assigning to them if possible, and deleting any that are
// left over.
assign_nodes<table> assign(*this);
table_impl::fill_buckets(x.begin(), *this, assign);
}
void assign(table const& x, true_type)
{
if (node_alloc() == x.node_alloc()) {
allocators_.assign(x.allocators_);
assign(x, false_type());
}
else {
boost::unordered::detail::set_hash_functions<hasher, key_equal>
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_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
}
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>());
}
}
void move_assign(table& x, true_type)
{
delete_buckets();
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();
move_assign_no_alloc(x);
}
else {
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
if (!size_ && !x.size_) return;
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
}
else {
clear_buckets();
}
// move_assign_nodes takes ownership of the container's
// elements, assigning to them if possible, and deleting
// any that are left over.
move_assign_nodes<table> assign(*this);
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, assign);
}
}
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.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
// Accessors
key_type const& get_key(value_type const& x) const
{
return extractor::extract(x);
}
std::size_t hash(key_type const& k) const
{
return policy::apply_hash(this->hash_function(), k);
}
// Find Node
template <typename Key, typename Hash, typename Pred>
iterator generic_find_node(
Key const& k,
Hash const& hf,
Pred const& eq) const
{
return static_cast<table_impl const*>(this)->
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
iterator find_node(
std::size_t key_hash,
key_type const& k) const
{
return static_cast<table_impl const*>(this)->
find_node_impl(key_hash, k, this->key_eq());
}
iterator find_node(key_type const& k) const
{
return static_cast<table_impl const*>(this)->
find_node_impl(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
void reserve_for_insert(std::size_t);
void rehash(std::size_t);
void reserve(std::size_t);
};
////////////////////////////////////////////////////////////////////////////
// Reserve & Rehash
// basic exception safety
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)));
}
// 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_)
static_cast<table_impl*>(this)->rehash_impl(num_buckets);
}
}
// if hash function throws, basic exception safety
// strong otherwise.
template <typename Types>
inline void table<Types>::rehash(std::size_t min_buckets)
{
using namespace std;
if(!size_) {
delete_buckets();
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>(mlf_))) + 1));
if(min_buckets != bucket_count_)
static_cast<table_impl*>(this)->rehash_impl(min_buckets);
}
}
template <typename Types>
inline void table<Types>::reserve(std::size_t num_elements)
{
rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(num_elements) / mlf_)));
}
}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
+651
View File
@@ -0,0 +1,651 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#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>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T> struct unique_node;
template <typename T> struct ptr_node;
template <typename Types> struct table_impl;
template <typename A, typename T>
struct unique_node :
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type::pointer link_pointer;
link_pointer next_;
std::size_t hash_;
unique_node() :
next_(),
hash_(0)
{}
void init(link_pointer)
{
}
private:
unique_node& operator=(unique_node const&);
};
template <typename T>
struct ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
ptr_node() :
bucket_base(),
hash_(0)
{}
void init(link_pointer)
{
}
private:
ptr_node& operator=(ptr_node const&);
};
// If the allocator uses raw pointers use ptr_node
// Otherwise use node.
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_node2
{
typedef boost::unordered::detail::unique_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
>::pointer node_pointer;
typedef boost::unordered::detail::bucket<node_pointer> bucket;
typedef node_pointer link_pointer;
};
template <typename A, typename T>
struct pick_node2<A, T,
boost::unordered::detail::ptr_node<T>*,
boost::unordered::detail::ptr_bucket*>
{
typedef boost::unordered::detail::ptr_node<T> node;
typedef boost::unordered::detail::ptr_bucket bucket;
typedef bucket* link_pointer;
};
template <typename A, typename T>
struct pick_node
{
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
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 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 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 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 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::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::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
typedef std::pair<iterator, bool> emplace_return;
// Constructors
table_impl(std::size_t n,
hasher const& hf,
key_equal const& eq,
node_allocator const& a)
: table(n, hf, eq, a)
{}
table_impl(table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
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)
: table(x, m)
{}
table_impl(table_impl& x,
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n.node_) return n;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
}
++n;
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k).node_ ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
iterator it = this->find_node(k);
if (it.node_) return *it;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
}
// equals
bool equals(table_impl const& other) const
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_; ++n1)
{
iterator n2 = other.find_matching_node(n1);
#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;
}
// Emplace/Insert
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(
policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
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_ = static_cast<link_pointer>(n);
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
}
++this->size_;
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);
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_with_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_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(this->begin(), false);
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_impl(
extractor::extract(args.a0, args.a1),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
#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);
}
#endif
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);
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_with_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);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
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)
{
// 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_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
//
// if hash function throws, or inserting > 1 element, basic exception
// safety strong otherwise
template <class InputIt>
void insert_range(InputIt i, InputIt j)
{
if(i != j)
return insert_range_impl(extractor::extract(*i), i, j);
}
template <class InputIt>
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
insert_range_impl2(a, k, i, j);
while(++i != j) {
// 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.
//
// TODO: Might be worth storing the value_type instead of the
// 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(a, extractor::extract(*i), i, j);
}
}
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);
iterator pos = this->find_node(key_hash, k);
if (!pos.node_) {
a.construct_with_value2(*i);
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
// Nothing after this point can throw.
this->add_node(a, key_hash);
}
}
template <class InputIt>
void insert_range_impl(no_key, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
do {
a.construct_with_value2(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
std::size_t erase_key(key_type const& k)
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
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 =
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(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = static_cast<previous_pointer>(prev->next_);
}
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_);
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_);
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_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
{
return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
}
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
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
node_pointer node = creator.create(*n);
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_);
this->create_buckets(num_buckets);
previous_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev);
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static previous_pointer place_in_bucket(table& dst,
previous_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(
table::to_bucket(dst.bucket_count_, n->hash_));
if (!b->next_) {
b->next_ = prev;
return static_cast<previous_pointer>(n);
}
else {
prev->next_ = n->next_;
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
return prev;
}
}
};
}}}
#endif
+260
View File
@@ -0,0 +1,260 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_empty.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/swap.hpp>
namespace boost { namespace unordered { namespace detail {
static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11;
struct move_tag {};
struct empty_emplace {};
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
template <typename I>
struct is_forward :
boost::is_convertible<
typename boost::iterator_traversal<I>::type,
boost::forward_traversal_tag>
{};
template <typename I, typename ReturnType>
struct enable_if_forward :
boost::enable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
template <typename I, typename ReturnType>
struct disable_if_forward :
boost::disable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
////////////////////////////////////////////////////////////////////////////
// primes
#define BOOST_UNORDERED_PRIMES \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
(1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
(50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
(1610612741ul)(3221225473ul)(4294967291ul)
template<class T> struct prime_list_template
{
static std::size_t const value[];
#if !defined(SUNPRO_CC)
static std::ptrdiff_t const length;
#else
static std::ptrdiff_t const length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
};
template<class T>
std::size_t const prime_list_template<T>::value[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
};
#if !defined(SUNPRO_CC)
template<class T>
std::ptrdiff_t const prime_list_template<T>::length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
#undef BOOST_UNORDERED_PRIMES
typedef prime_list_template<std::size_t> prime_list;
// no throw
inline std::size_t next_prime(std::size_t num) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::lower_bound(prime_list_begin, prime_list_end, num);
if(bound == prime_list_end)
bound--;
return *bound;
}
// no throw
inline std::size_t prev_prime(std::size_t num) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::upper_bound(prime_list_begin,prime_list_end, num);
if(bound != prime_list_begin)
bound--;
return *bound;
}
////////////////////////////////////////////////////////////////////////////
// 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 typename
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
insert_size(I i, I j)
{
return std::distance(i, j);
}
template <class I>
inline typename
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
insert_size(I, I)
{
return 1;
}
template <class I>
inline std::size_t initial_size(I i, I j,
std::size_t num_buckets =
boost::unordered::detail::default_bucket_count)
{
// TODO: Why +1?
return (std::max)(
boost::unordered::detail::insert_size(i, j) + 1,
num_buckets);
}
////////////////////////////////////////////////////////////////////////////
// compressed
template <typename T, int Index>
struct compressed_base : private T
{
compressed_base(T const& x) : T(x) {}
compressed_base(T& x, move_tag) : T(boost::move(x)) {}
T& get() { return *this; }
T const& get() const { return *this; }
};
template <typename T, int Index>
struct uncompressed_base
{
uncompressed_base(T const& x) : value_(x) {}
uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
T& get() { return value_; }
T const& get() const { return value_; }
private:
T value_;
};
template <typename T, int Index>
struct generate_base
: boost::detail::if_true<
boost::is_empty<T>::value
>:: BOOST_NESTED_TEMPLATE then<
boost::unordered::detail::compressed_base<T, Index>,
boost::unordered::detail::uncompressed_base<T, Index>
>
{};
template <typename T1, typename T2>
struct compressed
: private boost::unordered::detail::generate_base<T1, 1>::type,
private boost::unordered::detail::generate_base<T2, 2>::type
{
typedef typename generate_base<T1, 1>::type base1;
typedef typename generate_base<T2, 2>::type base2;
typedef T1 first_type;
typedef T2 second_type;
first_type& first() {
return static_cast<base1*>(this)->get();
}
first_type const& first() const {
return static_cast<base1 const*>(this)->get();
}
second_type& second() {
return static_cast<base2*>(this)->get();
}
second_type const& second() const {
return static_cast<base2 const*>(this)->get();
}
template <typename First, typename Second>
compressed(First const& x1, Second const& x2)
: base1(x1), base2(x2) {}
compressed(compressed const& x)
: base1(x.first()), base2(x.second()) {}
compressed(compressed& x, move_tag m)
: base1(x.first(), m), base2(x.second(), m) {}
void assign(compressed const& x)
{
first() = x.first();
second() = x.second();
}
void move_assign(compressed& x)
{
first() = boost::move(x.first());
second() = boost::move(x.second());
}
void swap(compressed& x)
{
boost::swap(first(), x.first());
boost::swap(second(), x.second());
}
private:
// Prevent assignment just to make use of assign or
// move_assign explicit.
compressed& operator=(compressed const&);
};
}}}
#endif
File diff suppressed because it is too large Load Diff
+45 -44
View File
@@ -6,59 +6,60 @@
#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>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
namespace boost
{
namespace unordered
{
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>&,
unordered_multimap<K, T, H, P, A>&);
}
template <class N, class K, class T, class A> class node_handle_map;
template <class N, class K, class T, class A> struct insert_return_type_map;
}
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
}
#endif
File diff suppressed because it is too large Load Diff
+43 -41
View File
@@ -6,56 +6,58 @@
#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>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
namespace boost
{
namespace unordered
{
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T, class H, class P, class A>
inline bool operator==(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class T, class H, class P, class A>
inline bool operator==(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2);
}
template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set;
}
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
}
#endif
+2 -3
View File
@@ -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>
+2 -3
View File
@@ -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>
-17
View File
@@ -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 -89
View File
@@ -5,92 +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"
<toolset>gcc:<c++-template-depth>500
;
#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 : : : <define>BOOST_UNORDERED_SUPPRESS_DEPRECATED ]
[ run unordered/erase_equiv_tests.cpp ]
[ run unordered/extract_tests.cpp ]
[ run unordered/node_handle_tests.cpp ]
[ run unordered/merge_tests.cpp ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MAP : insert_node_type_fail_map ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTIMAP : insert_node_type_fail_multimap ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_SET : insert_node_type_fail_set ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTISET : insert_node_type_fail_multiset ]
[ 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/detail_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 ]
[ run exception/merge_exception_tests.cpp framework ]
;
build-project unordered ;
build-project exception ;
+34
View File
@@ -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 ]
;
+45 -119
View File
@@ -4,64 +4,55 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
template <class T> struct self_assign_base : public test::exception_base
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, test::limited_range)
{
}
self_assign_base(int count = 0) : values(count) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const
{
x = x;
DISABLE_EXCEPTIONS;
test::check_container(x, values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x = x; }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
test::check_equivalent_keys(x);
}
{ test::check_equivalent_keys(x); }
};
template <class T> struct self_assign_test1 : self_assign_base<T>
{
};
template <class T>
struct self_assign_test1 : self_assign_base<T> {};
template <class T> struct self_assign_test2 : self_assign_base<T>
template <class T>
struct self_assign_test2 : self_assign_base<T>
{
self_assign_test2() : self_assign_base<T>(100) {}
};
template <class T> struct assign_base : public test::exception_base
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;
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))
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
float mlf1 = 1.0, float mlf2 = 1.0) :
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))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
@@ -69,117 +60,52 @@ template <class T> struct assign_base : public test::exception_base
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const
{
x1 = y;
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
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.
// internal structure is hidden, this exposes it.
T& y = const_cast<T&>(x1);
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
y.emplace(*x_values.begin());
test::check_equivalent_keys(y);
}
}
};
template <class T> struct assign_values : assign_base<T>
template <class T>
struct assign_test1 : assign_base<T>
{
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
test::random_generator gen = test::default_generator, float mlf1 = 1.0,
float mlf2 = 1.0)
: assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1, gen);
this->y_values.fill(count2, gen);
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>
template <class 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>
template <class 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_test2a : assign_values<T>
template <class T>
struct assign_test4 : assign_base<T>
{
assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
};
template <class T> struct assign_test3 : assign_values<T>
template <class T>
struct assign_test5 : assign_base<T>
{
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
};
template <class T> struct assign_test3a : assign_values<T>
{
assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
};
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_test4b : assign_values<T>
{
assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
};
template <class T> struct assign_test5 : assign_values<T>
{
assign_test5()
: assign_values<T>(5, 60, 0, 0, test::default_generator, 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());
}
};
// clang-format off
EXCEPTION_TESTS_REPEAT(5,
RUN_EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test2a)
(assign_test3)(assign_test3a)
(assign_test4)(assign_test4a)(assign_test4b)
(assign_test5)
(equivalent_test1),
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+78 -113
View File
@@ -4,11 +4,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/input_iterator.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/input_iterator.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
@@ -22,190 +19,158 @@ struct objects
test::exception::allocator<test::exception::object> allocator;
};
template <class T> struct construct_test1 : public objects, test::exception_base
template <class T>
struct construct_test1 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x;
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct construct_test2 : public objects, test::exception_base
template <class T>
struct construct_test2 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x(300);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct construct_test3 : public objects, test::exception_base
template <class T>
struct construct_test3 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x(0, hash);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct construct_test4 : public objects, test::exception_base
template <class T>
struct construct_test4 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x(0, hash, equal_to);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct construct_test5 : public objects, test::exception_base
template <class T>
struct construct_test5 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x(50, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct construct_test6 : public objects, test::exception_base
template <class T>
struct construct_test6 : public objects, test::exception_base
{
void run() const
{
void run() const {
T x(allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct range : public test::exception_base
template <class T>
struct range : public test::exception_base
{
test::random_values<T> values;
range() : values(5, test::limited_range) {}
range(unsigned int count) : values(count, test::limited_range) {}
range() : values(5) {}
range(unsigned int count) : values(count) {}
};
template <class T> struct range_construct_test1 : public range<T>, objects
template <class T>
struct range_construct_test1 : public range<T>, objects
{
void run() const
{
void run() const {
T x(this->values.begin(), this->values.end());
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct range_construct_test2 : public range<T>, objects
template <class T>
struct range_construct_test2 : public range<T>, objects
{
void run() const
{
void run() const {
T x(this->values.begin(), this->values.end(), 0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct range_construct_test3 : public range<T>, objects
template <class T>
struct range_construct_test3 : public range<T>, objects
{
void run() const
{
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
template <class T> struct range_construct_test4 : public range<T>, objects
template <class T>
struct range_construct_test4 : public range<T>, objects
{
void run() const
{
void run() const {
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
avoid_unused_warning(x);
}
};
// Need to run at least one test with a fairly large number
// of objects in case it triggers a rehash.
template <class T> struct range_construct_test5 : public range<T>, objects
template <class T>
struct range_construct_test5 : public range<T>, objects
{
range_construct_test5() : range<T>(60) {}
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash, equal_to,
allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
void run() const {
T x(this->values.begin(), this->values.end(), 0,
hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
template <class T> struct input_range_construct_test : public range<T>, objects
template <class T>
struct input_range_construct_test : public range<T>, objects
{
input_range_construct_test() : range<T>(60) {}
void run() const
{
void run() const {
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
begin = this->values.begin(),
end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
begin = this->values.begin(), end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
template <class T> struct copy_range_construct_test : public range<T>, objects
template <class T>
struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
void run() const
{
void run() const {
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()), 0, hash, equal_to,
allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
test::copy_iterator(this->values.end()),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)(
construct_test5)(construct_test6)(range_construct_test1)(
range_construct_test2)(range_construct_test3)(range_construct_test4)(
range_construct_test5)(input_range_construct_test)(
copy_range_construct_test),
RUN_EXCEPTION_TESTS(
(construct_test1)
(construct_test2)
(construct_test3)
(construct_test4)
(construct_test5)
(construct_test6)
(range_construct_test1)
(range_construct_test2)
(range_construct_test3)
(range_construct_test4)
(range_construct_test5)
(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
RUN_TESTS()
+20 -29
View File
@@ -3,42 +3,33 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../objects/exception.hpp"
typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_set;
typedef boost::unordered_multiset<test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<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;
typedef boost::unordered_multimap<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_multimap;
typedef boost::unordered_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_set;
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> > test_set;
typedef boost::unordered_multiset<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_pair_multiset;
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator2<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;
typedef boost::unordered_multimap<
test::exception::object,
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> > test_multimap;
#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
#define CONTAINER_PAIR_SEQ \
(test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
+19 -61
View File
@@ -4,87 +4,53 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t initialize_seed(73041);
template <class T> struct copy_test1 : public test::exception_base
template <class T>
struct copy_test1 : public test::exception_base
{
T x;
void run() const
{
void run() const {
T y(x);
DISABLE_EXCEPTIONS;
BOOST_TEST(y.empty());
test::check_equivalent_keys(y);
avoid_unused_warning(y);
}
};
template <class T> struct copy_test2 : public test::exception_base
template <class T>
struct copy_test2 : public test::exception_base
{
test::random_values<T> values;
T x;
copy_test2()
: values(5, test::limited_range), x(values.begin(), values.end())
{
}
copy_test2() : values(5), x(values.begin(), values.end()) {}
void run() const
{
void run() const {
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
avoid_unused_warning(y);
}
};
template <class T> struct copy_test3 : public test::exception_base
template <class T>
struct copy_test3 : public test::exception_base
{
test::random_values<T> values;
T x;
copy_test3() : values(100), x(values.begin(), values.end()) {}
void run() const
{
void run() const {
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
avoid_unused_warning(y);
}
};
template <class T> struct copy_test3a : public test::exception_base
{
test::random_values<T> values;
T x;
copy_test3a()
: values(100, test::limited_range), x(values.begin(), values.end())
{
}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
};
template <class T> struct copy_with_allocator_test : public test::exception_base
template <class T>
struct copy_with_allocator_test : public test::exception_base
{
test::random_values<T> values;
T x;
@@ -92,20 +58,12 @@ template <class T> struct copy_with_allocator_test : public test::exception_base
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
void run() const
{
void run() const {
T y(x, allocator);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
avoid_unused_warning(y);
}
};
// clang-format off
EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_test3a)(copy_with_allocator_test),
RUN_EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+21 -23
View File
@@ -4,53 +4,51 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
test::seed_t initialize_seed(835193);
template <class T> struct erase_test_base : public test::exception_base
template <class T>
struct erase_test_base : public test::exception_base
{
test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
{
}
erase_test_base(unsigned int count = 5) : values(count) {}
typedef T data_type;
data_type init() const { return T(values.begin(), values.end()); }
data_type init() const {
return T(values.begin(), values.end());
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
BOOST_TEST(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
test::check_equivalent_keys(x);
}
};
template <class T> struct erase_by_key_test1 : public erase_test_base<T>
template <class T>
struct erase_by_key_test1 : public erase_test_base<T>
{
void run(T& x) const
{
typedef BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
iterator;
typedef BOOST_DEDUCED_TYPENAME
test::random_values<T>::const_iterator iterator;
for (iterator it = this->values.begin(), end = this->values.end();
it != end; ++it) {
for(iterator it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
x.erase(test::get_key<T>(*it));
}
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
RUN_TESTS()
RUN_EXCEPTION_TESTS(
(erase_by_key_test1),
CONTAINER_SEQ)
+205 -374
View File
@@ -2,414 +2,245 @@
// 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 "./containers.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <cmath>
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include <boost/utility.hpp>
#include <cmath>
test::seed_t initialize_seed(747373);
// Fill in a container so that it's about to rehash
template <typename T> void rehash_prep(T& x)
template <class T>
struct insert_test_base : public test::exception_base
{
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
test::random_values<T> values;
insert_test_base(unsigned int count = 5) : values(count) {}
x.max_load_factor(0.25);
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);
test::random_values<T> v(initial_elements);
x.insert(v.begin(), v.end());
BOOST_TEST(bucket_count == x.bucket_count());
}
typedef T data_type;
typedef test::strong<T> strong_type;
// Overload to generate inserters that need type information.
data_type init() const {
return T();
}
template <typename Inserter, typename T>
Inserter generate(Inserter inserter, T&)
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const
{
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class T>
struct emplace_test1 : public insert_test_base<T>
{
return inserter;
}
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
// Get the iterator returned from an insert/emplace.
template <typename T> T get_iterator(T const& x) { return x; }
template <typename T> T get_iterator(std::pair<T, bool> const& x)
{
return x.first;
}
// Generic insert exception test for typical single element inserts..
template <typename T, typename Inserter, typename Values>
void insert_exception_test_impl(T x, Inserter insert, Values const& v)
{
test::strong<T> strong;
test::ordered<T> tracker;
tracker.insert(x.begin(), x.end());
try {
ENABLE_EXCEPTIONS;
for (typename Values::const_iterator it = v.begin(); it != v.end();
++it) {
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
insert(x, it);
}
} catch (...) {
test::check_equivalent_keys(x);
insert.exception_check(x, strong);
throw;
}
test::check_equivalent_keys(x);
insert.track(tracker, v.begin(), v.end());
tracker.compare(x);
}
// Simple insert exception test
template <typename T, typename Inserter>
void insert_exception_test(T*, Inserter insert, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen);
T x;
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
}
}
// Insert into a container which is about to hit its max load, so that it
// rehashes.
template <typename T, typename Inserter>
void insert_rehash_exception_test(
T*, Inserter insert, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
T x;
rehash_prep(x);
test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
}
}
// Various methods for inserting a single element
struct inserter_base
{
template <typename T> void exception_check(T& x, test::strong<T>& strong)
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
}
template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end)
{
tracker.insert(begin, end);
}
};
struct insert_lvalue_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(*it);
}
} insert_lvalue;
struct insert_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.begin(), *it);
}
} insert_lvalue_begin;
struct insert_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.end(), *it);
}
} insert_lvalue_end;
struct insert_lvalue_pos_type
{
template <typename T> struct impl : inserter_base
{
typename T::iterator pos;
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.insert(pos, *it));
}
};
template <typename T> friend impl<T> generate(insert_lvalue_pos_type, T& x)
{
return impl<T>(x);
}
} insert_lvalue_pos;
struct insert_single_item_range_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(it, test::next(it));
}
} insert_single_item_range;
struct emplace_lvalue_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace(*it);
}
} emplace_lvalue;
struct emplace_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.begin(), *it);
}
} emplace_lvalue_begin;
struct emplace_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.end(), *it);
}
} emplace_lvalue_end;
struct emplace_lvalue_pos_type
{
template <typename T> struct impl : inserter_base
{
typename T::iterator pos;
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.emplace_hint(pos, *it));
}
};
template <typename T> friend impl<T> generate(emplace_lvalue_pos_type, T& x)
{
return impl<T>(x);
}
} emplace_lvalue_pos;
// Run the exception tests in various combinations.
test_set* test_set_;
test_multiset* test_multiset_;
test_map* test_map_;
test_multimap* test_multimap_;
using test::default_generator;
using test::limited_range;
using test::generate_collisions;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
// Repeat insert tests with pairs
struct pair_emplace_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(it->first), boost::make_tuple(it->second));
}
} pair_emplace;
struct pair_emplace2_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(it->first),
boost::make_tuple(it->second.tag1_, it->second.tag2_));
}
} pair_emplace2;
test_pair_set* test_pair_set_;
test_pair_multiset* test_pair_multiset_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
// Test inserting using operator[]
struct try_emplace_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.try_emplace(it->first, it->second);
}
} try_emplace;
struct try_emplace2_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
}
} try_emplace2;
struct map_inserter_base
{
template <typename T> void exception_check(T& x, test::strong<T>& strong)
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos &&
scope.find("::operator=") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
}
template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end)
{
for (; begin != end; ++begin) {
tracker[begin->first] = begin->second;
x.emplace(*it);
}
}
};
struct map_insert_operator_type : map_inserter_base
#endif
template <class T>
struct insert_test1 : public insert_test_base<T>
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x[it->first] = it->second;
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
}
} map_insert_operator;
};
struct map_insert_or_assign_type : map_inserter_base
template <class T>
struct insert_test2 : public insert_test_base<T>
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert_or_assign(it->first, it->second);
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
} map_insert_or_assign;
};
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
// Range insert tests
template <typename T, typename Values>
void insert_range_exception_test_impl(T x, Values const& v)
template <class T>
struct insert_test3 : public insert_test_base<T>
{
test::ordered<T> tracker;
tracker.insert(x.begin(), x.end());
void run(T& x) const {
x.insert(this->values.begin(), this->values.end());
}
try {
ENABLE_EXCEPTIONS;
x.insert(v.begin(), v.end());
} catch (...) {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
test::check_equivalent_keys(x);
throw;
}
};
test::check_equivalent_keys(x);
tracker.insert(v.begin(), v.end());
tracker.compare(x);
}
template <typename T>
void insert_range_exception_test(T*, test::random_generator gen)
template <class T>
struct insert_test4 : public insert_test_base<T>
{
for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen);
T x;
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
}
};
template <typename T>
void insert_range_rehash_exception_test(T*, test::random_generator gen)
template <class T>
struct insert_test_rehash1 : public insert_test_base<T>
{
for (int i = 0; i < 5; ++i) {
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
insert_test_rehash1() : insert_test_base<T>(1000) {}
T init() const {
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
T x;
rehash_prep(x);
test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
x.max_load_factor(0.25);
size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>(
ceil(bucket_count * (double) x.max_load_factor()) - 1);
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_TEST(bucket_count == x.bucket_count());
return x;
}
}
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((default_generator)(limited_range)(generate_collisions))
)
void run(T& x, strong_type& strong) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
int count = 0;
BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();
UNORDERED_TEST(insert_range_rehash_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
RUN_TESTS()
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_TEST(x.bucket_count() != bucket_count);
}
};
template <class T>
struct insert_test_rehash2 : public insert_test_rehash1<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
int count = 0;
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_TEST(x.bucket_count() != bucket_count);
}
};
template <class T>
struct insert_test_rehash3 : public insert_test_base<T>
{
BOOST_DEDUCED_TYPENAME T::size_type mutable
rehash_bucket_count, original_bucket_count;
insert_test_rehash3() : insert_test_base<T>(1000) {}
T init() const {
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
T x;
x.max_load_factor(0.25);
original_bucket_count = x.bucket_count();
rehash_bucket_count = static_cast<size_type>(
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
size_type initial_elements =
rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_TEST(original_bucket_count == x.bucket_count());
return x;
}
void run(T& x) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
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.
BOOST_TEST(x.bucket_count() != bucket_count);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
if(x.size() < rehash_bucket_count) {
//BOOST_TEST(x.bucket_count() == original_bucket_count);
}
test::check_equivalent_keys(x);
}
};
#define BASIC_TESTS \
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
#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
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
-103
View File
@@ -1,103 +0,0 @@
#include "../helpers/exception_test.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/random_values.hpp"
#include "./containers.hpp"
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
{
std::size_t size = x.size() + y.size();
try {
ENABLE_EXCEPTIONS;
x.merge(y);
} catch (...) {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <typename T1, typename T2>
void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
test::random_generator gen1, test::random_generator gen2)
{
std::size_t count1 = count12 / 256;
std::size_t count2 = count12 % 256;
int tag1 = tag12 / 256;
int tag2 = tag12 % 256;
test::random_values<T1> v1(count1, gen1);
test::random_values<T2> v2(count2, gen2);
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
test::exception::equal_to(tag1));
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
test::exception::equal_to(tag2));
EXCEPTION_LOOP(merge_exception_test(x, y))
}
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_multiset<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_multiset_;
boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0101)(0x0200)(0x0201))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
// clang-format on
RUN_TESTS_QUIET()
@@ -1,128 +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 "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.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);
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
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, test::limited_range);
this->y_values.fill(count2, test::limited_range);
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, test::limited_range);
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, test::limited_range);
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()
+34 -78
View File
@@ -4,126 +4,82 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include <iostream>
test::seed_t initialize_seed(3298597);
template <class T> struct rehash_test_base : public test::exception_base
template <class T>
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, test::limited_range), n(n_)
{
}
rehash_test_base(unsigned int count = 100, unsigned int n = 0)
: values(count), n(n)
{}
typedef T data_type;
typedef test::strong<T> strong_type;
data_type init() const
{
data_type init() const {
T x(values.begin(), values.end(), n);
return x;
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x,
strong_type const& strong) const
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos &&
scope.find("equal_to::operator()") == std::string::npos &&
scope != "operator==(object, object)")
if(scope.find("hash::operator()") == std::string::npos &&
scope.find("equal_to::operator()") == std::string::npos &&
scope != "operator==(object, object)")
strong.test(x);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test0 : rehash_test_base<T>
template <class T>
struct rehash_test0 : rehash_test_base<T>
{
rehash_test0() : rehash_test_base<T>(0) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x.rehash(0); }
};
template <class T> struct rehash_test1 : rehash_test_base<T>
template <class T>
struct rehash_test1 : rehash_test_base<T>
{
rehash_test1() : rehash_test_base<T>(0) {}
void run(T& x) const
{
x.rehash(200);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x.rehash(200); }
};
template <class T> struct rehash_test2 : rehash_test_base<T>
template <class T>
struct rehash_test2 : rehash_test_base<T>
{
rehash_test2() : rehash_test_base<T>(0, 200) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x.rehash(0); }
};
template <class T> struct rehash_test3 : rehash_test_base<T>
template <class T>
struct rehash_test3 : rehash_test_base<T>
{
rehash_test3() : rehash_test_base<T>(10, 0) {}
void run(T& x) const
{
x.rehash(200);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x.rehash(200); }
};
template <class T> struct rehash_test4 : rehash_test_base<T>
template <class T>
struct rehash_test4 : rehash_test_base<T>
{
rehash_test4() : rehash_test_base<T>(10, 200) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run(T& x) const { x.rehash(0); }
};
template <class T> struct rehash_test5 : rehash_test_base<T>
{
rehash_test5() : rehash_test_base<T>(200, 10) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
EXCEPTION_TESTS((rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(
rehash_test4)(rehash_test5),
RUN_EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
CONTAINER_SEQ)
RUN_TESTS()
+51 -71
View File
@@ -4,60 +4,49 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(9387);
template <class T> struct self_swap_base : public test::exception_base
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, test::limited_range)
{
}
self_swap_base(int count = 0) : values(count) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const
{
x.swap(x);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
void run(T& x) const { x.swap(x); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
BOOST_TEST(
scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(x);
}
};
template <class T> struct self_swap_test1 : self_swap_base<T>
{
};
template <class T>
struct self_swap_test1 : self_swap_base<T> {};
template <class T> struct self_swap_test2 : self_swap_base<T>
template <class T>
struct self_swap_test2 : self_swap_base<T>
{
self_swap_test2() : self_swap_base<T>(100) {}
};
template <class T> struct swap_base : public test::exception_base
template <class T>
struct swap_base : public test::exception_base
{
const test::random_values<T> x_values, y_values;
const T initial_x, initial_y;
@@ -67,78 +56,69 @@ template <class T> struct swap_base : public test::exception_base
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1, test::limited_range),
y_values(count2, test::limited_range),
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))
{
}
: x_values(count1), y_values(count2),
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))
{}
struct data_type
{
data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
struct data_type {
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
{
void run(data_type& d) const {
try {
d.x.swap(d.y);
} catch (std::runtime_error) {
}
DISABLE_EXCEPTIONS;
test::check_container(d.x, this->y_values);
test::check_equivalent_keys(d.x);
test::check_container(d.y, this->x_values);
test::check_equivalent_keys(d.y);
} catch (std::runtime_error) {}
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
{
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
BOOST_TEST(
scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
}
};
template <class T> struct swap_test1 : swap_base<T>
template <class T>
struct swap_test1 : swap_base<T>
{
swap_test1() : swap_base<T>(0, 0, 0, 0) {}
};
template <class T> struct swap_test2 : swap_base<T>
template <class T>
struct swap_test2 : swap_base<T>
{
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
};
template <class T> struct swap_test3 : swap_base<T>
template <class T>
struct swap_test3 : swap_base<T>
{
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
};
template <class T> struct swap_test4 : swap_base<T>
template <class T>
struct swap_test4 : swap_base<T>
{
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
};
EXCEPTION_TESTS((self_swap_test1)(self_swap_test2)(swap_test1)(swap_test2)(
swap_test3)(swap_test4),
RUN_EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
RUN_TESTS()
+20 -15
View File
@@ -7,27 +7,32 @@
#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
namespace test {
template <class T1> struct check_return_type
namespace test
{
template <class T2> static void equals(T2)
template <class T1>
struct check_return_type
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals(T2)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2> static void equals_ref(T2&)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2> static void convertible(T2)
{
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
template <class T2>
static void convertible(T2)
{
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
}
#endif
+60 -70
View File
@@ -6,84 +6,74 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
namespace test {
struct object_count
{
int instances;
int constructions;
struct object_count {
int instances;
int constructions;
object_count() : instances(0), constructions(0) {}
void reset() { *this = object_count(); }
object_count() : instances(0), constructions(0) {}
void reset() { *this = object_count(); }
void construct()
{
++instances;
++constructions;
}
void destruct()
{
if (instances == 0) {
BOOST_ERROR("Unbalanced constructions.");
} else {
--instances;
void construct() {
++instances;
++constructions;
}
}
bool operator==(object_count const& x) const
void destruct() {
if(instances == 0) {
BOOST_ERROR("Unbalanced constructions.");
}
else {
--instances;
}
}
bool operator==(object_count const& x) const {
return instances == x.instances &&
constructions == x.constructions;
}
bool operator!=(object_count const& x) const {
return !(*this == x);
}
friend std::ostream& operator<<(std::ostream& out,
object_count const& c)
{
out
<< "[instances: "
<< c.instances
<< ", constructions: "
<< c.constructions
<< "]";
return out;
}
};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count global_object_count;
}
struct counted_object
{
return instances == x.instances && constructions == x.constructions;
}
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
bool operator!=(object_count const& x) const { return !(*this == x); }
friend std::ostream& operator<<(std::ostream& out, object_count const& c)
{
out << "[instances: " << c.instances
<< ", constructions: " << c.constructions << "]";
return out;
}
};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count global_object_count;
}
struct counted_object
{
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
struct check_instances
{
int instances_;
int constructions_;
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_;
}
};
struct check_instances {
int instances;
check_instances() : instances(global_object_count.instances) {}
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
};
}
#endif
+75 -72
View File
@@ -6,90 +6,93 @@
#if !defined(BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER)
#define BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER
#include "./fwd.hpp"
#include "./list.hpp"
#include "./metafunctions.hpp"
#include <algorithm>
#include <boost/detail/lightweight_test.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <algorithm>
#include "./metafunctions.hpp"
#include "./fwd.hpp"
#include "./list.hpp"
namespace test {
template <class T1, class T2>
bool equivalent_impl(T1 const& x, T2 const& y, base_type)
namespace test
{
return x == y;
}
template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&, derived_type)
{
return true;
}
template <class T>
bool equivalent_impl(
std::equal_to<T> const&, std::equal_to<T> const&, derived_type)
{
return true;
}
template <class T1, class T2, class T3, class T4>
bool equivalent_impl(
std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type)
{
return equivalent_impl(x1.first, x2.first, derived) &&
equivalent_impl(x1.second, x2.second, derived);
}
struct equivalent_type
{
equivalent_type() {}
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const
{
return equivalent_impl(x, y, derived);
}
};
const equivalent_type equivalent;
template <class Container> class unordered_equivalence_tester
{
BOOST_DEDUCED_TYPENAME Container::size_type size_;
BOOST_DEDUCED_TYPENAME Container::hasher hasher_;
BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_;
float max_load_factor_;
typedef test::list<BOOST_DEDUCED_TYPENAME Container::value_type> value_list;
value_list values_;
public:
unordered_equivalence_tester(Container const& x)
: size_(x.size()), hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()), values_(x.begin(), x.end())
{
values_.sort();
bool equivalent_impl(T1 const& x, T2 const& y, base_type) {
return x == y;
}
bool operator()(Container const& x) const
template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&,
derived_type)
{
if (!((size_ == x.size()) &&
return true;
}
template <class T>
bool equivalent_impl(std::equal_to<T> const&, std::equal_to<T> const&,
derived_type)
{
return true;
}
template <class T1, class T2, class T3, class T4>
bool equivalent_impl(std::pair<T1, T2> const& x1,
std::pair<T3, T4> const& x2, derived_type) {
return equivalent_impl(x1.first, x2.first, derived) &&
equivalent_impl(x1.second, x2.second, derived);
}
struct equivalent_type {
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) {
return equivalent_impl(x, y, derived);
}
};
// 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
{
BOOST_DEDUCED_TYPENAME Container::size_type size_;
BOOST_DEDUCED_TYPENAME Container::hasher hasher_;
BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_;
float max_load_factor_;
typedef test::list<BOOST_DEDUCED_TYPENAME Container::value_type>
value_list;
value_list values_;
public:
unordered_equivalence_tester(Container const &x)
: size_(x.size()),
hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()),
values_(x.begin(), x.end())
{
values_.sort();
}
bool operator()(Container const& x) const
{
if(!((size_ == x.size()) &&
(test::equivalent(hasher_, x.hash_function())) &&
(test::equivalent(key_equal_, x.key_eq())) &&
(max_load_factor_ == x.max_load_factor()) &&
(values_.size() == x.size())))
return false;
(values_.size() == x.size()))) return false;
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
}
private:
unordered_equivalence_tester();
};
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
}
private:
unordered_equivalence_tester();
};
}
#endif
+182 -298
View File
@@ -6,347 +6,231 @@
#if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
#define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
#include "./count.hpp"
#include "./test.hpp"
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/cat.hpp>
#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
}
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::lightweight::exception_safety( \
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_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 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(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product) \
) \
#define EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product))
#define UNORDERED_SCOPE(scope_name) \
for(::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); \
unordered_test_guard.dismiss()) \
#define UNORDERED_SCOPE(scope_name) \
for (::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
#define UNORDERED_EPOINT(name) \
if(::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
} \
#define UNORDERED_EPOINT(name) \
if (::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT( \
ENABLE_EXCEPTIONS_, __LINE__)(true) \
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT( \
ENABLE_EXCEPTIONS_, __LINE__)(false) \
namespace test {
static char const* scope = "";
bool exceptions_enabled = false;
static char const* scope = "";
bool exceptions_enabled = false;
class scope_guard
{
scope_guard& operator=(scope_guard const&);
scope_guard(scope_guard const&);
class scope_guard {
scope_guard& operator=(scope_guard const&);
scope_guard(scope_guard const&);
char const* old_scope_;
char const* scope_;
bool dismissed_;
public:
scope_guard(char const* name)
: old_scope_(scope), scope_(name), dismissed_(false)
{
scope = scope_;
}
~scope_guard()
{
if (dismissed_)
scope = old_scope_;
}
void dismiss() { dismissed_ = true; }
bool dismissed() const { return dismissed_; }
};
class exceptions_enable
{
exceptions_enable& operator=(exceptions_enable const&);
exceptions_enable(exceptions_enable const&);
bool old_value_;
bool released_;
public:
exceptions_enable(bool enable)
: old_value_(exceptions_enabled), released_(false)
{
exceptions_enabled = enable;
}
~exceptions_enable()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
char const* old_scope_;
char const* scope_;
bool dismissed_;
public:
scope_guard(char const* name)
: old_scope_(scope),
scope_(name),
dismissed_(false)
{
scope = scope_;
}
}
void release()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
~scope_guard() {
if(dismissed_) scope = old_scope_;
}
void dismiss() {
dismissed_ = true;
}
bool dismissed() const {
return dismissed_;
}
};
class exceptions_enable
{
exceptions_enable& operator=(exceptions_enable const&);
exceptions_enable(exceptions_enable const&);
bool old_value_;
public:
exceptions_enable(bool enable)
: old_value_(exceptions_enabled)
{
exceptions_enabled = enable;
}
~exceptions_enable()
{
exceptions_enabled = old_value_;
}
};
struct exception_base {
struct data_type {};
struct strong_type {
template <class T> void store(T const&) {}
template <class T> void test(T const&) const {}
};
data_type init() const { return data_type(); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
};
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)() const, T2 const& obj,
P1&, P2&)
{
(obj.*fn)();
}
};
struct exception_base
{
struct data_type
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&) const, T2 const& obj,
P1& p1, P2&)
{
};
struct strong_type
(obj.*fn)(p1);
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&, P2&) const, T2 const& obj,
P1& p1, P2& p2)
{
template <class T> void store(T const&) {}
template <class T> void test(T const&) const {}
};
data_type init() const { return data_type(); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
};
(obj.*fn)(p1, p2);
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)() const, T2 const& obj, P1&, P2&)
{
(obj.*fn)();
}
template <class T>
T const& constant(T const& x) {
return x;
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&)
{
(obj.*fn)(p1);
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2)
{
(obj.*fn)(p1, p2);
}
template <class T> T const& constant(T const& x) { return x; }
template <class 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()
template <class Test>
class test_runner
{
DISABLE_EXCEPTIONS;
test::check_instances check;
test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
BOOST_DEDUCED_TYPENAME Test::strong_type strong;
strong.store(x);
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type,
BOOST_DEDUCED_TYPENAME Test::strong_type>(
&Test::run, test_, x, strong);
} catch (...) {
Test const& test_;
test_runner(test_runner const&);
test_runner& operator=(test_runner const&);
public:
test_runner(Test const& t) : test_(t) {}
void operator()() const {
DISABLE_EXCEPTIONS;
test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
BOOST_DEDUCED_TYPENAME Test::strong_type strong;
strong.store(x);
try {
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type,
BOOST_DEDUCED_TYPENAME Test::strong_type
>(&Test::run, test_, x, strong);
}
catch(...) {
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;
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
throw;
}
throw;
}
}
void end()
{
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
}
};
};
// Quick exception testing based on lightweight test
// Quick exception testing based on lightweight test
namespace lightweight {
static int iteration;
static int count;
namespace lightweight {
static int iteration;
static int count;
struct test_exception
{
char const* name;
test_exception(char const* n) : name(n) {}
};
struct test_exception {
char const* name;
test_exception(char const* n) : name(n) {}
};
struct test_failure
{
};
struct test_failure {
};
void epoint(char const* name)
{
++count;
if (count == iteration) {
throw test_exception(name);
}
}
template <class Test> void exception_safety(Test const& f, char const* /*name*/)
{
test_runner<Test> runner(f);
iteration = 0;
bool success = false;
unsigned int failure_count = 0;
char const* error_msg = 0;
do {
int error_count = boost::detail::test_errors();
++iteration;
count = 0;
try {
runner.run();
success = true;
} catch (test_failure) {
error_msg = "test_failure caught.";
break;
} catch (test_exception e) {
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
void epoint(char const* name) {
++count;
if(count == iteration) {
throw test_exception(name);
}
} catch (...) {
error_msg = "Unexpected exception.";
break;
}
if (error_count != boost::detail::test_errors()) {
++failure_count;
}
} while (!success && failure_count < 5);
template <class Test>
void exception_safety(Test const& f, char const* /*name*/) {
test_runner<Test> runner(f);
if (error_msg) {
BOOST_ERROR(error_msg);
}
runner.end();
}
iteration = 0;
bool success = false;
do {
++iteration;
count = 0;
//
// An alternative way to run exception tests.
// See merge_exception_tests.cpp for an example.
struct exception_looper
{
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{
return !error_msg && !success && failure_count < 5;
}
void start_iteration()
{
error_count = boost::detail::test_errors();
++iteration;
count = 0;
}
void successful_run() { success = true; }
void test_failure_caught(test_failure const&)
{
error_msg = "test_failure caught.";
}
void test_exception_caught(test_exception const& e)
{
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
try {
runner();
success = true;
}
catch(test_failure) {
BOOST_ERROR("test_failure caught.");
break;
}
catch(test_exception) {
continue;
}
catch(...) {
BOOST_ERROR("Unexpected exception.");
break;
}
} while(!success);
}
}
void unexpected_exception_caught() { error_msg = "Unexpected exception."; }
void end()
{
if (error_msg) {
BOOST_ERROR(error_msg);
}
}
};
#define EXCEPTION_LOOP(op) \
test::lightweight::exception_looper looper; \
looper.start(); \
while (looper.loop_condition()) { \
looper.start_iteration(); \
try { \
op; \
looper.successful_run(); \
} catch (test::lightweight::test_failure e) { \
looper.test_failure_caught(e); \
} catch (test::lightweight::test_exception e) { \
looper.test_exception_caught(e); \
} catch (...) { \
looper.unexpected_exception_caught(); \
} \
} \
looper.end();
}
}
#endif
+10 -18
View File
@@ -8,25 +8,17 @@
#include <string>
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);
struct base_type
namespace test
{
} base;
struct derived_type : base_type
{
} derived;
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;
}
#endif
+45 -69
View File
@@ -11,84 +11,60 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER
#include "./fwd.hpp"
#include <boost/type_traits/add_const.hpp>
#include <cstdlib>
#include <stdexcept>
#include <string>
#include <utility>
#include <stdexcept>
#include <cstdlib>
#include <boost/type_traits/add_const.hpp>
#include "./fwd.hpp"
namespace test {
struct seed_t
namespace test
{
seed_t(unsigned int x)
struct seed_t {
seed_t(unsigned int x) {
using namespace std;
srand(x);
}
};
inline int generate(int const*)
{
using namespace std;
srand(x);
}
};
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)
{
using namespace std;
int value = rand();
if (g == limited_range) {
value = value % 100;
}
return value;
}
inline char generate(char const*, random_generator)
{
using namespace std;
return static_cast<char>((rand() >> 1) % (128 - 32) + 32);
}
inline signed char generate(signed char const*, random_generator)
{
using namespace std;
return static_cast<signed char>(rand());
}
inline std::string generate(std::string const*, random_generator g)
{
using namespace std;
char* char_ptr = 0;
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);
}
return rand();
}
return result;
}
inline char generate(char const*)
{
using namespace std;
return static_cast<char>((rand() >> 1) % (128-32) + 32);
}
float generate(float const*, random_generator g)
{
using namespace std;
int x = 0;
int value = generate(&x, g);
return (float)value / (float)RAND_MAX;
}
inline signed char generate(signed char const*)
{
using namespace std;
return static_cast<signed char>(rand());
}
inline std::string generate(std::string const*)
{
using namespace std;
char* char_ptr = 0;
std::string result;
int length = rand() % 10;
for(int i = 0; i < length; ++i)
result += generate(char_ptr);
return result;
}
float generate(float const*)
{
using namespace std;
return (float) rand() / (float) RAND_MAX;
}
}
#endif
+27 -37
View File
@@ -6,48 +6,38 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_HEADER
namespace test {
template <class Container> struct get_key_impl
namespace test
{
typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type;
static key_type const& get_key(key_type const& x) { return x; }
template <class T>
static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
template <class Container>
struct get_key_impl
{
return x.first;
}
typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type;
template <class T>
static key_type const& get_key(
std::pair<key_type const, T> const& x, unsigned char = 0)
static key_type const& get_key(key_type const& x)
{
return x;
}
template <class T>
static key_type const& get_key(
std::pair<key_type, T> const& x, char = 0)
{
return x.first;
}
template <class T>
static key_type const& get_key(std::pair<key_type const, T> const& x,
unsigned char = 0)
{
return x.first;
}
};
template <class Container, class T>
inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x)
{
return x.first;
return get_key_impl<Container>::get_key(x);
}
};
template <class Container, class T>
inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x)
{
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
+141 -149
View File
@@ -7,167 +7,159 @@
#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 {
template <class Iterator> struct proxy
namespace test
{
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
operator value_type const&() const { return v_; }
value_type v_;
private:
proxy& operator=(proxy const&);
};
template <class Iterator>
struct input_iterator_adaptor
: public std::iterator<std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> >
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
input_iterator_adaptor() : base_() {}
explicit input_iterator_adaptor(Iterator& it) : base_(&it) {}
proxy<Iterator> operator*() const { return proxy<Iterator>(**base_); }
value_type* operator->() const { return &**base_; }
input_iterator_adaptor& operator++()
template <class Iterator>
struct proxy
{
++*base_;
return *this;
}
// input_iterator_adaptor operator++(int) {
//}
bool operator==(input_iterator_adaptor const& x) const
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
operator value_type const&() const { return v_; }
value_type v_;
private:
proxy& operator=(proxy const&);
};
template <class Iterator>
struct input_iterator_adaptor
: public boost::iterator<
std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
return *base_ == *x.base_;
}
bool operator!=(input_iterator_adaptor const& x) const
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
input_iterator_adaptor()
: base_() {}
explicit input_iterator_adaptor(Iterator& it)
: base_(&it) {}
proxy<Iterator> operator*() const {
return proxy<Iterator>(**base_);
}
value_type* operator->() const {
return &**base_;
}
input_iterator_adaptor& operator++() {
++*base_; return *this;
}
//input_iterator_adaptor operator++(int) {
//}
bool operator==(input_iterator_adaptor const& x) const {
return *base_ == *x.base_;
}
bool operator!=(input_iterator_adaptor const& x) const {
return *base_ != *x.base_;
}
private:
Iterator* base_;
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
return *base_ != *x.base_;
return input_iterator_adaptor<Iterator>(it);
}
private:
Iterator* base_;
};
template <class Iterator>
struct copy_iterator_adaptor
: 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,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type;
copy_iterator_adaptor()
: base_() {}
explicit copy_iterator_adaptor(Iterator const& it)
: base_(it) {}
value_type operator*() const {
return *base_;
}
value_type* operator->() const {
return &*base_;
}
value_type operator[](difference_type d) {
return base_[d];
}
copy_iterator_adaptor& operator++() {
++base_; return *this;
}
copy_iterator_adaptor operator++(int) {
copy_iterator_adaptor tmp(*this); ++base_; return tmp;
}
copy_iterator_adaptor& operator--() {
--base_; return *this;
}
copy_iterator_adaptor operator--(int) {
copy_iterator_adaptor tmp(*this); --base_; return tmp;
}
copy_iterator_adaptor operator+=(difference_type x) {
base_ += x;
return *this;
}
copy_iterator_adaptor operator-=(difference_type x) {
base_ -= x;
return *this;
}
copy_iterator_adaptor operator+(difference_type n) {
return copy_iterator_adaptor(base_+n);
}
copy_iterator_adaptor operator-(difference_type n) {
return copy_iterator_adaptor(base_-n);
}
friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x) {
return x+n;
}
difference_type operator-(copy_iterator_adaptor const& other) {
return base_-other.base_;
}
bool operator==(copy_iterator_adaptor const& x) const {
return base_ == x.base_;
}
bool operator!=(copy_iterator_adaptor const& x) const {
return base_ != x.base_;
}
bool operator<(copy_iterator_adaptor const& x) const {
return base_ < x.base_;
}
bool operator>(copy_iterator_adaptor const& x) const {
return base_ > x.base_;
}
bool operator<=(copy_iterator_adaptor const& x) const {
return base_ <= x.base_;
}
bool operator>=(copy_iterator_adaptor const& x) const {
return base_ >= x.base_;
}
private:
Iterator base_;
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
return input_iterator_adaptor<Iterator>(it);
}
template <class Iterator>
struct copy_iterator_adaptor
: public std::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,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> >
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type;
copy_iterator_adaptor() : base_() {}
explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {}
value_type operator*() const { return *base_; }
value_type* operator->() const { return &*base_; }
value_type operator[](difference_type d) { return base_[d]; }
copy_iterator_adaptor& operator++()
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
++base_;
return *this;
}
copy_iterator_adaptor operator++(int)
{
copy_iterator_adaptor tmp(*this);
++base_;
return tmp;
}
copy_iterator_adaptor& operator--()
{
--base_;
return *this;
}
copy_iterator_adaptor operator--(int)
{
copy_iterator_adaptor tmp(*this);
--base_;
return tmp;
}
copy_iterator_adaptor operator+=(difference_type x)
{
base_ += x;
return *this;
}
copy_iterator_adaptor operator-=(difference_type x)
{
base_ -= x;
return *this;
}
copy_iterator_adaptor operator+(difference_type n)
{
return copy_iterator_adaptor(base_ + n);
}
copy_iterator_adaptor operator-(difference_type n)
{
return copy_iterator_adaptor(base_ - n);
}
friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x)
{
return x + n;
}
difference_type operator-(copy_iterator_adaptor const& other)
{
return base_ - other.base_;
}
bool operator==(copy_iterator_adaptor const& x) const
{
return base_ == x.base_;
}
bool operator!=(copy_iterator_adaptor const& x) const
{
return base_ != x.base_;
}
bool operator<(copy_iterator_adaptor const& x) const
{
return base_ < x.base_;
}
bool operator>(copy_iterator_adaptor const& x) const
{
return base_ > x.base_;
}
bool operator<=(copy_iterator_adaptor const& x) const
{
return base_ <= x.base_;
}
bool operator>=(copy_iterator_adaptor const& x) const
{
return base_ >= x.base_;
return copy_iterator_adaptor<Iterator>(it);
}
private:
Iterator base_;
};
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
return copy_iterator_adaptor<Iterator>(it);
}
}
#endif
+80 -87
View File
@@ -9,121 +9,113 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER
#include "./helpers.hpp"
#include "./metafunctions.hpp"
#include <cmath>
#include <set>
#include <cmath>
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data
#endif
namespace test {
template <class X> void check_equivalent_keys(X const& x1)
namespace test
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
std::set<key_type, std::less<key_type> > found_;
template <class X>
void check_equivalent_keys(X const& x1)
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
std::set<key_type, std::less<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while (it != end) {
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
if (!found_.insert(key).second)
BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while(it != end) {
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
if(!found_.insert(key).second)
BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
// Iterate over equivalent keys, counting them.
unsigned int count = 0;
do {
++it;
++count;
++size;
} while (it != end && eq(get_key<X>(*it), key));
// Iterate over equivalent keys, counting them.
unsigned int count = 0;
do {
++it;
++count;
++size;
} while(it != end && eq(get_key<X>(*it), key));
// If the container has unique keys, test that there's only one.
// Since the previous test makes sure that all equivalent keys are
// adjacent, this is all the equivalent keys - so the test is
// sufficient. (6.3.1/6 again).
if (test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key.");
// If the container has unique keys, test that there's only one.
// Since the previous test makes sure that all equivalent keys are
// adjacent, this is all the equivalent keys - so the test is
// sufficient. (6.3.1/6 again).
if(test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key.");
if (x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count.");
std::cerr << x1.count(key) << "," << count << "\n";
}
if(x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count.");
std::cerr<<x1.count(key)<<","<<count<<"\n";
}
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket),
lend = x1.end(bucket);
unsigned int count_checked = 0;
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
++count_checked;
}
if (lit == lend) {
BOOST_ERROR("Unable to find element with a local_iterator");
std::cerr << "Checked: " << count_checked << " elements"
<< std::endl;
} else {
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
BOOST_DEDUCED_TYPENAME X::const_local_iterator
lit = x1.begin(bucket), lend = x1.end(bucket);
for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
if(lit == lend)
BOOST_ERROR("Unable to find element with a local_iterator");
unsigned int count2 = 0;
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
++count2;
if (count != count2)
for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
if(count != count2)
BOOST_ERROR("Element count doesn't match local_iterator.");
for (; lit != lend; ++lit) {
if (eq(get_key<X>(*lit), key)) {
for(; lit != lend; ++lit) {
if(eq(get_key<X>(*lit), key)) {
BOOST_ERROR("Non-adjacent element with equivalent key "
"in bucket.");
"in bucket.");
break;
}
}
};
// 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 that size matches up.
// Check the load factor.
if (x1.size() != size) {
BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout << x1.size() << "/" << size << std::endl;
}
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 the load factor.
// Check that size in the buckets matches up.
float load_factor =
size == 0 ? 0 : 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.");
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
// Check that size in the buckets matches up.
for (BOOST_DEDUCED_TYPENAME X::size_type
i = 0; i < x1.bucket_count(); ++i)
{
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
{
++bucket_size;
}
}
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;
}
}
if (x1.size() != bucket_size) {
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout << x1.size() << "/" << bucket_size << std::endl;
}
}
}
#if defined(BOOST_MSVC)
@@ -131,3 +123,4 @@ template <class X> void check_equivalent_keys(X const& x1)
#endif
#endif
+280 -282
View File
@@ -11,310 +11,308 @@
#if !defined(UNORDERED_TEST_LIST_HEADER)
#define UNORDERED_TEST_LIST_HEADER
#include <boost/iterator.hpp>
#include <boost/limits.hpp>
#include <functional>
#include <iterator>
namespace test {
template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare)
namespace test
{
for (; begin != end; ++begin, ++compare)
if (*begin != *compare)
return false;
return true;
}
template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{
for (; begin != end; ++begin, ++compare)
if (!predicate(*begin, *compare))
return false;
return true;
}
template <typename T> class list;
namespace test_detail {
template <typename T> class list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
template <typename T> class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T> class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data()
template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare)
{
while (first_) {
node* tmp = first_;
first_ = first_->next_;
delete tmp;
for(;begin != end; ++begin, ++compare)
if(*begin != *compare) return false;
return true;
}
template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{
for(;begin != end; ++begin, ++compare)
if(!predicate(*begin, *compare)) return false;
return true;
}
template <typename T> class list;
namespace test_detail
{
template <typename T> class list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
template <typename T>
class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T>
class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data() {
while(first_) {
node* tmp = first_;
first_ = first_->next_;
delete tmp;
}
}
private:
list_data(list_data const&);
list_data& operator=(list_data const&);
};
template <typename T>
class list_iterator
: public boost::iterator<
std::forward_iterator_tag, T,
int, T*, T&>
{
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++() {
ptr_ = ptr_->next_; return *this; }
list_iterator operator++(int) {
list_iterator tmp = *this; ptr_ = ptr_->next_; return tmp; }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
template <typename T>
class list_const_iterator
: public boost::iterator<
std::forward_iterator_tag, T,
int, T const*, T const&>
{
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
list_const_iterator operator++(int)
{
list_const_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
bool operator==(const_iterator y) const
{
return ptr_ == y.ptr_;
}
bool operator!=(const_iterator y) const
{
return ptr_ != y.ptr_;
}
};
}
template <typename T>
class list
{
typedef test::test_detail::list_data<T> data;
typedef test::test_detail::list_node<T> node;
data data_;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef unsigned int size_type;
typedef test::test_detail::list_iterator<T> iterator;
typedef test::test_detail::list_const_iterator<T> const_iterator;
list() : data_() {}
list(list const& other) : data_() {
insert(other.begin(), other.end());
}
}
private:
list_data(list_data const&);
list_data& operator=(list_data const&);
};
template <class InputIterator>
list(InputIterator i, InputIterator j) : data_() {
insert(i, j);
}
template <typename T>
class list_iterator
: public std::iterator<std::forward_iterator_tag, T, int, T*, T&>
{
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
list& operator=(list const& other) {
clear();
insert(other.begin(), other.end());
return *this;
}
node* ptr_;
iterator begin() { return iterator(data_.first_); }
iterator end() { return iterator(); }
const_iterator begin() const { return iterator(data_.first_); }
const_iterator end() const { return iterator(); }
const_iterator cbegin() const { return iterator(data_.first_); }
const_iterator cend() const { return iterator(); }
public:
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
template <class InputIterator>
void insert(InputIterator i, InputIterator j) {
for(; i != j; ++i)
push_back(*i);
}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
list_iterator operator++(int)
{
list_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
template <typename T>
class list_const_iterator : public std::iterator<std::forward_iterator_tag, T,
int, T const*, T const&>
{
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
list_const_iterator operator++(int)
{
list_const_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
}
template <typename T> class list
{
typedef test::test_detail::list_data<T> data;
typedef test::test_detail::list_node<T> node;
data data_;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef unsigned int size_type;
typedef test::test_detail::list_iterator<T> iterator;
typedef test::test_detail::list_const_iterator<T> const_iterator;
list() : data_() {}
list(list const& other) : data_() { insert(other.begin(), other.end()); }
template <class InputIterator>
list(InputIterator i, InputIterator j) : data_()
{
insert(i, j);
}
list& operator=(list const& other)
{
clear();
insert(other.begin(), other.end());
return *this;
}
iterator begin() { return iterator(data_.first_); }
iterator end() { return iterator(); }
const_iterator begin() const { return iterator(data_.first_); }
const_iterator end() const { return iterator(); }
const_iterator cbegin() const { return iterator(data_.first_); }
const_iterator cend() const { return iterator(); }
template <class InputIterator> void insert(InputIterator i, InputIterator j)
{
for (; i != j; ++i)
push_back(*i);
}
void push_front(value_type const& v)
{
data_.first_ = new node(v, data_.first_);
if (!data_.size_)
void push_front(value_type const& v) {
data_.first_ = new node(v, data_.first_);
if(!data_.size_) data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
}
void push_back(value_type const& v) {
*data_.last_ptr_ = new node(v);
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
}
void push_back(value_type const& v)
{
*data_.last_ptr_ = new node(v);
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
}
void clear()
{
while (data_.first_) {
node* tmp = data_.first_;
data_.first_ = data_.first_->next_;
--data_.size_;
delete tmp;
++data_.size_;
}
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator i, const_iterator j)
{
node** ptr = &data_.first_;
while (*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
void clear() {
while(data_.first_) {
node* tmp = data_.first_;
data_.first_ = data_.first_->next_;
--data_.size_;
delete tmp;
}
data_.last_ptr_ = &data_.first_;
}
while (*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
void erase(const_iterator i, const_iterator j) {
node** ptr = &data_.first_;
if (!*ptr)
data_.last_ptr_ = ptr;
}
bool empty() const { return !data_.size_; }
size_type size() const { return data_.size_; }
void sort() { sort(std::less<T>()); }
template <typename Less> void sort(Less less = Less())
{
if (!empty())
merge_sort(
&data_.first_, (std::numeric_limits<size_type>::max)(), less);
}
bool operator==(list const& y) const
{
return size() == y.size() && test::equal(begin(), end(), y.begin());
}
bool operator!=(list const& y) const { return !(*this == y); }
private:
template <typename Less>
node** merge_sort(node** l, size_type recurse_limit, Less less)
{
node** ptr = &(*l)->next_;
for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
ptr = merge_adjacent_ranges(
l, ptr, merge_sort(ptr, count, less), less);
}
return ptr;
}
template <typename Less>
node** merge_adjacent_ranges(
node** first, node** second, node** third, Less less)
{
for (;;) {
for (;;) {
if (first == second)
return third;
if (less((*second)->value_, (*first)->value_))
break;
first = &(*first)->next_;
while(*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for (;;) {
if (first == third)
return second;
if (!less((*first)->value_, (*third)->value_))
break;
first = &(*first)->next_;
while(*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
if(!*ptr) data_.last_ptr_ = ptr;
}
}
void swap_adjacent_ranges(node** first, node** second, node** third)
{
node* tmp = *first;
*first = *second;
*second = *third;
*third = tmp;
if (!*second)
data_.last_ptr_ = second;
}
};
bool empty() const {
return !data_.size_;
}
size_type size() const {
return data_.size_;
}
void sort() {
sort(std::less<T>());
}
template <typename Less>
void sort(Less less = Less()) {
if(!empty()) merge_sort(&data_.first_,
(std::numeric_limits<size_type>::max)(), less);
}
bool operator==(list const& y) const {
return size() == y.size() &&
test::equal(begin(), end(), y.begin());
}
bool operator!=(list const& y) const {
return !(*this == y);
}
private:
template <typename Less>
node** merge_sort(node** l, size_type recurse_limit, Less less)
{
node** ptr = &(*l)->next_;
for(size_type count = 0; count < recurse_limit && *ptr; ++count)
{
ptr = merge_adjacent_ranges(l, ptr,
merge_sort(ptr, count, less), less);
}
return ptr;
}
template <typename Less>
node** merge_adjacent_ranges(node** first, node** second,
node** third, Less less)
{
for(;;) {
for(;;) {
if(first == second) return third;
if(less((*second)->value_, (*first)->value_)) break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for(;;) {
if(first == third) return second;
if(!less((*first)->value_, (*third)->value_)) break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
}
}
void swap_adjacent_ranges(node** first, node** second, node** third)
{
node* tmp = *first;
*first = *second;
*second = *third;
*third = tmp;
if(!*second) data_.last_ptr_ = second;
}
};
}
#endif
+144 -170
View File
@@ -6,184 +6,158 @@
#if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER)
#define BOOST_UNORDERED_TEST_MEMORY_HEADER
#include "../helpers/test.hpp"
#include <boost/assert.hpp>
#include <boost/unordered/detail/implementation.hpp>
#include <map>
#include <memory>
#include <map>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include "../helpers/test.hpp"
namespace test {
namespace detail {
struct memory_area
namespace test
{
void const* start;
void const* end;
memory_area(void const* s, void const* e) : start(s), end(e)
namespace detail
{
BOOST_ASSERT(start != end);
}
};
struct memory_area {
void const* start;
void const* end;
struct memory_track
{
explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
{
return x.end <= y.start;
}
};
struct memory_tracker
{
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> > >
allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
bool tracking_constructions;
memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0),
tracking_constructions(true)
{
}
~memory_tracker() { BOOST_TEST(count_allocators == 0); }
void allocator_ref()
{
if (count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
void allocator_unref()
{
BOOST_TEST(count_allocators > 0);
if (count_allocators > 0) {
--count_allocators;
if (count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
memory_area(void const* s, void const* e)
: start(s), end(e)
{
BOOST_ASSERT(start != end);
}
};
struct memory_track {
explicit memory_track(int tag = -1) :
constructed_(0),
tag_(tag) {}
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare {
bool operator()(memory_area const& x, memory_area const& y) const {
return x.end <= y.start;
}
};
struct memory_tracker {
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> >
> allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
memory_tracker() :
count_allocators(0), count_allocations(0),
count_constructions(0)
{}
void allocator_ref()
{
if(count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
void allocator_unref()
{
BOOST_TEST(count_allocators > 0);
if(count_allocators > 0) {
--count_allocators;
if(count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
}
void track_allocate(void *ptr, std::size_t n, std::size_t size,
int tag)
{
if(n == 0) {
BOOST_ERROR("Allocating 0 length array.");
}
else {
++count_allocations;
allocated_memory.insert(
std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*) ptr + n * size),
memory_track(tag)));
}
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag, bool check_tag_ = true)
{
allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
} else {
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
if (check_tag_) BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_TEST(count_allocations > 0);
if(count_allocations > 0) --count_allocations;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/,
int /*tag*/)
{
++count_constructions;
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/,
int /*tag*/)
{
BOOST_TEST(count_constructions > 0);
if(count_constructions > 0) --count_constructions;
}
};
}
namespace detail
{
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
if (n == 0) {
BOOST_ERROR("Allocating 0 length array.");
} else {
++count_allocations;
allocated_memory.insert(std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
}
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
bool check_tag_ = true)
{
allocated_memory_type::iterator pos =
allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
if (pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
} else {
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*)ptr + n * size);
if (check_tag_)
BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_TEST(count_allocations > 0);
if (count_allocations > 0)
--count_allocations;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
++count_constructions;
}
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
--count_constructions;
}
}
};
}
namespace detail {
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
namespace detail {
struct disable_construction_tracking
{
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{
test::detail::tracker.tracking_constructions = false;
}
~disable_construction_tracking()
{
test::detail::tracker.tracking_constructions = old_value;
}
private:
disable_construction_tracking(disable_construction_tracking const&);
disable_construction_tracking& operator=(
disable_construction_tracking const&);
};
}
}
#endif
+26 -18
View File
@@ -8,27 +8,35 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test {
template <class Container>
struct is_set
: public boost::is_same<BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type>
namespace test
{
};
template <class Container>
struct is_set
: public boost::is_same<
BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type> {};
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))));
};
template <class Container>
struct has_unique_keys
{
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);
};
}
#endif
+1 -1
View File
@@ -6,6 +6,6 @@
#if defined(_WIN32_WCE)
// The standard windows mobile headers trigger this warning so I disable it
// before doing anything else.
#pragma warning(disable : 4201) // nonstandard extension used :
#pragma warning(disable:4201) // nonstandard extension used :
// nameless struct/union
#endif
+79 -73
View File
@@ -6,104 +6,110 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER
#include "./generators.hpp"
#include "./list.hpp"
#include "./metafunctions.hpp"
#include <algorithm>
#include <boost/detail/select_type.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
namespace test {
template <class X> struct unordered_generator_set
namespace test
{
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef enum {
default_generator,
generate_collisions
} random_generator;
random_generator type_;
unordered_generator_set(random_generator type) : type_(type) {}
template <class T> void fill(T& x, std::size_t len)
template <class X>
struct unordered_generator_set
{
value_type* value_ptr = 0;
len += x.size();
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr, type_);
random_generator type_;
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
unordered_generator_set(random_generator type)
: type_(type) {}
for (std::size_t j = 0; j < count; ++j) {
x.push_back(value);
template <class T>
void fill(T& x, std::size_t len) {
value_type* value_ptr = 0;
int* int_ptr = 0;
len += x.size();
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr);
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int i = 0; i < count; ++i) {
x.push_back(value);
}
}
}
}
};
};
template <class X> struct unordered_generator_map
{
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
random_generator type_;
unordered_generator_map(random_generator type) : type_(type) {}
template <class T> void fill(T& x, std::size_t len)
template <class X>
struct unordered_generator_map
{
key_type* key_ptr = 0;
mapped_type* mapped_ptr = 0;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr, type_);
random_generator type_;
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
unordered_generator_map(random_generator type)
: type_(type) {}
for (std::size_t j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr, type_)));
template <class T>
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);
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int i = 0; i < count; ++i) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
}
}
}
}
};
};
template <class X>
struct unordered_generator_base
: public boost::detail::if_true<test::is_set<X>::value>::
BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
{
};
template <class X>
struct unordered_generator : public unordered_generator_base<X>::type
{
typedef BOOST_DEDUCED_TYPENAME unordered_generator_base<X>::type base;
unordered_generator(random_generator const& type = default_generator)
: base(type)
template <class X>
struct unordered_generator_base
: public boost::detail::if_true<
test::is_set<X>::value
>::BOOST_NESTED_TEMPLATE then<
test::unordered_generator_set<X>,
test::unordered_generator_map<X>
>
{
}
};
};
template <class X>
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 = test::default_generator)
template <class X>
struct unordered_generator : public unordered_generator_base<X>::type
{
fill(count, generator);
}
typedef BOOST_DEDUCED_TYPENAME unordered_generator_base<X>::type base;
void fill(std::size_t count,
test::random_generator const& generator = test::default_generator)
unordered_generator(random_generator const& type = default_generator)
: base(type) {}
};
template <class X>
struct random_values
: public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
{
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
random_values(int count, test::random_generator const& generator =
test::default_generator)
{
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
}
#endif
+25 -26
View File
@@ -6,38 +6,37 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER
#include "./equivalent.hpp"
#include "./exception_test.hpp"
#include "./list.hpp"
#include <boost/config.hpp>
#include <iterator>
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
namespace test {
template <class X> class strong
namespace test
{
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
values_type values_;
unsigned int allocations_;
public:
void store(X const& x, unsigned int allocations = 0)
template <class X>
class strong
{
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
allocations_ = allocations;
}
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
values_type values_;
unsigned int allocations_;
public:
void store(X const& x, unsigned int allocations = 0) {
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
allocations_ = allocations;
}
void test(X const& x, unsigned int allocations = 0) const
{
if (!(x.size() == values_.size() &&
test::equal(
x.cbegin(), x.cend(), values_.begin(), test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
if (allocations != allocations_)
BOOST_ERROR("Strong exception failure: extra allocations.");
}
};
void test(X const& x, unsigned int allocations = 0) const {
if(!(x.size() == values_.size() &&
test::equal(x.cbegin(), x.cend(), values_.begin(),
test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
if(allocations != allocations_)
BOOST_ERROR("Strong exception failure: extra allocations.");
}
};
}
#endif
+68 -169
View File
@@ -9,197 +9,96 @@
#include <boost/detail/lightweight_test.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \
BOOST_PP_CAT(x, _type) \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::get_state().add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base { \
BOOST_PP_CAT(x, _type)() \
: ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::test_list::add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run() \
#define RUN_TESTS() \
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(); \
return boost::report_errors(); \
}
#define RUN_TESTS_QUIET() \
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(true); \
return boost::report_errors(); \
}
#define UNORDERED_SUB_TEST(x) \
for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
UNORDERED_SUB_TEST_VALUE; \
UNORDERED_SUB_TEST_VALUE = \
::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
#define RUN_TESTS() int main(int, char**) \
{ ::test::test_list::run_tests(); return boost::report_errors(); } \
namespace test {
struct registered_test_base {
registered_test_base* next;
char const* name;
explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0;
virtual ~registered_test_base() {}
};
struct registered_test_base
{
registered_test_base* next;
char const* name;
explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0;
virtual ~registered_test_base() {}
};
struct state
{
bool is_quiet;
registered_test_base* first_test;
registered_test_base* last_test;
state() : is_quiet(false), first_test(0), last_test(0) {}
void add_test(registered_test_base* test)
{
if (last_test) {
last_test->next = test;
} else {
first_test = test;
namespace test_list {
static inline registered_test_base*& first() {
static registered_test_base* ptr = 0;
return ptr;
}
last_test = test;
}
void run_tests(bool quiet = false)
{
is_quiet = quiet;
static inline registered_test_base*& last() {
static registered_test_base* ptr = 0;
return ptr;
}
for (registered_test_base* i = first_test; i; i = i->next) {
int error_count = boost::detail::test_errors();
if (!quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
<< std::flush;
static inline void add_test(registered_test_base* test) {
if(last()) {
last()->next = test;
}
i->run();
BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
if (quiet && error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name
<< "\n"
<< std::flush;
else {
first() = test;
}
last() = test;
}
static inline void run_tests() {
for(registered_test_base* i = first(); i; i = i->next) {
std::cout<<"Running "<<i->name<<"\n"<<std::flush;
i->run();
std::cerr<<std::flush;
std::cout<<std::flush;
}
}
}
int start_sub_test(char const* name)
{
if (!is_quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
<< std::flush;
}
// Add one because it's used as a loop condition.
return boost::detail::test_errors() + 1;
}
int end_sub_test(char const* name, int value)
{
if (is_quiet && value != boost::detail::test_errors() + 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name
<< "\n"
<< std::flush;
}
return 0;
}
};
// Get the currnet translation unit's test state.
static inline state& get_state()
{
static state instance;
return instance;
}
}
#if defined(__cplusplus)
#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
#else
#define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
#endif
#define BOOST_UNORDERED_TEST_COMPILER_INFO() \
{ \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Compiler: " << BOOST_COMPILER << "\n" \
<< "Library: " << BOOST_STDLIB << "\n" \
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
<< "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " \
<< BOOST_UNORDERED_EMPLACE_LIMIT << "\n" \
<< "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
<< BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
<< BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
<< std::flush; \
}
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/cat.hpp>
// 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(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)
#define UNORDERED_TEST_REPEAT(name, n, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, \
((name))((n)) 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)))
#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))) \
#define UNORDERED_TEST_OP2(name, n, 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); \
}
#define UNORDERED_TEST_OP2(name, n, 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); \
} \
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem)) \
#define UNORDERED_MULTI_TEST(name, impl, parameters) \
UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
UNORDERED_AUTO_TEST(name) \
{ \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
}
#define UNORDERED_MULTI_TEST_OP(r, product) \
UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
#define UNORDERED_MULTI_TEST_OP2(name, n, params) \
{ \
UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
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); \
} \
}
#endif
+135 -122
View File
@@ -9,139 +9,152 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER
#include "../objects/fwd.hpp"
#include "./equivalent.hpp"
#include "./helpers.hpp"
#include "./list.hpp"
#include "./metafunctions.hpp"
#include <algorithm>
#include <iterator>
#include <map>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/type_traits/is_same.hpp>
#include "../objects/fwd.hpp"
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
namespace test {
template <typename X> struct equals_to_compare
namespace test
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> type;
};
template <> struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
{
typedef test::list<BOOST_DEDUCED_TYPENAME X1::value_type> value_list;
value_list values1(x1.begin(), x1.end());
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
}
template <class X1, class X2, class T>
void compare_pairs(X1 const& x1, X2 const& x2, T*)
{
test::list<T> values1(x1.first, x1.second);
test::list<T> values2(x2.first, x2.second);
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), 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>
struct ordered_base;
template <typename X> struct ordered_base<X, true, true>
{
typedef std::set<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, true, false>
{
typedef std::multiset<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, true>
{
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>
type;
};
template <typename X> struct ordered_base<X, false, false>
{
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>
type;
};
template <class X> class ordered : public ordered_base<X>::type
{
typedef BOOST_DEDUCED_TYPENAME ordered_base<X>::type base;
public:
typedef BOOST_DEDUCED_TYPENAME base::key_compare key_compare;
ordered() : base() {}
explicit ordered(key_compare const& kc) : base(kc) {}
void compare(X const& x) { compare_range(x, *this); }
void compare_key(
X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val)
template <typename X>
struct equals_to_compare
{
compare_pairs(x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type>
type;
};
template <>
struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
template <class X1, class X2>
void compare_range(X1 const& x1, X2 const& x2)
{
typedef test::list<BOOST_DEDUCED_TYPENAME X1::value_type> value_list;
value_list values1(x1.begin(), x1.end());
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
}
template <class It> void insert_range(It b, It e)
template <class X1, class X2, class T>
void compare_pairs(X1 const& x1, X2 const& x2, T*)
{
while (b != e) {
this->insert(*b);
++b;
test::list<T> values1(x1.first, x1.second);
test::list<T> values2(x2.first, x2.second);
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(),
values2.begin(), test::equivalent));
}
template <typename X>
struct ordered_base;
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_set<V, H, P, A> >
{
typedef std::set<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
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<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
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<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
class ordered : public ordered_base<X>::type
{
typedef BOOST_DEDUCED_TYPENAME ordered_base<X>::type base;
public:
typedef BOOST_DEDUCED_TYPENAME base::key_compare key_compare;
ordered()
: base()
{}
explicit ordered(key_compare const& kc)
: base(kc)
{}
void compare(X const& x)
{
compare_range(x, *this);
}
void compare_key(X const& x,
BOOST_DEDUCED_TYPENAME X::value_type const& val)
{
compare_pairs(
x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)),
(BOOST_DEDUCED_TYPENAME X::value_type*) 0);
}
template <class It>
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
}
}
};
template <class Equals>
BOOST_DEDUCED_TYPENAME
equals_to_compare<Equals>::type create_compare(Equals const&)
{
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x;
return x;
}
};
template <class Equals>
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type create_compare(
Equals const&)
{
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x;
return x;
}
template <class X>
ordered<X> create_ordered(X const& container)
{
return ordered<X>(create_compare(container.key_eq()));
}
template <class X> ordered<X> create_ordered(X const& container)
{
return ordered<X>(create_compare(container.key_eq()));
}
template <class X1, class X2>
void check_container(X1 const& container, X2 const& values)
{
ordered<X1> tracker = create_ordered(container);
tracker.insert_range(values.begin(), values.end());
tracker.compare(container);
}
template <class X1, class X2>
void check_container(X1 const& container, X2 const& values)
{
ordered<X1> tracker = create_ordered(container);
tracker.insert_range(values.begin(), values.end());
tracker.compare(container);
}
}
#endif
+265 -292
View File
@@ -13,332 +13,305 @@
#include "../helpers/fwd.hpp"
#include "../helpers/memory.hpp"
namespace test {
struct allocator_false
namespace test
{
enum
struct allocator_false
{
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
struct allocator_flags_all
{
enum
{
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
struct select_copy : allocator_false
{
enum
{
is_select_on_copy = 1
};
};
struct propagate_swap : allocator_false
{
enum
{
is_propagate_on_swap = 1
};
};
struct propagate_assign : allocator_false
{
enum
{
is_propagate_on_assign = 1
};
};
struct propagate_move : allocator_false
{
enum
{
is_propagate_on_move = 1
};
};
struct no_select_copy : allocator_flags_all
{
enum
{
is_select_on_copy = 0
};
};
struct no_propagate_swap : allocator_flags_all
{
enum
{
is_propagate_on_swap = 0
};
};
struct no_propagate_assign : allocator_flags_all
{
enum
{
is_propagate_on_assign = 0
};
};
struct no_propagate_move : allocator_flags_all
{
enum
{
is_propagate_on_move = 0
};
};
template <typename Flag> struct swap_allocator_base
{
struct propagate_on_container_swap
{
enum
{
value = Flag::is_propagate_on_swap
enum {
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
};
template <typename Flag> struct assign_allocator_base
{
struct propagate_on_container_copy_assignment
struct allocator_flags_all
{
enum
{
value = Flag::is_propagate_on_assign
enum {
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
};
struct select_copy : allocator_false
{ enum { is_select_on_copy = 1 }; };
struct propagate_swap : allocator_false
{ enum { is_propagate_on_swap = 1 }; };
struct propagate_assign : allocator_false
{ enum { is_propagate_on_assign = 1 }; };
struct propagate_move : allocator_false
{ enum { is_propagate_on_move = 1 }; };
template <typename Flag> struct move_allocator_base
{
struct propagate_on_container_move_assignment
struct no_select_copy : allocator_flags_all
{ enum { is_select_on_copy = 0 }; };
struct no_propagate_swap : allocator_flags_all
{ enum { is_propagate_on_swap = 0 }; };
struct no_propagate_assign : allocator_flags_all
{ enum { is_propagate_on_assign = 0 }; };
struct no_propagate_move : allocator_flags_all
{ enum { is_propagate_on_move = 0 }; };
template <typename Flag>
struct swap_allocator_base
{
enum
struct propagate_on_container_swap {
enum { value = Flag::is_propagate_on_swap }; };
};
template <typename Flag>
struct assign_allocator_base
{
struct propagate_on_container_copy_assignment {
enum { value = Flag::is_propagate_on_assign }; };
};
template <typename Flag>
struct move_allocator_base
{
struct propagate_on_container_move_assignment {
enum { value = Flag::is_propagate_on_move }; };
};
namespace
{
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
struct force_equal_allocator
{
bool old_value_;
explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value)
{ force_equal_allocator_value = value; }
~force_equal_allocator()
{ force_equal_allocator_value = old_value_; }
};
template <typename T>
struct cxx11_allocator_base
{
int tag_;
int selected_;
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;
explicit cxx11_allocator_base(int t)
: tag_(t), selected_(0)
{
value = Flag::is_propagate_on_move
detail::tracker.allocator_ref();
}
template <typename Y> cxx11_allocator_base(
cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
~cxx11_allocator_base()
{
detail::tracker.allocator_unref();
}
pointer address(reference r)
{
return pointer(&r);
}
const_pointer address(const_reference r)
{
return const_pointer(&r);
}
pointer allocate(size_type n) {
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* u)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_,
!force_equal_allocator_value);
::operator delete((void*) p);
}
void construct(T* p, T const& t) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
#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)...);
}
#endif
void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
};
template <typename T, typename Flags = propagate_swap,
typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<
T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
{
}
template <typename Y> cxx11_allocator(
cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
{
}
cxx11_allocator(cxx11_allocator const& x)
: cxx11_allocator_base<T>(x)
{
}
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const
{
return !(*this == x);
}
};
};
namespace {
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
struct force_equal_allocator
{
bool old_value_;
explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value)
template <typename T, typename Flags>
struct cxx11_allocator<
T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
force_equal_allocator_value = value;
}
cxx11_allocator select_on_container_copy_construction() const
{
cxx11_allocator tmp(*this);
++tmp.selected_;
return tmp;
}
~force_equal_allocator() { force_equal_allocator_value = old_value_; }
};
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
template <typename T> struct cxx11_allocator_base
{
int tag_;
int selected_;
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
{
}
template <typename Y> cxx11_allocator(
cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
{
}
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;
cxx11_allocator(cxx11_allocator const& x)
: cxx11_allocator_base<T>(x)
{
}
explicit cxx11_allocator_base(int t) : tag_(t), selected_(0)
{
detail::tracker.allocator_ref();
}
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
template <typename Y>
cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer allocate(size_type n)
{
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 ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate(
(void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
::operator delete((void*)p);
}
void construct(T* p, T const& t)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
}
#if !defined(BOOST_NO_CXX11_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)...);
}
#endif
void destroy(T* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const
{
return (std::numeric_limits<size_type>::max)();
}
};
template <typename T, typename Flags = propagate_swap, typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind
{
typedef cxx11_allocator<U, Flags> other;
bool operator!=(cxx11_allocator const& x) const
{
return !(*this == x);
}
};
#endif
explicit cxx11_allocator(int t = 0) : cxx11_allocator_base<T>(t) {}
template <typename Y>
cxx11_allocator(cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
template <typename T, typename Flags>
bool equivalent_impl(
cxx11_allocator<T, Flags> const& x,
cxx11_allocator<T, Flags> const& y,
test::derived_type)
{
return x.tag_ == y.tag_;
}
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
struct convert_from_anything
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
};
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
cxx11_allocator select_on_container_copy_construction() const
{
cxx11_allocator tmp(*this);
++tmp.selected_;
return tmp;
}
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind
{
typedef cxx11_allocator<U, Flags> other;
template <typename T>
convert_from_anything(T const&) {}
};
#endif
explicit cxx11_allocator(int t = 0) : cxx11_allocator_base<T>(t) {}
template <typename Y>
cxx11_allocator(cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
inline int selected_count(convert_from_anything)
{
return 0;
}
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
return x.selected_;
}
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
};
template <typename T, typename Flags>
bool equivalent_impl(cxx11_allocator<T, Flags> const& x,
cxx11_allocator<T, Flags> const& y, test::derived_type)
{
return x.tag_ == y.tag_;
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
template <typename T> convert_from_anything(T const&) {}
};
inline int selected_count(convert_from_anything) { return 0; }
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
return x.selected_;
}
}
#endif
+515 -670
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -6,12 +6,13 @@
#if !defined(BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER)
#define BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER
namespace test {
class object;
class hash;
class less;
class equal_to;
template <class T> class allocator;
namespace test
{
class object;
class hash;
class less;
class equal_to;
template <class T> class allocator;
}
#endif
+432 -542
View File
File diff suppressed because it is too large Load Diff
+550 -603
View File
File diff suppressed because it is too large Load Diff
+68
View File
@@ -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 ]
;
+89 -118
View File
@@ -3,93 +3,71 @@
// 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/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered/detail/implementation.hpp>
#include <boost/static_assert.hpp>
#include <boost/limits.hpp>
// Boilerplate
#define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r; } \
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*) \
{ \
return static_cast<T*>(::operator new(n * sizeof(T))); \
} \
void deallocate(T* p, std::size_t) { ::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 \
{ \
return (std::numeric_limits<std::size_t>::max)(); \
} \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
#define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r;} \
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* u) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
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 \
{ return (std::numeric_limits<std::size_t>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
#define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r; } \
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*) \
{ \
return pointer(::operator new(n * sizeof(T))); \
} \
void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \
size_type max_size() const \
{ \
return (std::numeric_limits<size_type>::max)(); \
} \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
#define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r;} \
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* u) \
{ return pointer(::operator new(n * sizeof(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(); } \
size_type max_size() const \
{ return (std::numeric_limits<size_type>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
struct yes_type
{
enum
{
value = true
};
};
struct no_type
{
enum
{
value = false
};
};
struct yes_type { enum { value = true }; };
struct no_type { enum { value = false }; };
// For tracking calls...
static int selected;
void reset() { selected = 0; }
void reset() {
selected = 0;
}
template <typename Allocator> int call_select()
template <typename Allocator>
int call_select()
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
@@ -101,7 +79,8 @@ template <typename Allocator> int call_select()
// Empty allocator test
template <typename T> struct empty_allocator
template <typename T>
struct empty_allocator
{
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
@@ -115,14 +94,11 @@ void test_empty_allocator()
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
@@ -132,17 +108,17 @@ void test_empty_allocator()
// allocator 1
template <typename T> struct allocator1
template <typename T>
struct allocator1
{
typedef T value_type;
ALLOCATOR_METHODS(allocator1)
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
allocator1<T> select_on_container_copy_construction() const
{
allocator1<T> select_on_container_copy_construction() const {
++selected;
return allocator1<T>();
}
@@ -156,14 +132,11 @@ void test_allocator1()
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
@@ -173,24 +146,25 @@ void test_allocator1()
// allocator 2
template <typename Alloc> struct allocator2_base
template <typename Alloc>
struct allocator2_base
{
Alloc select_on_container_copy_construction() const
{
Alloc select_on_container_copy_construction() const {
++selected;
return Alloc();
}
};
template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
template <typename T>
struct allocator2 : allocator2_base<allocator2<T> >
{
typedef T value_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::size_t size_type;
ALLOCATOR_METHODS(allocator2)
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
@@ -200,13 +174,10 @@ void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
@@ -216,27 +187,31 @@ void test_allocator2()
// allocator 3
template <typename T> struct ptr
template <typename T>
struct ptr
{
T* value_;
ptr(void* v) : value_((T*)v) {}
ptr(void* v) : value_((T*) v) {}
T& operator*() const { return *value_; }
};
template <> struct ptr<void>
template <>
struct ptr<void>
{
void* value_;
ptr(void* v) : value_(v) {}
};
template <> struct ptr<const void>
template <>
struct ptr<const void>
{
void const* value_;
ptr(void const* v) : value_(v) {}
};
template <typename T> struct allocator3
template <typename T>
struct allocator3
{
typedef T value_type;
typedef ptr<T> pointer;
@@ -244,12 +219,11 @@ template <typename T> struct allocator3
typedef unsigned short size_type;
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
allocator3<T> select_on_container_copy_construction() const
{
allocator3<T> select_on_container_copy_construction() const {
++selected;
return allocator3<T>();
}
@@ -259,13 +233,10 @@ void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+79 -77
View File
@@ -3,13 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -17,20 +14,23 @@
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include <iostream>
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace assign_tests {
test::seed_t initialize_seed(96785);
template <class T> void assign_tests1(T*, test::random_generator generator)
template <class T>
void assign_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
std::cerr<<"assign_tests1.1\n";
{
test::check_instances check_;
@@ -41,7 +41,7 @@ template <class T> void assign_tests1(T*, test::random_generator generator)
BOOST_TEST(test::equivalent(x.key_eq(), eq));
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
std::cerr<<"assign_tests1.2\n";
{
test::check_instances check_;
@@ -66,7 +66,8 @@ template <class T> void assign_tests1(T*, test::random_generator generator)
}
}
template <class T> void assign_tests2(T*, test::random_generator generator)
template <class T>
void assign_tests2(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
@@ -74,24 +75,10 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
std::cerr<<"assign_tests2.1\n";
{
test::check_instances check_;
@@ -108,7 +95,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
std::cerr<<"assign_tests2.1a\n";
{
test::check_instances check_;
@@ -126,7 +113,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
std::cerr<<"assign_tests2.2\n";
{
test::check_instances check_;
@@ -139,7 +126,8 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
@@ -148,7 +136,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
std::cerr<<"assign_tests2.3\n";
{
test::check_instances check_;
@@ -161,7 +149,8 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
@@ -170,7 +159,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
std::cerr<<"assign_tests2.4\n";
{
test::check_instances check_;
@@ -183,7 +172,8 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
@@ -193,51 +183,62 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multiset_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multimap_prop_assign;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multiset_no_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
template <typename T>
bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
@@ -249,27 +250,27 @@ UNORDERED_AUTO_TEST(check_traits)
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
}
UNORDERED_TEST(assign_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
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)))
UNORDERED_TEST(assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(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))
)
UNORDERED_TEST(
assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)(
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)))
UNORDERED_TEST(assign_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(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))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init;
boost::unordered_map<int, int> x1;
x1[25] = 3;
@@ -284,17 +285,18 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::cerr<<"Initializer List Tests\n";
boost::unordered_set<int> x;
x.insert(10);
x.insert(20);
x = {1, 2, -10};
x = { 1, 2, -10 };
BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end());
}
#endif
}
RUN_TESTS()
+4 -27
View File
@@ -3,37 +3,20 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <string>
namespace at_tests {
UNORDERED_AUTO_TEST(at_tests)
{
UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
try {
x.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
try {
x_const.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
@@ -44,25 +27,19 @@ UNORDERED_AUTO_TEST(at_tests)
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
BOOST_TEST(x_const.at("one") == 1);
BOOST_TEST(x_const.at("two") == 2);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
try {
x.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
try {
x_const.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
catch(std::out_of_range) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
RUN_TESTS()
+39 -37
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <algorithm>
@@ -17,15 +15,16 @@
#include "../helpers/helpers.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#endif
namespace bucket_tests {
test::seed_t initialize_seed(54635);
template <class X> void tests(X*, test::random_generator generator)
template <class X>
void tests(X*, test::random_generator generator)
{
test::check_instances check_;
@@ -35,62 +34,65 @@ template <class X> 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())) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << 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) {
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = v.begin(), end = v.end(); it != end; ++it)
{
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 &&
test::get_key<X>(*it) != test::get_key<X>(*lit)) {
while(lit != lend
&& test::get_key<X>(*it) != test::get_key<X>(*lit))
{
++lit;
}
BOOST_TEST(lit != lend);
}
}
for (size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_TEST(x.bucket_size(i) ==
static_cast<size_type>(std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x.cbegin(i), x.cend(i))));
for(size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x.cbegin(i), x.cend(i))));
X const& x_ref = x;
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.cbegin(i), x_ref.cend(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x_ref.cbegin(i), x_ref.cend(i))));
}
}
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
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))
((default_generator)(generate_collisions))
)
}
RUN_TESTS()
+80 -110
View File
@@ -6,105 +6,110 @@
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <iostream>
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
template class boost::unordered_map<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_multimap<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
INSTANTIATE(multimap)<int const, int const, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >;
INSTANTIATE(map)<test::minimal::assignable const,
test::minimal::default_assignable const,
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
test::minimal::allocator<test::minimal::assignable> >;
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const,
test::minimal::assignable>
value_type;
test::minimal::assignable> value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
std::cout<<"Test unordered_map.\n";
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
boost::unordered_map<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
test::minimal::allocator<value_type> > map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<test::minimal::assignable,
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
multimap;
test::minimal::allocator<value_type> > multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
}
UNORDERED_AUTO_TEST(equality_tests)
{
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_equality_comparable const,
test::minimal::copy_constructible_equality_comparable> value_type;
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > map;
equality_test(int_map);
equality_test(int_map2);
@@ -112,39 +117,37 @@ UNORDERED_AUTO_TEST(equality_tests)
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multimap;
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
UNORDERED_AUTO_TEST(test1)
{
UNORDERED_AUTO_TEST(test1) {
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
std::cout<<"Test unordered_map.\n";
boost::unordered_map<int, int> map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> map2;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
@@ -156,13 +159,14 @@ UNORDERED_AUTO_TEST(test1)
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> multimap2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
@@ -183,79 +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;
test::minimal::assignable> map_value_type;
map_value_type map_value(assignable, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
std::cout<<"Test unordered_map.\n";
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
boost::unordered_map<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
test::minimal::allocator<map_value_type> > map;
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
boost::unordered_map<test::minimal::assignable,
boost::unordered_map<
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
test::minimal::allocator<map_value_type> > map2;
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<test::minimal::assignable,
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
multimap;
test::minimal::allocator<map_value_type> > multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
int value;
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059)
{
{
boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
{
boost::unordered_multimap<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
}
RUN_TESTS()
+95 -126
View File
@@ -6,34 +6,38 @@
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <iostream>
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
template class boost::unordered_set<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
template class boost::unordered_multiset<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
INSTANTIATE(set)<test::minimal::assignable const,
template class boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<test::minimal::assignable,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
test::minimal::allocator<test::minimal::assignable> >;
UNORDERED_AUTO_TEST(test0)
{
@@ -41,61 +45,60 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<test::minimal::assignable,
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
test::minimal::allocator<test::minimal::assignable> > set;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<test::minimal::assignable,
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
test::minimal::allocator<test::minimal::assignable> > multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(equality_tests)
{
UNORDERED_AUTO_TEST(equality_tests) {
typedef test::minimal::copy_constructible_equality_comparable value_type;
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > set;
equality_test(int_set);
equality_test(int_set2);
@@ -103,18 +106,16 @@ UNORDERED_AUTO_TEST(equality_tests)
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multiset;
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
@@ -127,13 +128,14 @@ UNORDERED_AUTO_TEST(test1)
std::equal_to<int> equal_to;
int value = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
std::cout<<"Test unordered_set." << std::endl;
boost::unordered_set<int> set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> set2;
unordered_unique_test(set, value);
unordered_set_test(set, value);
@@ -143,13 +145,14 @@ UNORDERED_AUTO_TEST(test1)
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
std::cout<<"Test unordered_multiset." << std::endl;
boost::unordered_multiset<int> multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
multiset2;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> multiset2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
@@ -163,37 +166,35 @@ UNORDERED_AUTO_TEST(test1)
UNORDERED_AUTO_TEST(test2)
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
std::cout<<"Test unordered_set.\n";
boost::unordered_set<test::minimal::assignable,
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
test::minimal::allocator<test::minimal::assignable> > set;
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);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::assignable,
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
test::minimal::allocator<test::minimal::assignable> > multiset;
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)
@@ -204,27 +205,27 @@ UNORDERED_AUTO_TEST(movable1_tests)
test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
std::cout<<"Test unordered_set.\n";
boost::unordered_set<test::minimal::movable1,
boost::unordered_set<
test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
test::minimal::allocator<test::minimal::movable1> > set;
// unordered_unique_test(set, movable1);
//unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable1,
boost::unordered_multiset<
test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
multiset;
test::minimal::allocator<test::minimal::movable1> > multiset;
// unordered_equivalent_test(multiset, movable1);
//unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
}
@@ -237,27 +238,27 @@ UNORDERED_AUTO_TEST(movable2_tests)
test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
std::cout<<"Test unordered_set.\n";
boost::unordered_set<test::minimal::movable2,
boost::unordered_set<
test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
test::minimal::allocator<test::minimal::movable2> > set;
// unordered_unique_test(set, movable2);
//unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable2,
boost::unordered_multiset<
test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
multiset;
test::minimal::allocator<test::minimal::movable2> > multiset;
// unordered_equivalent_test(multiset, movable2);
//unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
}
@@ -270,55 +271,23 @@ UNORDERED_AUTO_TEST(destructible_tests)
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
std::cout<<"Test unordered_set.\n";
boost::unordered_set<test::minimal::destructible,
boost::unordered_set<
test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
test::minimal::equal_to<test::minimal::destructible> > set;
unordered_destructible_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
boost::unordered_multiset<
test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
test::minimal::equal_to<test::minimal::destructible> > multiset;
unordered_destructible_test(multiset);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
int value;
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059)
{
{
boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
{
boost::unordered_multiset<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
}
RUN_TESTS()
+115 -444
View File
@@ -5,9 +5,9 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4100) // unreferenced formal parameter
#pragma warning(disable : 4610) // class can never be instantiated
#pragma warning(disable : 4510) // default constructor could not be generated
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4610) // class can never be instantiated
#pragma warning(disable:4510) // default constructor could not be generated
#endif
#include <boost/concept_check.hpp>
@@ -16,15 +16,13 @@
#pragma warning(pop)
#endif
#include "../helpers/check_return_type.hpp"
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/limits.hpp>
#include <boost/predef.h>
#include <boost/static_assert.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/swap.hpp>
#include "../helpers/check_return_type.hpp"
typedef long double comparison_type;
@@ -32,47 +30,28 @@ template <class T> void sink(T const&) {}
template <class T> T rvalue(T const& v) { return v; }
template <class T> T rvalue_default() { return T(); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T> T implicit_construct() { return {}; }
#else
template <class T> int implicit_construct()
{
T x;
sink(x);
return 0;
}
#endif
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
#define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x)));
#else
#define TEST_NOEXCEPT_EXPR(x)
#endif
template <class X, class T> void container_test(X& r, T const&)
template <class X, class T>
void container_test(X& r, T const&)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<iterator>::type
iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<const_iterator>::type
const_iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type
iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
const_iterator>::type const_iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_value<iterator>::type iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_value<const_iterator>::type const_iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<iterator>::type iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_iterator>::type
const_iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::reference reference;
typedef BOOST_DEDUCED_TYPENAME X::const_reference const_reference;
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
// value_type
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
@@ -87,27 +66,21 @@ template <class X, class T> void container_test(X& r, T const&)
boost::function_requires<boost::InputIteratorConcept<iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
BOOST_STATIC_ASSERT(
(boost::is_convertible<iterator, const_iterator>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
// const_iterator
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
// node_type
BOOST_STATIC_ASSERT((boost::is_same<allocator_type,
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value));
// difference_type
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
BOOST_STATIC_ASSERT(
(boost::is_same<difference_type, iterator_difference_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>::value));
iterator_difference_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>::value));
// size_type
@@ -116,40 +89,28 @@ template <class X, class T> 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));
BOOST_TEST((std::numeric_limits<difference_type>::max)() == converted_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);
BOOST_TEST(
static_cast<comparison_type>((std::numeric_limits<size_type>::max)()) >
static_cast<comparison_type>(
(std::numeric_limits<size_type>::max)()) >
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
// I don't test the runtime post-conditions here.
X u;
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
X a, b;
X a,b;
X a_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);
@@ -157,56 +118,18 @@ template <class X, class T> void container_test(X& r, T const&)
// Allocator
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);
// node_type
implicit_construct<node_type const>();
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
TEST_NOEXCEPT_EXPR(node_type());
#endif
node_type n1;
node_type n2(rvalue_default<node_type>());
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
TEST_NOEXCEPT_EXPR(node_type(boost::move(n1)));
#endif
node_type n3;
n3 = boost::move(n2);
n1.swap(n3);
swap(n1, n3);
// TODO: noexcept for swap?
// value, key, mapped tests in map and set specific testing.
node_type const n_const;
BOOST_TEST(n_const ? 0 : 1);
TEST_NOEXCEPT_EXPR(n_const ? 0 : 1);
test::check_return_type<bool>::equals(!n_const);
test::check_return_type<bool>::equals(n_const.empty());
TEST_NOEXCEPT_EXPR(!n_const);
TEST_NOEXCEPT_EXPR(n_const.empty());
// Avoid unused variable warnings:
sink(u);
sink(u2);
sink(u3);
sink(u4);
sink(u5);
sink(c);
sink(c2);
sink(c3);
}
template <class X> void unordered_destructible_test(X&)
template <class X>
void unordered_destructible_test(X&)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
@@ -214,20 +137,19 @@ template <class X> 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
// is true.
// x2 = rvalue_default<X>();
// This can only be done if propagate_on_container_move_assignment::value
// is true.
// x2 = rvalue_default<X>();
#endif
X* ptr = new X();
X& a1 = *ptr;
(&a1)->~X();
::operator delete((void*)(&a1));
X a, b;
X a,b;
X const a_const;
test::check_return_type<iterator>::equals(a.begin());
test::check_return_type<const_iterator>::equals(a_const.begin());
@@ -240,7 +162,7 @@ template <class X> void unordered_destructible_test(X&)
a.swap(b);
boost::swap(a, b);
test::check_return_type<size_type>::equals(a.size());
test::check_return_type<size_type>::equals(a.max_size());
test::check_return_type<bool>::convertible(a.empty());
@@ -251,48 +173,13 @@ template <class X> void unordered_destructible_test(X&)
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
}
template <class X, class Key> void unordered_set_test(X& r, Key const&)
template <class X, class Key>
void unordered_set_test(X&, Key const&)
{
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
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));
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type;
BOOST_STATIC_ASSERT((boost::is_same<value_type, node_value_type>::value));
// Call node_type functions.
test::minimal::constructor_param v;
Key k_lvalue(v);
r.emplace(boost::move(k_lvalue));
node_type n1 = r.extract(r.begin());
test::check_return_type<value_type>::equals_ref(n1.value());
}
template <class X, class Key, class T>
@@ -301,95 +188,21 @@ void unordered_map_test(X& r, Key const& k, T const& v)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
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));
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type;
typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type;
BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
// Superfluous,but just to make sure.
BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value));
// Calling functions
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
r.insert(std::pair<Key const, T>(k, v));
r.insert(r.begin(), std::pair<Key const, T>(k, v));
std::pair<Key const, T> const value(k, v);
r.insert(value);
r.insert(r.end(), value);
Key k_lvalue(k);
T v_lvalue(v);
// Emplace
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));
// Emplace with hint
r.emplace_hint(r.begin(), k, v);
r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
// Extract
test::check_return_type<node_type>::equals(r.extract(r.begin()));
r.emplace(k, v);
test::check_return_type<node_type>::equals(r.extract(k));
r.emplace(k, v);
node_type n1 = r.extract(r.begin());
test::check_return_type<key_type>::equals_ref(n1.key());
test::check_return_type<T>::equals_ref(n1.mapped());
node_type n2 = boost::move(n1);
r.insert(boost::move(n2));
r.insert(r.extract(r.begin()));
n2 = r.extract(r.begin());
r.insert(r.begin(), boost::move(n2));
r.insert(r.end(), r.extract(r.begin()));
node_type n = r.extract(r.begin());
test::check_return_type<node_key_type>::equals_ref(n.key());
test::check_return_type<node_mapped_type>::equals_ref(n.mapped());
}
template <class X> void equality_test(X& r)
template <class X>
void equality_test(X& r)
{
X const a = r, b = r;
@@ -399,36 +212,16 @@ template <class X> void equality_test(X& r)
test::check_return_type<bool>::equals(boost::operator!=(a, b));
}
template <class X, class T> void unordered_unique_test(X& r, T const& t)
template <class X, class T>
void unordered_unique_test(X& r, T const& t)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME X::insert_return_type insert_return_type;
// insert_return_type
// TODO;
// boost::function_requires<boost::MoveConstructibleConcept<insert_return_type>
// >();
// TODO;
// boost::function_requires<boost::MoveAssignableConcept<insert_return_type>
// >();
boost::function_requires<
boost::DefaultConstructibleConcept<insert_return_type> >();
// TODO:
// boost::function_requires<boost::DestructibleConcept<insert_return_type>
// >();
insert_return_type insert_return, insert_return2;
test::check_return_type<bool>::equals(insert_return.inserted);
test::check_return_type<iterator>::equals(insert_return.position);
test::check_return_type<node_type>::equals_ref(insert_return.node);
boost::swap(insert_return, insert_return2);
}
template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
template <class X, class T>
void unordered_equivalent_test(X& r, T const& t)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
test::check_return_type<iterator>::equals(r.insert(t));
@@ -436,30 +229,13 @@ template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
}
template <class X, class Key, class T>
void unordered_map_functions(X&, Key const& k, T const& v)
void unordered_map_functions(X&, Key const& k, T const&)
{
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
X a;
test::check_return_type<mapped_type>::equals_ref(a[k]);
test::check_return_type<mapped_type>::equals_ref(a[rvalue(k)]);
test::check_return_type<mapped_type>::equals_ref(a.at(k));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.try_emplace(k, v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.try_emplace(rvalue(k), v));
test::check_return_type<iterator>::equals(a.try_emplace(a.begin(), k, v));
test::check_return_type<iterator>::equals(
a.try_emplace(a.begin(), rvalue(k), v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.insert_or_assign(k, v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.insert_or_assign(rvalue(k), v));
test::check_return_type<iterator>::equals(
a.insert_or_assign(a.begin(), k, v));
test::check_return_type<iterator>::equals(
a.insert_or_assign(a.begin(), rvalue(k), v));
X const b = a;
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
@@ -481,45 +257,60 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<iterator>::type iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type
boost::BOOST_ITERATOR_CATEGORY<iterator>::type
iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<iterator>::type
iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type
iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<iterator>::type
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<iterator>::type
iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
local_iterator>::type local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
local_iterator>::type local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<local_iterator>::type
local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<local_iterator>::type
local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type
local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<
local_iterator>::type local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<local_iterator>::type
local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
const_iterator>::type const_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
const_iterator>::type const_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<const_iterator>::type
const_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_iterator>::type
const_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<
const_iterator>::type const_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_iterator>::type
const_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
const_local_iterator>::type const_local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
const_local_iterator>::type const_local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<
const_local_iterator>::type const_local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<
const_local_iterator>::type const_local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<const_local_iterator>::type
const_local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_local_iterator>::type
const_local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
// boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
// boost::function_requires<boost::AssignableConcept<key_type> >();
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
//boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
test::check_return_type<std::size_t>::equals(hf(k));
@@ -528,14 +319,14 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<bool>::convertible(eq(k, k));
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
BOOST_STATIC_ASSERT(
(boost::is_same<local_iterator_category, iterator_category>::value));
BOOST_STATIC_ASSERT((
boost::is_same<local_iterator_difference, iterator_difference>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<local_iterator_pointer, iterator_pointer>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<local_iterator_reference, iterator_reference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_category,
iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>::value));
boost::function_requires<
boost::InputIteratorConcept<const_local_iterator> >();
@@ -548,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);
@@ -562,21 +348,11 @@ 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();
test::check_return_type<iterator>::equals(a.erase(q1, q2));
TEST_NOEXCEPT_EXPR(a.clear());
a.clear();
X const b;
@@ -588,9 +364,9 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<const_iterator>::equals(b.find(k));
test::check_return_type<size_type>::equals(b.count(k));
test::check_return_type<std::pair<iterator, iterator> >::equals(
a.equal_range(k));
a.equal_range(k));
test::check_return_type<std::pair<const_iterator, const_iterator> >::equals(
b.equal_range(k));
b.equal_range(k));
test::check_return_type<size_type>::equals(b.bucket_count());
test::check_return_type<size_type>::equals(b.max_bucket_count());
test::check_return_type<size_type>::equals(b.bucket(k));
@@ -608,25 +384,15 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<float>::equals(b.load_factor());
test::check_return_type<float>::equals(b.max_load_factor());
a.max_load_factor((float)2.0);
a.max_load_factor((float) 2.0);
a.rehash(100);
a.merge(a2);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
a.merge(rvalue_default<X>());
#endif
// 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>
@@ -636,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);
@@ -655,64 +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);
X b1;
b1.insert(t);
X a9b(b1);
sink(a9b);
X a9c(b1, m);
sink(a9c);
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) && \
(!defined(__clang__) || __clang_major__ >= 4 || \
(__clang_major__ == 3 && __clang_minor__ >= 4))
a.insert({});
a.insert({t});
a.insert({t, t});
#endif
#endif
X a10;
a10.insert(t);
@@ -727,15 +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);
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
node_type const n_const = a.extract(a.begin());
test::check_return_type<allocator_type>::equals(n_const.get_allocator());
}
template <class X, class Key, class T, class Hash, class Pred>
@@ -745,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* 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);
@@ -771,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();
@@ -795,9 +486,10 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
a.insert(boost::move(v2));
T v3(v);
test::check_return_type<iterator>::equals(
a.emplace_hint(q, boost::move(v3)));
a.emplace_hint(q, boost::move(v3)));
T v4(v);
test::check_return_type<iterator>::equals(a.insert(q, boost::move(v4)));
test::check_return_type<iterator>::equals(
a.insert(q, boost::move(v4)));
a.insert(i, j);
@@ -814,26 +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();
}
+78 -66
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -22,13 +20,14 @@ namespace constructor_tests {
test::seed_t initialize_seed(356730);
template <class T> void constructor_tests1(T*, test::random_generator generator)
template <class T>
void constructor_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
UNORDERED_SUB_TEST("Construct 1")
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
@@ -40,7 +39,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 2")
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
@@ -53,7 +52,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 3")
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
@@ -66,7 +65,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 4")
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
@@ -78,7 +77,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 5")
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
@@ -92,7 +91,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 6")
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
@@ -106,7 +105,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 7")
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
@@ -120,7 +119,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 8")
std::cerr<<"Construct 8\n";
{
test::check_instances check_;
@@ -133,7 +132,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 9")
std::cerr<<"Construct 9\n";
{
test::check_instances check_;
@@ -145,7 +144,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 10")
std::cerr<<"Construct 10\n";
{
test::check_instances check_;
@@ -159,7 +158,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 11")
std::cerr<<"Construct 11\n";
{
test::check_instances check_;
@@ -185,7 +184,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
UNORDERED_SUB_TEST("Construct 1")
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
T x(10000, hf1, eq1);
@@ -196,7 +195,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 2")
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf1);
@@ -208,7 +207,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 3")
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
@@ -220,7 +219,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 4")
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
test::random_values<T> v(5, generator);
@@ -233,7 +232,8 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 5")
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
@@ -245,7 +245,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 6")
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
@@ -257,7 +257,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 7")
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
@@ -269,40 +269,39 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 8 - from input iterator")
std::cerr<<"Construct 8 - from input iterator\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
v_begin = v.begin(),
v_end = v.end();
T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1,
eq1);
BOOST_DEDUCED_TYPENAME T::const_iterator x_begin = x.begin(),
x_end = x.end();
T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2,
eq2);
v_begin = v.begin(), v_end = v.end();
T x(test::input_iterator(v_begin),
test::input_iterator(v_end), 0, hf1, eq1);
BOOST_DEDUCED_TYPENAME T::const_iterator
x_begin = x.begin(), x_end = x.end();
T y(test::input_iterator(x_begin),
test::input_iterator(x_end), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator")
std::cerr<<"Construct 8.5 - from copy iterator\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0,
hf1, eq1);
T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0,
hf2, eq2);
T x(test::copy_iterator(v.begin()),
test::copy_iterator(v.end()), 0, hf1, eq1);
T y(test::copy_iterator(x.begin()),
test::copy_iterator(x.end()), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 9")
std::cerr<<"Construct 9\n";
{
test::check_instances check_;
@@ -319,8 +318,8 @@ void constructor_tests2(T*, test::random_generator const& generator)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
UNORDERED_SUB_TEST("Initializer list construct 1")
std::cerr<<"Initializer list construct 1\n";
{
test::check_instances check_;
@@ -331,7 +330,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 2")
std::cerr<<"Initializer list construct 2\n";
{
test::check_instances check_;
@@ -343,7 +342,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 3")
std::cerr<<"Initializer list construct 3\n";
{
test::check_instances check_;
@@ -355,7 +354,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 4")
std::cerr<<"Initializer list construct 4\n";
{
test::check_instances check_;
@@ -367,7 +366,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 5")
std::cerr<<"Initializer list construct 5\n";
{
test::check_instances check_;
@@ -384,9 +383,14 @@ void constructor_tests2(T*, test::random_generator const& generator)
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
{
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type,
BOOST_DEDUCED_TYPENAME T::mapped_type> >
list;
std::cerr<<"map_constructor_test\n";
typedef test::list<
std::pair<
BOOST_DEDUCED_TYPENAME T::key_type,
BOOST_DEDUCED_TYPENAME T::mapped_type
>
> list;
test::random_values<T> v(1000, generator);
list l(v.begin(), v.end());
T x(l.begin(), l.end());
@@ -395,38 +399,45 @@ void map_constructor_test(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
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(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(constructor_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
((test_map_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list)
{
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
std::initializer_list<int> init;
boost::unordered_set<int> x1 = init;
BOOST_TEST(x1.empty());
@@ -436,14 +447,15 @@ UNORDERED_AUTO_TEST(test_default_initializer_list)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list)
{
boost::unordered_set<int> x1 = {2, 10, 45, -5};
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
boost::unordered_set<int> x1 = { 2, 10, 45, -5 };
BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end());
}
#endif
}
RUN_TESTS_QUIET()
RUN_TESTS()
+57 -46
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -20,7 +18,8 @@
test::seed_t initialize_seed(9063);
namespace copy_tests {
namespace copy_tests
{
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator)
@@ -29,7 +28,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
{
test::check_instances check_;
@@ -42,7 +41,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
@@ -56,7 +55,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
@@ -76,7 +75,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
// This isn't guaranteed:
BOOST_TEST(y.load_factor() < y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
}
@@ -88,7 +87,7 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
@@ -102,7 +101,7 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
@@ -131,7 +130,7 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
}
@@ -150,60 +149,72 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
}
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_set_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_multiset_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_map_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_multimap_select_copy;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_set_no_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multiset_no_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_map_no_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
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_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))
)
UNORDERED_TEST(copy_construct_tests2, (
(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))
)
UNORDERED_TEST(copy_construct_tests2,
((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)))
}
RUN_TESTS()
-102
View File
@@ -1,102 +0,0 @@
// Copyright 2017 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <map>
// Pretty inefficient, but the test is fast enough.
// Might be too slow if we had larger primes?
bool is_prime(std::size_t x)
{
if (x == 2) {
return true;
} else if (x == 1 || x % 2 == 0) {
return false;
} else {
// y*y <= x had rounding errors, so instead use y <= (x/y).
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
break;
}
}
return true;
}
}
void test_next_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::next_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x >= value);
}
void test_prev_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::prev_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x <= value);
if (x > value) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
}
}
UNORDERED_AUTO_TEST(next_prime_test)
{
BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100));
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
// test_prev_prime doesn't work for values less than 17.
// Which should be okay, unless an allocator has a really tiny
// max_size?
const std::size_t min_prime = 17;
// test_next_prime doesn't work for values greater than this,
// which might be a problem if you've got terrabytes of memory?
// I seriously doubt the container would work well at such sizes
// regardless.
const std::size_t max_prime = 4294967291ul;
std::size_t i;
BOOST_TEST(is_prime(min_prime));
BOOST_TEST(is_prime(max_prime));
for (i = 0; i < 10000; ++i) {
if (i < min_prime) {
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
} else {
test_prev_prime(i);
}
test_next_prime(i);
}
std::size_t last = i - 1;
for (; i > last; last = i, i += i / 5) {
if (i > max_prime) {
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
} else {
test_next_prime(i);
}
test_prev_prime(i);
}
}
RUN_TESTS()
-519
View File
@@ -1,519 +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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#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);
}
UNORDERED_AUTO_TEST(try_emplace)
{
test::check_instances check_;
typedef boost::unordered_map<int, emplace_value> container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2, r3;
int k1 = 3;
emplace_value m1(414, "grr");
r1 = x.try_emplace(3, 414, "grr");
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first == k1);
BOOST_TEST(r1.first->second == m1);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(check_.instances(), 2);
BOOST_TEST_EQ(check_.constructions(), 2);
int k2 = 10;
emplace_value m2(25, "", 'z');
r2 = x.try_emplace(10, 25, std::string(""), 'z');
BOOST_TEST(r2.second);
BOOST_TEST(r2.first->first == k2);
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST(x.find(k2)->second == m2);
r3 = x.try_emplace(k2, 68, "jfeoj", 'p', 49309, 2323);
BOOST_TEST(!r3.second);
BOOST_TEST(r3.first == r2.first);
BOOST_TEST(r3.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST(
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
}
}
RUN_TESTS()
+174
View File
@@ -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()
+144 -128
View File
@@ -3,163 +3,179 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
namespace equality_tests {
struct mod_compare
namespace equality_tests
{
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; }
std::size_t operator()(int x) const
struct mod_compare
{
return alt_hash_ ? static_cast<std::size_t>(x % 250)
: static_cast<std::size_t>((x + 5) % 250);
}
};
bool alt_hash_;
#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); \
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_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_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_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) \
#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));
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));
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))
}
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=,
((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==,
((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST(equality_map_value_test)
{
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
}
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), !=, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_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_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(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))
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST(equality_map_value_test)
{
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST((1), !=, (1001))
UNORDERED_EQUALITY_MAP_TEST(((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(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);
}
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()
+18 -12
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <algorithm>
@@ -17,6 +15,8 @@
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
template <class Container, class Iterator>
void test_equal_insertion(Iterator begin, Iterator end)
{
@@ -25,7 +25,7 @@ void test_equal_insertion(Iterator begin, Iterator end)
Container x1;
tracker x2 = test::create_ordered(x1);
for (Iterator it = begin; it != end; ++it) {
for(Iterator it = begin; it != end; ++it) {
x1.insert(*it);
x2.insert(*it);
x2.compare_key(x1, *it);
@@ -37,7 +37,13 @@ void test_equal_insertion(Iterator begin, Iterator end)
UNORDERED_AUTO_TEST(set_tests)
{
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
int values[][5] = {
{1},
{54, 23},
{-13, 65},
{77, 77},
{986, 25, 986}
};
typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset;
@@ -59,19 +65,19 @@ UNORDERED_AUTO_TEST(map_tests)
{
typedef test::list<std::pair<int const, int> > values_type;
values_type v[5];
v[0].push_back(std::pair<int const, int>(1, 1));
v[1].push_back(std::pair<int const, int>(28, 34));
v[1].push_back(std::pair<int const, int>(16, 58));
v[0].push_back(std::pair<int const, int>(1,1));
v[1].push_back(std::pair<int const, int>(28,34));
v[1].push_back(std::pair<int const, int>(16,58));
v[1].push_back(std::pair<int const, int>(-124, 62));
v[2].push_back(std::pair<int const, int>(432, 12));
v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24));
v[2].push_back(std::pair<int const, int>(432,12));
v[2].push_back(std::pair<int const, int>(9,13));
v[2].push_back(std::pair<int const, int>(432,24));
for (int i = 0; i < 5; ++i)
for(int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2)
for(int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
}
+57 -62
View File
@@ -6,23 +6,22 @@
// The code for erasing elements from containers with equivalent keys is very
// hairy with several tricky edge cases - so explicitly test each one.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#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)
#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#endif
struct write_pair_type
@@ -30,47 +29,44 @@ struct write_pair_type
template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second
<< ")";
std::cout<<"("<<x.first<<","<<x.second<<")";
}
} write_pair;
template <class Container> void write_container(Container const& x)
template <class Container>
void write_container(Container const& x)
{
std::for_each(x.begin(), x.end(), write_pair);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
std::cout<<"\n";
}
// 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);
}
int operator()(int x) const { return 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; }
};
typedef boost::unordered_multimap<int, int, collision_hash, std::equal_to<int>,
test::allocator1<std::pair<int const, int> > >
collide_map;
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 boost::unordered_multimap<int, int,
collision_hash, std::equal_to<int>,
test::allocator1<std::pair<int const, int> > > collide_map;
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;
@@ -86,7 +82,7 @@ UNORDERED_AUTO_TEST(empty_range_tests)
UNORDERED_AUTO_TEST(single_item_tests)
{
collide_list init;
init.push_back(collide_value(1, 1));
init.push_back(collide_value(1,1));
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
@@ -103,8 +99,8 @@ UNORDERED_AUTO_TEST(single_item_tests)
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_list init;
init.push_back(collide_value(1, 1));
init.push_back(collide_value(1, 2));
init.push_back(collide_value(1,1));
init.push_back(collide_value(1,2));
{
collide_map x(init.begin(), init.end());
@@ -115,26 +111,26 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_map x(init.begin(), init.end());
int value = test::next(x.begin())->second;
x.erase(x.begin(), test::next(x.begin()));
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
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());
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
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);
}
}
// More automated tests...
template <class Range1, class Range2>
template<class Range1, class Range2>
bool compare(Range1 const& x, Range2 const& y)
{
collide_list a(x.begin(), x.end());
@@ -148,25 +144,24 @@ 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));
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
x.erase(boost::next(x.begin(), start), boost::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
}
template <class Container> void erase_subrange_tests(Container const& x)
template <class Container>
void erase_subrange_tests(Container const& x)
{
for (std::size_t length = 0; length < x.size(); ++length) {
for (std::size_t position = 0; position < x.size() - length;
++position) {
for(std::size_t length = 0; length < x.size(); ++length) {
for(std::size_t position = 0; position < x.size() - length; ++position)
{
Container y(x);
collide_list init(y.begin(), y.end());
if (!general_erase_range_test(y, position, position + length)) {
if(!general_erase_range_test(y, position, position + length)) {
BOOST_ERROR("general_erase_range_test failed.");
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
<< position + length << ")\n";
std::cout<<"Erase: ["<<position<<","<<position + length<<")\n";
write_container(init);
write_container(y);
}
@@ -179,47 +174,47 @@ void x_by_y_erase_range_tests(Container*, int values, int duplicates)
{
Container y;
for (int i = 0; i < values; ++i) {
for (int j = 0; j < duplicates; ++j) {
for(int i = 0; i < values; ++i) {
for(int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j));
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
<< ", Duplicates: " << duplicates << "\n";
std::cout<<"Values: "<<values<<", Duplicates: "<<duplicates<<"\n";
erase_subrange_tests(y);
}
template <class Container>
void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated)
void exhaustive_erase_tests(Container* x, int num_values,
int num_duplicated)
{
for (int i = 0; i < num_values; ++i) {
for (int j = 0; j < num_duplicated; ++j) {
for(int i = 0; i < num_values; ++i) {
for(int j = 0; j < num_duplicated; ++j) {
x_by_y_erase_range_tests(x, i, j);
}
}
}
UNORDERED_AUTO_TEST(exhaustive_collide_tests)
UNORDERED_AUTO_TEST(exhaustive_collide_tests)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
std::cout<<"exhaustive_collide_tests:\n";
collide_map m;
exhaustive_erase_tests((collide_map*)0, 4, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
exhaustive_erase_tests((collide_map*) 0, 4, 4);
std::cout<<"\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
std::cout<<"exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*) 0, 8, 4);
std::cout<<"\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
std::cout<<"exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*) 0, 8, 4);
std::cout<<"\n";
}
RUN_TESTS()
+77 -119
View File
@@ -3,55 +3,51 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#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 <cstdlib>
namespace erase_tests {
#include <iostream>
namespace erase_tests
{
test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
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) {
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
it = v.begin(); it != v.end(); ++it)
{
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n";
std::cerr<<"erase(begin()).\n";
{
test::check_instances check_;
@@ -59,22 +55,23 @@ void erase_tests1(Container*, test::random_generator 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());
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);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n";
std::cerr<<"erase(random position).\n";
{
test::check_instances check_;
@@ -82,38 +79,35 @@ void erase_tests1(Container*, test::random_generator 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;
if (index == 0) {
while(size > 0 && !x.empty())
{
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);
}
next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
else {
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
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));
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
<< x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
std::cerr<<"erase(ranges).\n";
{
test::check_instances check_;
@@ -140,46 +134,7 @@ void erase_tests1(Container*, test::random_generator generator)
test::check_equivalent_keys(x);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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());
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
std::cerr<<"quick_erase(begin()).\n";
{
test::check_instances check_;
@@ -187,21 +142,21 @@ void erase_tests1(Container*, test::random_generator 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());
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);
x.quick_erase(x.begin());
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n";
std::cerr<<"quick_erase(random position).\n";
{
test::check_instances check_;
@@ -209,38 +164,36 @@ void erase_tests1(Container*, test::random_generator 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());
while(size > 0 && !x.empty())
{
using namespace std;
int index = rand() % (int) x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if (index == 0) {
if(index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
else {
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
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));
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
<< x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
std::cerr<<"clear().\n";
{
test::check_instances check_;
@@ -251,25 +204,30 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_TEST(x.begin() == x.end());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
std::cerr<<"\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
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(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(erase_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
}
RUN_TESTS()
-138
View File
@@ -1,138 +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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/test.hpp"
#include <boost/next_prior.hpp>
namespace extract_tests {
test::seed_t initialize_seed(85638);
template <class Container>
void extract_tests1(Container*, test::random_generator generator)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract 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) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
std::size_t new_count = count ? count - 1 : count;
std::size_t new_size = count ? old_size - 1 : old_size;
typename Container::node_type n =
x.extract(test::get_key<Container>(*it));
BOOST_TEST((n ? true : false) == (count ? true : false));
BOOST_TEST(x.size() == new_size);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
if (!new_count) {
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
} else {
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
}
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
{
test::check_instances check_;
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);
typename Container::node_type n = x.extract(x.begin());
BOOST_TEST(n);
--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());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
{
test::check_instances check_;
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()) {
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 = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(pos);
BOOST_TEST(n);
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == boost::next(prev));
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());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
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;
UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)))
}
RUN_TESTS()
+51 -46
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -16,11 +14,13 @@
#include "../helpers/tracker.hpp"
#include "../helpers/helpers.hpp"
namespace find_tests {
namespace find_tests
{
test::seed_t initialize_seed(78937);
template <class X> void find_tests1(X*, test::random_generator generator)
template <class X>
void find_tests1(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
@@ -33,35 +33,35 @@ template <class X> void find_tests1(X*, test::random_generator generator)
test::ordered<X> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
for (BOOST_DEDUCED_TYPENAME test::ordered<X>::const_iterator it1 =
tracker.begin();
it1 != tracker.end(); ++it1) {
for(BOOST_DEDUCED_TYPENAME test::ordered<X>::const_iterator it1 =
tracker.begin(); it1 != tracker.end(); ++it1)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
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_DEDUCED_TYPENAME X::const_iterator
const_pos = x_const.find(key);
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(pos != x.end());
BOOST_TEST(
pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(x.count(key) == tracker.count(key));
test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
test::compare_pairs(x.equal_range(key),
tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*) 0);
test::compare_pairs(x_const.equal_range(key),
tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*) 0);
}
test::random_values<X> v2(500, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it2 =
v2.begin();
it2 != v2.end(); ++it2) {
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it2 =
v2.begin(); it2 != v2.end(); ++it2)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2);
if (tracker.find(test::get_key<X>(key)) == tracker.end()) {
if(tracker.find(test::get_key<X>(key)) == tracker.end())
{
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x_const.find(key) == x_const.end());
BOOST_TEST(x.count(key) == 0);
@@ -77,9 +77,9 @@ template <class X> void find_tests1(X*, test::random_generator generator)
X x;
test::random_values<X> v2(5, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it3 =
v2.begin();
it3 != v2.end(); ++it3) {
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it3 =
v2.begin(); it3 != v2.end(); ++it3)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0);
@@ -92,7 +92,7 @@ template <class X> void find_tests1(X*, test::random_generator generator)
struct compatible_key
{
test::object o_;
compatible_key(test::object const& o) : o_(o) {}
};
@@ -100,8 +100,7 @@ struct compatible_hash
{
test::hash hash_;
std::size_t operator()(compatible_key const& k) const
{
std::size_t operator()(compatible_key const& k) const {
return hash_(k.o_);
}
};
@@ -110,8 +109,7 @@ struct compatible_predicate
{
test::equal_to equal_;
bool operator()(compatible_key const& k1, compatible_key const& k2) const
{
bool operator()(compatible_key const& k1, compatible_key const& k2) const {
return equal_(k1.o_, k2.o_);
}
};
@@ -119,46 +117,53 @@ struct compatible_predicate
template <class X>
void find_compatible_keys_test(X*, test::random_generator 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);
X x(v.begin(), v.end());
compatible_hash h;
compatible_predicate eq;
for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
for(value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
test::random_values<X> v2(20, generator);
for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
for(value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
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(
find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
}
RUN_TESTS()
+16 -18
View File
@@ -3,48 +3,48 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_map_fwd.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
void call_swap(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
swap(x, y);
swap(x,y);
}
template <typename T>
bool call_equals(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
bool call_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
bool call_not_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
return x != y;
}
template <typename T>
void call_swap(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
void call_swap(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
swap(x, y);
swap(x,y);
}
template <typename T>
bool call_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
bool call_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
bool call_not_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
return x != y;
}
@@ -55,8 +55,7 @@ bool call_not_equals(
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST(use_map_fwd_declared_function)
{
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
int_map x, y;
x[1] = 2;
y[2] = 1;
@@ -72,8 +71,7 @@ UNORDERED_AUTO_TEST(use_map_fwd_declared_function)
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function)
{
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function) {
int_multimap x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
+30 -37
View File
@@ -3,61 +3,57 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_set_fwd.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
struct true_type
{
char x[100];
};
struct false_type
{
char x;
};
struct true_type { char x[100]; };
struct false_type { char x; };
false_type is_unordered_set_impl(void*);
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*);
boost::unordered_set<Value, Hash, Pred, Alloc>*);
template <typename T>
void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
template<typename T>
void call_swap(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
swap(x, y);
swap(x,y);
}
template <typename T>
bool call_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
template<typename T>
bool call_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
template<typename T>
bool call_not_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
return x != y;
}
template <typename T>
void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
template<typename T>
void call_swap(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
swap(x, y);
swap(x,y);
}
template <typename T>
bool call_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
template<typename T>
bool call_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
template<typename T>
bool call_not_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
return x != y;
}
@@ -67,23 +63,21 @@ bool call_not_equals(
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition)
{
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0))
== sizeof(true_type));
}
#include <boost/unordered_set.hpp>
UNORDERED_AUTO_TEST(use_fwd_declared_trait)
{
UNORDERED_AUTO_TEST(use_fwd_declared_trait) {
boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*) 0)) == sizeof(false_type));
}
UNORDERED_AUTO_TEST(use_set_fwd_declared_function)
{
UNORDERED_AUTO_TEST(use_set_fwd_declared_function) {
int_set x, y;
x.insert(1);
y.insert(2);
@@ -99,8 +93,7 @@ UNORDERED_AUTO_TEST(use_set_fwd_declared_function)
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function)
{
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function) {
int_multiset x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
+123 -143
View File
@@ -3,169 +3,149 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <utility>
namespace x {
struct D
namespace x
{
boost::unordered_map<D, D> x;
};
struct D { boost::unordered_map<D, D> x; };
}
namespace incomplete_test {
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T> struct allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
map;
typedef boost::unordered_multimap<value, value, hash, equals,
allocator<std::pair<value const, value> > >
multimap;
typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
struct hash
namespace incomplete_test
{
template <typename T> std::size_t operator()(T const&) const { return 0; }
};
// Declare, but don't define some types.
struct equals
{
template <typename T> bool operator()(T const&, T const&) const
struct value;
struct hash;
struct equals;
template <class T> struct allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
struct hash {
template <typename T>
std::size_t operator()(T const&) const { return 0; }
};
struct equals {
template <typename T>
bool operator()(T const&, T const&) const { return true; }
};
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T>
struct allocator : std::allocator<T> {
allocator() {}
template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
allocator<struct4> > x;
};
// Now define the value type.
struct value {};
// Create some instances.
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
// And finally use these
void use_types()
{
return true;
}
};
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
s2.insert(x);
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T> struct allocator : std::allocator<T>
{
allocator() {}
template <typename T2>
allocator(const allocator<T2>& other) : std::allocator<T>(other)
{
c1.x.insert(std::make_pair(c1, c1));
c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3);
c4.x.insert(c4);
}
template <typename T2>
allocator(const std::allocator<T2>& other) : std::allocator<T>(other)
{
}
};
// And finally define the operators required for comparing elements.
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
struct struct1
{
boost::unordered_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > >
x;
};
struct struct2
{
boost::unordered_multimap<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > >
x;
};
struct struct3
{
boost::unordered_set<struct3, hash, equals, allocator<struct3> > x;
};
struct struct4
{
boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
};
// Now define the value type.
struct value
{
};
// Create some instances.
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
// And finally use these
void use_types()
{
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
s2.insert(x);
c1.x.insert(std::make_pair(c1, c1));
c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3);
c4.x.insert(c4);
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
// And finally define the operators required for comparing elements.
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
int main()
{
int main() {
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
-128
View File
@@ -1,128 +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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../helpers/invariants.hpp"
#include <map>
#include <set>
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()
-34
View File
@@ -1,34 +0,0 @@
// Copyright 2017 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_map.hpp>
#include <boost/unordered_set.hpp>
int main()
{
#if defined(UNORDERED_TEST_MAP)
typedef boost::unordered_map<int, int> container;
container x;
x.emplace(1, 1);
#elif defined(UNORDERED_TEST_MULTIMAP)
typedef boost::unordered_multimap<int, int> container;
container x;
#elif defined(UNORDERED_TEST_SET)
typedef boost::unordered_set<int> container;
container x;
x.emplace(1);
#elif defined(UNORDERED_TEST_MULTISET)
typedef boost::unordered_multiset<int> container;
container x;
x.emplace(1);
#else
#define UNORDERED_ERROR
#endif
#if !defined(UNORDERED_ERROR)
container::node_type n = x.extract(x.begin());
x.insert(n);
#endif
}
+40 -72
View File
@@ -3,34 +3,32 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
namespace insert_stable {
struct member
#include <iostream>
namespace insert_stable
{
int tag1_;
int tag2_;
member() : tag1_(0), tag2_(0) {}
member(int t1, int t2) : tag1_(t1), tag2_(t2) {}
friend bool operator==(member const& x, member const& y)
{
return x.tag1_ == y.tag1_;
}
friend bool operator!=(member const& x, member const& y)
{
return x.tag1_ != y.tag1_;
}
};
struct member {
int tag1_;
int tag2_;
member() : tag1_(0), tag2_(0) {}
member(int t1, int t2) : tag1_(t1), tag2_(t2) {}
friend bool operator==(member const& x, member const& y) {
return x.tag1_ == y.tag1_;
}
friend bool operator!=(member const& x, member const& y) {
return x.tag1_ != y.tag1_;
}
};
}
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
@@ -39,79 +37,49 @@ namespace boost
namespace insert_stable
#endif
{
std::size_t hash_value(insert_stable::member const& x)
{
return static_cast<std::size_t>(x.tag1_);
}
std::size_t hash_value(insert_stable::member const& x) {
return static_cast<std::size_t>(x.tag1_);
}
}
// This is no longer supported, as there's no longer an efficient way to get to
// the end of a group of equivalent nodes.
#if 0
UNORDERED_AUTO_TEST(stable_insert_test1)
{
UNORDERED_AUTO_TEST(stable_insert_test1) {
boost::unordered_multiset<insert_stable::member> x;
x.insert(insert_stable::member(1, 1));
x.insert(insert_stable::member(1, 2));
x.insert(insert_stable::member(1, 3));
BOOST_TEST(x.count(insert_stable::member(1, 4)) == 3);
x.insert(insert_stable::member(1,1));
x.insert(insert_stable::member(1,2));
x.insert(insert_stable::member(1,3));
boost::unordered_multiset<insert_stable::member>::const_iterator
it = x.begin(),
end = x.end();
it = x.begin(), end = x.end();
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->tag2_ == 1);
++it;
}
if(it != end) { BOOST_TEST(it->tag2_ == 1); ++it; }
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->tag2_ == 2);
++it;
}
if(it != end) { BOOST_TEST(it->tag2_ == 2); ++it; }
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->tag2_ == 3);
++it;
}
if(it != end) { BOOST_TEST(it->tag2_ == 3); ++it; }
BOOST_TEST(it == end);
}
UNORDERED_AUTO_TEST(stable_insert_test2)
{
UNORDERED_AUTO_TEST(stable_insert_test2) {
boost::unordered_multimap<insert_stable::member, int> x;
typedef boost::unordered_multimap<insert_stable::member,
int>::const_iterator iterator;
typedef
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();
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->first.tag2_ == 1 && it->second == 1);
++it;
}
if(it != end) { BOOST_TEST(it->first.tag2_ == 1 && it->second == 1); ++it; }
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->first.tag2_ == 2 && it->second == 2);
++it;
}
if(it != end) { BOOST_TEST(it->first.tag2_ == 2 && it->second == 2); ++it; }
BOOST_TEST(it != end);
if (it != end) {
BOOST_TEST(it->first.tag2_ == 3 && it->second == 3);
++it;
}
if(it != end) { BOOST_TEST(it->first.tag2_ == 3 && it->second == 3); ++it; }
BOOST_TEST(it == end);
}
#endif
RUN_TESTS()
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -3,15 +3,15 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&,
boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
void foo(boost::unordered_set<int>&,
boost::unordered_map<int, int>&,
boost::unordered_multiset<int>&,
boost::unordered_multimap<int, int>&);
int main()
{
@@ -21,6 +21,6 @@ int main()
boost::unordered_multimap<int, int> x4;
foo(x1, x2, x3, x4);
return 0;
}
+10 -11
View File
@@ -3,24 +3,23 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4)
void foo(boost::unordered_set<int>& x1,
boost::unordered_map<int, int>& x2,
boost::unordered_multiset<int>& x3,
boost::unordered_multimap<int, int>& x4)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
{
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
struct dummy {
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
#endif
x1.insert(1);
+24 -24
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <boost/limits.hpp>
@@ -16,14 +14,16 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace load_factor_tests {
namespace load_factor_tests
{
test::seed_t initialize_seed(783656);
template <class X> void set_load_factor_tests(X*)
template <class X>
void set_load_factor_tests(X*)
{
X x;
@@ -32,10 +32,8 @@ template <class X> void set_load_factor_tests(X*)
// A valid implementation could fail these tests, but I think they're
// reasonable.
x.max_load_factor(2.0);
BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5);
BOOST_TEST(x.max_load_factor() == 0.5);
x.max_load_factor(2.0); BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5); BOOST_TEST(x.max_load_factor() == 0.5);
}
template <class X>
@@ -47,15 +45,13 @@ void insert_test(X*, float mlf, test::random_generator generator)
test::random_values<X> values(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = values.begin(),
end = values.end();
it != end; ++it) {
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = values.begin(), end = values.end(); it != end; ++it)
{
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
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);
}
}
@@ -67,10 +63,12 @@ void load_factor_insert_tests(X* ptr, test::random_generator generator)
insert_test(ptr, 0.1f, generator);
insert_test(ptr, 100.0f, generator);
insert_test(ptr, (std::numeric_limits<float>::min)(), generator);
insert_test(ptr, (std::numeric_limits<float>::min)(),
generator);
if (std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
if(std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity(),
generator);
}
boost::unordered_set<int>* int_set_ptr;
@@ -80,19 +78,21 @@ 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)))
((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)))
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
}
RUN_TESTS()
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable:4127) // conditional expression is constant
#endif
-341
View File
@@ -1,341 +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/postfix.hpp"
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/count.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/test.hpp"
#include <boost/next_prior.hpp>
namespace merge_tests {
UNORDERED_AUTO_TEST(merge_set)
{
boost::unordered_set<int> x;
boost::unordered_set<int> y;
x.merge(y);
BOOST_TEST(x.empty());
BOOST_TEST(y.empty());
x.insert(10);
x.merge(y);
BOOST_TEST(x.size() == 1);
BOOST_TEST(x.count(10) == 1);
BOOST_TEST(y.empty());
y.merge(x);
BOOST_TEST(x.empty());
BOOST_TEST(y.size() == 1);
BOOST_TEST(y.count(10) == 1);
x.insert(10);
x.insert(50);
y.insert(70);
y.insert(80);
x.merge(y);
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST_EQ(y.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
BOOST_TEST_EQ(x.count(50), 1u);
BOOST_TEST_EQ(x.count(70), 1u);
BOOST_TEST_EQ(x.count(80), 1u);
BOOST_TEST_EQ(y.count(10), 1u);
BOOST_TEST_EQ(y.count(50), 0u);
BOOST_TEST_EQ(y.count(70), 0u);
BOOST_TEST_EQ(y.count(80), 0u);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_AUTO_TEST(merge_multiset)
{
boost::unordered_multiset<int> x;
boost::unordered_multiset<int> y;
x.merge(y);
BOOST_TEST(x.empty());
BOOST_TEST(y.empty());
x.insert(10);
x.merge(y);
BOOST_TEST(x.size() == 1);
BOOST_TEST(x.count(10) == 1);
BOOST_TEST(y.empty());
y.merge(x);
BOOST_TEST(x.empty());
BOOST_TEST(y.size() == 1);
BOOST_TEST(y.count(10) == 1);
x.insert(10);
x.insert(50);
y.insert(70);
y.insert(80);
x.merge(y);
BOOST_TEST_EQ(x.size(), 5u);
BOOST_TEST_EQ(y.size(), 0u);
BOOST_TEST_EQ(x.count(10), 2u);
BOOST_TEST_EQ(x.count(50), 1u);
BOOST_TEST_EQ(x.count(70), 1u);
BOOST_TEST_EQ(x.count(80), 1u);
BOOST_TEST_EQ(y.count(10), 0u);
BOOST_TEST_EQ(y.count(50), 0u);
BOOST_TEST_EQ(y.count(70), 0u);
BOOST_TEST_EQ(y.count(80), 0u);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_AUTO_TEST(merge_set_and_multiset)
{
boost::unordered_set<int> x;
boost::unordered_multiset<int> y;
x.merge(y);
BOOST_TEST(x.empty());
BOOST_TEST(y.empty());
x.insert(10);
x.merge(y);
BOOST_TEST(x.size() == 1);
BOOST_TEST(x.count(10) == 1);
BOOST_TEST(y.empty());
y.merge(x);
BOOST_TEST(x.empty());
BOOST_TEST(y.size() == 1);
BOOST_TEST(y.count(10) == 1);
x.insert(10);
x.insert(50);
y.insert(70);
y.insert(80);
x.merge(y);
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST_EQ(y.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
BOOST_TEST_EQ(x.count(50), 1u);
BOOST_TEST_EQ(x.count(70), 1u);
BOOST_TEST_EQ(x.count(80), 1u);
BOOST_TEST_EQ(y.count(10), 1u);
BOOST_TEST_EQ(y.count(50), 0u);
BOOST_TEST_EQ(y.count(70), 0u);
BOOST_TEST_EQ(y.count(80), 0u);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <class X1, class X2>
void merge_empty_test(X1*, X2*, test::random_generator generator)
{
test::check_instances check_;
test::random_values<X1> v(1000, generator);
X1 x1(v.begin(), v.end());
X2 x2;
x1.merge(x2);
test::check_container(x1, v);
BOOST_TEST(x2.empty());
test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2);
}
template <class X>
void merge_into_empty_test(X*, test::random_generator generator)
{
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x1;
X x2(v.begin(), v.end());
x1.merge(x2);
test::check_container(x1, v);
BOOST_TEST(x2.empty());
test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2);
}
template <class X1, class X2>
void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
test::random_generator generator)
{
test::check_instances check_;
test::random_values<X1> v1(1000, generator);
test::random_values<X2> v2(1000, generator);
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
test::equal_to(hash_equal1));
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
test::equal_to(hash_equal2));
test::ordered<X1> tracker1 = test::create_ordered(x1);
test::ordered<X2> tracker2 = test::create_ordered(x2);
tracker1.insert(v1.begin(), v1.end());
for (typename X2::iterator it = x2.begin(); it != x2.end(); ++it) {
if (!tracker1.insert(*it).second) {
tracker2.insert(*it);
}
}
x1.merge(x2);
tracker1.compare(x1);
tracker2.compare(x2);
test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2);
}
template <class X1, class X2>
void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
test::random_generator generator)
{
test::check_instances check_;
test::random_values<X1> v1(1000, generator);
test::random_values<X2> v2(1000, generator);
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
test::equal_to(hash_equal1));
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
test::equal_to(hash_equal2));
x1.merge(x2);
test::ordered<X1> tracker1 = test::create_ordered(x1);
test::ordered<X2> tracker2 = test::create_ordered(x2);
tracker1.insert(v1.begin(), v1.end());
tracker2.insert(v2.begin(), v2.end());
tracker1.insert(tracker2.begin(), tracker2.end());
tracker2.clear();
tracker1.compare(x1);
tracker2.compare(x2);
test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2);
}
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_multiset_std_alloc;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map;
boost::unordered_multimap<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
// clang-format off
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_map_std_alloc)(test_multimap_std_alloc))
((test_map_std_alloc)(test_multimap_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_set)(test_multiset))
((test_set)(test_multiset))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_map)(test_multimap))
((test_map)(test_multimap))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_map_std_alloc)(test_multimap_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_set)(test_multiset))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_map)(test_multimap))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_set_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_map_std_alloc))
((test_map_std_alloc)(test_multimap_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_set))
((test_set)(test_multiset))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_map))
((test_map)(test_multimap))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_equiv_keys_test,
((test_multiset_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_equiv_keys_test,
((test_multimap_std_alloc))
((test_map_std_alloc)(test_multimap_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_equiv_keys_test,
((test_multiset))
((test_set)(test_multiset))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_equiv_keys_test,
((test_multimap))
((test_map)(test_multimap))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
}
RUN_TESTS()
+35 -33
View File
@@ -3,58 +3,60 @@
// 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 "../objects/test.hpp"
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered/detail/implementation.hpp>
#include <boost/static_assert.hpp>
#include "../objects/test.hpp"
template <class Tp> struct SimpleAllocator
{
template <class Tp>
struct SimpleAllocator
{
typedef Tp value_type;
SimpleAllocator() {}
SimpleAllocator()
{
}
template <class T> SimpleAllocator(const SimpleAllocator<T>&) {}
template <class T> SimpleAllocator(const SimpleAllocator<T>& other)
{
}
Tp* allocate(std::size_t n)
Tp *allocate(std::size_t n)
{
return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
}
void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); }
void deallocate(Tp* p, std::size_t)
{
::operator delete((void*) p);
}
};
template <typename T> void test_simple_allocator()
template <typename T>
void test_simple_allocator()
{
test::check_instances check_;
typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> >
traits;
typedef boost::unordered::detail::allocator_traits<
SimpleAllocator<T> > traits;
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type,
SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::const_pointer, T const*>::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void*
// >::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer,
// void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T* >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_pointer, T const*>::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void* >::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type,
std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
@@ -67,18 +69,18 @@ template <typename T> void test_simple_allocator()
SimpleAllocator<T> a;
T* ptr1 = traits::allocate(a, 1);
// T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
//T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
traits::construct(a, ptr1, T(10));
// traits::construct(a, ptr2, T(30), ptr1);
//traits::construct(a, ptr2, T(30), ptr1);
BOOST_TEST(*ptr1 == T(10));
// BOOST_TEST(*ptr2 == T(30));
//BOOST_TEST(*ptr2 == T(30));
traits::destroy(a, ptr1);
// traits::destroy(a, ptr2);
//traits::destroy(a, ptr2);
// traits::deallocate(a, ptr2, 1);
//traits::deallocate(a, ptr2, 1);
traits::deallocate(a, ptr1, 1);
traits::max_size(a);
+347 -317
View File
@@ -3,12 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -19,357 +17,389 @@
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace move_tests {
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
namespace move_tests
{
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template <class T> T empty(T*) { return T(); }
template <class T>
T create(test::random_values<T> const& v, test::object_count& count)
{
T x(v.begin(), v.end());
count = test::global_object_count;
return x;
}
template <class T>
T create(test::random_values<T> const& v, test::object_count& count,
BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq,
BOOST_DEDUCED_TYPENAME T::allocator_type al, float mlf)
{
T x(0, hf, eq, al);
x.max_load_factor(mlf);
x.insert(v.begin(), v.end());
count = test::global_object_count;
return x;
}
template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
{
test::check_instances check_;
T y(empty(ptr));
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y);
template<class T>
T empty(T*) {
return T();
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
{
{
test::check_instances check_;
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
template <class T>
void move_construct_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
test::object_count count;
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y);
template<class T>
T create(test::random_values<T> const& v,
test::object_count& count) {
T x(v.begin(), v.end());
count = test::global_object_count;
return x;
}
{
test::check_instances check_;
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_TEST(count != test::global_object_count);
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
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)
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()));
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()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
}
template <class T>
void move_assign_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::random_values<T> v(500, generator);
test::object_count count;
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
template<class T>
T create(test::random_values<T> const& v,
test::object_count& count,
BOOST_DEDUCED_TYPENAME T::hasher hf,
BOOST_DEDUCED_TYPENAME T::key_equal eq,
BOOST_DEDUCED_TYPENAME T::allocator_type al,
float mlf) {
T x(0, hf, eq, al);
x.max_load_factor(mlf);
x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
count = test::global_object_count;
return x;
}
template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator)
{
test::check_instances check_;
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator);
{
test::check_instances check_;
T x(0, hf, eq, al2);
x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x);
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count1.instances == test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
test::global_object_count.constructions);
T y(empty(ptr));
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y);
}
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
{
test::check_instances check_;
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
{
{
test::check_instances check_;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
template <class T>
void move_construct_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
test::object_count count;
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_TEST(count != test::global_object_count);
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
#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()));
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()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
}
template <class T>
void move_assign_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::random_values<T> v(500, generator);
test::object_count count;
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{
test::check_instances check_;
test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator);
T x(0, hf, eq, al2);
x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x);
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count1.instances ==
test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
test::global_object_count.constructions);
}
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
}
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_map_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multimap_prop_move;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multimap_no_prop_move;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(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)))
UNORDERED_TEST(move_assign_tests1,
((test_map_std_alloc)(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)))
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)))
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)))
UNORDERED_TEST(move_construct_tests1, (
(test_map_std_alloc)
(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))
)
UNORDERED_TEST(move_assign_tests1, (
(test_map_std_alloc)
(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))
)
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))
)
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))
)
}
RUN_TESTS()
-436
View File
@@ -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/postfix.hpp"
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/helpers.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/test.hpp"
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <set>
#include <string>
UNORDERED_AUTO_TEST(example1)
{
typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type;
boost::unordered_map<int, std::string> src;
src.emplace(1, "one");
src.emplace(2, "two");
src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst;
dst.emplace(3, "three");
dst.insert(src.extract(src.find(1)));
dst.insert(src.extract(2));
insert_return_type r = dst.insert(src.extract(3));
BOOST_TEST(src.empty());
BOOST_TEST(dst.size() == 3);
BOOST_TEST(dst[1] == "one");
BOOST_TEST(dst[2] == "two");
BOOST_TEST(dst[3] == "three");
BOOST_TEST(!r.inserted);
BOOST_TEST(r.position == dst.find(3));
BOOST_TEST(r.node.mapped() == "buckle my shoe");
}
UNORDERED_AUTO_TEST(example2)
{
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
// dst.merge(src);
// Merge src into dst.
// src == {5}
// dst == {1, 2, 3, 4, 5}
}
UNORDERED_AUTO_TEST(example3)
{
typedef boost::unordered_set<int>::iterator iterator;
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
for (iterator i = src.begin(); i != src.end();) {
std::pair<iterator, iterator> p = dst.equal_range(*i);
if (p.first == p.second)
dst.insert(p.first, src.extract(i++));
else
++i;
}
BOOST_TEST(src.size() == 1);
BOOST_TEST(*src.begin() == 5);
std::set<int> dst2(dst.begin(), dst.end());
std::set<int>::iterator it = dst2.begin();
BOOST_TEST(*it++ == 1);
BOOST_TEST(*it++ == 2);
BOOST_TEST(*it++ == 3);
BOOST_TEST(*it++ == 4);
BOOST_TEST(*it++ == 5);
BOOST_TEST(it == dst2.end());
}
UNORDERED_AUTO_TEST(failed_insertion_with_hint)
{
{
boost::unordered_set<int> src;
boost::unordered_set<int> dst;
src.emplace(10);
src.emplace(20);
dst.emplace(10);
dst.emplace(20);
boost::unordered_set<int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
{
boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst;
src.emplace(10, 30);
src.emplace(20, 5);
dst.emplace(10, 20);
dst.emplace(20, 2);
boost::unordered_map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
}
template <typename NodeHandle>
bool node_handle_compare(NodeHandle const& nh,
BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x)
{
return x == nh.value();
}
template <typename NodeHandle>
bool node_handle_compare(
NodeHandle const& nh,
std::pair<BOOST_DEDUCED_TYPENAME NodeHandle::key_type const,
BOOST_DEDUCED_TYPENAME NodeHandle::mapped_type> const& x)
{
return x.first == nh.key() && x.second == nh.mapped();
}
template <typename Container> void node_handle_tests_impl(Container& c)
{
typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type;
BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin();
node_type n1;
BOOST_TEST(!n1);
BOOST_TEST(n1.empty());
node_type n2 = c.extract(c.begin());
BOOST_TEST(n2);
BOOST_TEST(!n2.empty());
node_handle_compare(n2, value);
node_type n3 = boost::move(n2);
BOOST_TEST(n3);
BOOST_TEST(!n2);
node_handle_compare(n3, value);
// TODO: Check that n2 doesn't have an allocator?
// Maybe by swapping and observing that the allocator is
// swapped rather than moved?
n1 = boost::move(n3);
BOOST_TEST(n1);
BOOST_TEST(!n3);
node_handle_compare(n1, value);
// Self move-assignment empties the node_handle.
n1 = boost::move(n1);
BOOST_TEST(!n1);
n3 = boost::move(n3);
BOOST_TEST(!n3);
BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin();
n1 = c.extract(c.begin());
BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin();
n2 = c.extract(c.begin());
n3 = node_type();
node_handle_compare(n1, value1);
node_handle_compare(n2, value2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(n2);
node_handle_compare(n1, value2);
node_handle_compare(n2, value1);
BOOST_TEST(n1);
BOOST_TEST(!n3);
n1.swap(n3);
BOOST_TEST(!n1);
BOOST_TEST(n3);
node_handle_compare(n3, value2);
BOOST_TEST(!n1);
BOOST_TEST(n2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(!n2);
node_handle_compare(n1, value1);
node_type n4;
BOOST_TEST(!n2);
BOOST_TEST(!n4);
n2.swap(n4);
BOOST_TEST(!n2);
BOOST_TEST(!n4);
}
UNORDERED_AUTO_TEST(node_handle_tests)
{
boost::unordered_set<int> x1;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
node_handle_tests_impl(x1);
boost::unordered_map<int, std::string> x2;
x2.emplace(10, "ten");
x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty");
node_handle_tests_impl(x2);
}
template <typename Container1, typename Container2>
void insert_node_handle_unique(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2;
insert_return_type1 r1 = c1.insert(node_type());
insert_return_type2 r2 = c2.insert(node_type());
BOOST_TEST(!r1.inserted);
BOOST_TEST(!r1.node);
BOOST_TEST(r1.position == c1.end());
BOOST_TEST(!r2.inserted);
BOOST_TEST(!r2.node);
BOOST_TEST(r2.position == c2.end());
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
if (!count) {
BOOST_TEST(r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST(!r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(test::get_key<Container2>(*r.position) ==
test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
}
}
template <typename Container1, typename Container2>
void insert_node_handle_unique2(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
// typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
// insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2;
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r =
c2.insert(c1.extract(test::get_key<Container1>(v)));
if (r.inserted) {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(test::get_key<Container2>(*r.position) ==
test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
}
}
template <typename Container1, typename Container2>
void insert_node_handle_equiv(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1;
typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2;
iterator1 r1 = c1.insert(node_type());
iterator2 r2 = c2.insert(node_type());
BOOST_TEST(r1 == c1.end());
BOOST_TEST(r2 == c2.end());
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
iterator2 r = c2.insert(c1.extract(c1.begin()));
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r != c2.end());
BOOST_TEST(boost::addressof(*r) == v_ptr);
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests)
{
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
UNORDERED_AUTO_TEST(insert_node_handle_equiv_tests)
{
{
boost::unordered_multimap<int, int, hash_thing> x1;
boost::unordered_multimap<int, int> x2;
x1.emplace(67, 50);
x1.emplace(67, 100);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_equiv(x1, x2);
BOOST_TEST(x2.size() == 6);
}
}
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests2)
{
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
RUN_TESTS()
-171
View File
@@ -1,171 +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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#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) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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()
+69 -52
View File
@@ -3,12 +3,10 @@
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../helpers/random_values.hpp"
@@ -16,19 +14,21 @@
#include "../helpers/metafunctions.hpp"
#include "../objects/test.hpp"
namespace rehash_tests {
namespace rehash_tests
{
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()) >=
static_cast<double>(x.size()) / x.max_load_factor() &&
x.bucket_count() >= n;
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*)
template <class X>
void rehash_empty_test1(X*)
{
X x;
@@ -42,7 +42,8 @@ template <class X> void rehash_empty_test1(X*)
BOOST_TEST(postcondition(x, 10000000));
}
template <class X> void rehash_empty_test2(X*, test::random_generator generator)
template <class X>
void rehash_empty_test2(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -57,13 +58,14 @@ template <class X> 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)
template <class X>
void rehash_empty_test3(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -80,33 +82,31 @@ template <class X> 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)
template <class X>
void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x(v.begin(), v.end());
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.max_load_factor(0.25);
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.max_load_factor(50.0);
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.rehash(1000);
BOOST_TEST(postcondition(x, 1000));
x.rehash(1000); BOOST_TEST(postcondition(x, 1000));
tracker.compare(x);
}
template <class X> void reserve_empty_test1(X*)
template <class X>
void reserve_empty_test1(X*)
{
X x;
@@ -119,7 +119,8 @@ template <class X> void reserve_empty_test1(X*)
BOOST_TEST(x.bucket_count() >= 10000000);
}
template <class X> void reserve_empty_test2(X*)
template <class X>
void reserve_empty_test2(X*)
{
X x;
x.max_load_factor(0.25);
@@ -133,20 +134,24 @@ template <class X> void reserve_empty_test2(X*)
BOOST_TEST(x.bucket_count() >= 40000000);
}
template <class X> void reserve_test1(X*, test::random_generator generator)
template <class X>
void reserve_test1(X*, test::random_generator 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 random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(
random_mlf
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
// 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(test::has_unique_keys<X>::value ? i : v.size());
// Insert an element before the range insert, otherwise there are
@@ -164,26 +169,28 @@ template <class X> void reserve_test1(X*, test::random_generator generator)
}
}
template <class X> void reserve_test2(X*, test::random_generator generator)
template <class X>
void reserve_test2(X*, test::random_generator 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 random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(
random_mlf
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
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());
std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) {
it != v.end(); ++it)
{
x.insert(*it);
}
@@ -194,37 +201,47 @@ template <class X> 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,
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,
boost::unordered_map<test::movable, test::movable,
test::hash, test::equal_to,
test::allocator2<test::movable> >* test_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)(test_multiset_ptr)(test_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)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
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)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
((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)(test_multiset_ptr)(test_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)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
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)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
}
RUN_TESTS()

Some files were not shown because too many files have changed in this diff Show More