forked from boostorg/unordered
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1c1e96476 |
@@ -1 +0,0 @@
|
||||
/doc/html/
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
# Copyright (C) 2016 Daniel James.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Use Trusty to get a reasonably recent version of Boost.
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
language: c++
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libboost-tools-dev
|
||||
- libxml2-utils
|
||||
- g++-multilib
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-std11
|
||||
#- compiler: gcc
|
||||
# env: BJAM_TOOLSET=gcc-m32
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-std11m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-std11
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang-std11m32
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-interopable
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-interopable
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- touch Jamroot.jam
|
||||
- cd $HOME
|
||||
- |
|
||||
echo "using gcc : : g++-4.8 -Werror --std=c++03 -fsanitize=address ;" > ~/user-config.jam
|
||||
echo "using gcc : std11 : g++-4.8 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : m32 : g++-4.8 -m32 -Werror -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : std11m32 : g++-4.8 -m32 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : : clang++ -Werror --std=c++03 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : std11 : clang++ -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
# sanitized=address not available for 32-bit clang on travis.
|
||||
echo "using clang : m32 : clang++ -m32 -Werror --std=c++03 ;" >> ~/user-config.jam
|
||||
echo "using clang : std11m32 : clang++ -m32 -Werror --std=c++11 ;" >> ~/user-config.jam
|
||||
echo "using gcc : interopable : g++-4.8 -Werror --std=c++03 -fsanitize=address -DBOOST_UNORDERED_INTEROPERABLE_NODES=1 ;" >> ~/user-config.jam
|
||||
echo "using clang : interopable : clang++ -Werror --std=c++11 -fsanitize=address -DBOOST_UNORDERED_INTEROPERABLE_NODES=1 ;" >> ~/user-config.jam
|
||||
- cat ~/user-config.jam
|
||||
- wget -O boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2
|
||||
- tar -xjf boost.tar.bz2
|
||||
- mv boost_1_63_0 boost
|
||||
- rm -r boost/boost/unordered
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- bjam ${BJAM_TOOLSET} include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
|
||||
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
|
||||
@@ -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 ]
|
||||
@@ -57,12 +57,3 @@ boostbook standalone : unordered :
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: unordered
|
||||
:
|
||||
:
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease ;
|
||||
explicit boostrelease ;
|
||||
|
||||
+1
-73
@@ -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
|
||||
@@ -239,77 +239,5 @@ C++11 support has resulted in some breaking changes:
|
||||
|
||||
* 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 transfering 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.
|
||||
|
||||
[endsect]
|
||||
|
||||
+2
-2
@@ -54,14 +54,14 @@ order to work with non-C++11 compilers and libraries.
|
||||
class Key, class Mapped,
|
||||
class Hash = ``[classref boost::hash]``<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
|
||||
class Alloc = std::allocator<Key> >
|
||||
class ``[classref boost::unordered_map unordered_map]``;
|
||||
|
||||
template<
|
||||
class Key, class Mapped,
|
||||
class Hash = ``[classref boost::hash]``<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
|
||||
class Alloc = std::allocator<Key> >
|
||||
class ``[classref boost::unordered_multimap unordered_multimap]``;
|
||||
}
|
||||
|
||||
|
||||
+8
-13
@@ -3,7 +3,7 @@
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[def __wang__
|
||||
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
Thomas Wang's article on integer hash functions]]
|
||||
|
||||
[section:rationale Implementation Rationale]
|
||||
@@ -85,8 +85,7 @@ of 2.
|
||||
|
||||
Using a prime number of buckets, and choosing a bucket by using the modulus
|
||||
of the hash function's result will usually give a good result. The downside
|
||||
is that the required modulus operation is fairly expensive. This is what the
|
||||
containers do in most cases.
|
||||
is that the required modulus operation is fairly expensive.
|
||||
|
||||
Using a power of 2 allows for much quicker selection of the bucket
|
||||
to use, but at the expense of loosing the upper bits of the hash value.
|
||||
@@ -96,16 +95,12 @@ functions this can't be relied on.
|
||||
|
||||
To avoid this a transformation could be applied to the hash function, for an
|
||||
example see __wang__. Unfortunately, a transformation like Wang's requires
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough
|
||||
to use as a default. It can applicable in certain cases so the containers
|
||||
have a policy based implementation that can use this alternative technique.
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough.
|
||||
This leaves more expensive methods, such as Knuth's Multiplicative Method
|
||||
(mentioned in Wang's article). These don't tend to work as well as taking the
|
||||
modulus of a prime, and the extra computation required might negate
|
||||
efficiency advantage of power of 2 hash tables.
|
||||
|
||||
Currently this is only done on 64 bit architecures, where prime number
|
||||
modulus can be expensive. Although this varies depending on the architecture,
|
||||
so I probably should revisit it.
|
||||
|
||||
I'm also thinking of introducing a mechanism whereby a hash function can
|
||||
indicate that it's safe to be used directly with power of 2 buckets, in
|
||||
which case a faster plain power of 2 implementation can be used.
|
||||
So, this implementation uses a prime number for the hash table size.
|
||||
|
||||
[endsect]
|
||||
|
||||
+2
-580
@@ -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&</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; ?> &&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>Allocator const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para>This is implemented using Boost.Move.</para>
|
||||
</notes>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is move insertable.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="il">
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
<default><emphasis>implementation-defined</emphasis></default>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
<default>hasher()</default>
|
||||
</parameter>
|
||||
<parameter name="eq">
|
||||
<paramtype>key_equal const&</paramtype>
|
||||
<default>key_equal()</default>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
<default>allocator_type()</default>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
<code>eq</code> as the key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0
|
||||
and inserts the elements from <code>il</code> into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
|
||||
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<postconditions>
|
||||
<code><methodname>size</methodname>() == 0</code>
|
||||
</postconditions>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
the default hash function and key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<postconditions>
|
||||
<code><methodname>size</methodname>() == 0</code>
|
||||
</postconditions>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
the default key equality predicate,
|
||||
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<template>
|
||||
<template-type-parameter name="InputIterator">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="f">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="l">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>a</code> as the allocator, with the
|
||||
default hash function and key equality predicate
|
||||
and a maximum load factor of 1.0
|
||||
and inserts the elements from [f, l) into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<constructor>
|
||||
<template>
|
||||
<template-type-parameter name="InputIterator">
|
||||
</template-type-parameter>
|
||||
</template>
|
||||
<parameter name="f">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="l">
|
||||
<paramtype>InputIterator</paramtype>
|
||||
</parameter>
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<parameter name="hf">
|
||||
<paramtype>hasher const&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="a">
|
||||
<paramtype>allocator_type const&</paramtype>
|
||||
</parameter>
|
||||
<description>
|
||||
<para>Constructs an empty container with at least <code>n</code> buckets,
|
||||
using <code>hf</code> as the hash function,
|
||||
<code>a</code> as the allocator, with the
|
||||
default key equality predicate
|
||||
and a maximum load factor of 1.0
|
||||
and inserts the elements from [f, l) into it.
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</constructor>
|
||||
<destructor>
|
||||
<notes>
|
||||
<para>The destructor is applied to every element, and all memory is deallocated</para>
|
||||
@@ -555,21 +358,6 @@ EOL;
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<type><?php echo $name; ?>&</type>
|
||||
<description>
|
||||
<para>Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed.</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para>
|
||||
<code>value_type</code> is <code>CopyInsertable</code> into the container and
|
||||
<code>CopyAssignable</code>.
|
||||
</para>
|
||||
</requires>
|
||||
</method>
|
||||
<method name="get_allocator" cv="const">
|
||||
<type>allocator_type</type>
|
||||
</method>
|
||||
@@ -851,54 +639,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<value_type></paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Inserts a range of elements into the container.
|
||||
<?php if (!$equivalent_keys): ?>
|
||||
Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
|
||||
<?php endif; ?>
|
||||
</para>
|
||||
</description>
|
||||
<requires>
|
||||
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
|
||||
<code>X</code> from <code>*first</code>.</para>
|
||||
</requires>
|
||||
<throws>
|
||||
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
|
||||
<para>Pointers and references to elements are never invalidated.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
<parameter name="il">
|
||||
<paramtype>initializer_list<value_type></paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Inserts a range of elements into the container. 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 +654,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&</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&&</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&&</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 +785,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; ?><Key, Mapped, H2, P2, Alloc>&</paramtype>
|
||||
<?php else: ?>
|
||||
<paramtype><?php echo $name; ?><Value, H2, P2, Alloc>&</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; ?><Key, Mapped, H2, P2, Alloc>&&</paramtype>
|
||||
<?php else: ?>
|
||||
<paramtype><?php echo $name; ?><Value, H2, P2, Alloc>&&</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; ?><Key, Mapped, H2, P2, Alloc>&</paramtype>
|
||||
<?php else: ?>
|
||||
<paramtype><?php echo $node_partner; ?><Value, H2, P2, Alloc>&</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; ?><Key, Mapped, H2, P2, Alloc>&&</paramtype>
|
||||
<?php else: ?>
|
||||
<paramtype><?php echo $node_partner; ?><Value, H2, P2, Alloc>&&</paramtype>
|
||||
<?php endif; ?>
|
||||
</parameter>
|
||||
</method>
|
||||
*/ ?>
|
||||
</method-group>
|
||||
<method-group name="observers">
|
||||
<method name="hash_function" cv="const">
|
||||
@@ -1654,122 +1194,6 @@ EOL;
|
||||
<?php
|
||||
}
|
||||
|
||||
function echo_node_handle_docs($map)
|
||||
{
|
||||
$type = $map ? 'map' : 'set';
|
||||
$name = 'node_handle_'.$type;
|
||||
$full_type = "{$name}<ImplementationDefined>";
|
||||
?>
|
||||
<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; ?> &&</paramtype>
|
||||
</parameter>
|
||||
</constructor>
|
||||
<method name="operator=">
|
||||
<parameter>
|
||||
<paramtype><?php echo $name; ?>&&</paramtype>
|
||||
</parameter>
|
||||
<type><?php echo $name; ?>&</type>
|
||||
</method>
|
||||
<?php if ($map): ?>
|
||||
<method name="key" cv="const">
|
||||
<type>key_type&</type>
|
||||
</method>
|
||||
<method name="mapped" cv="const">
|
||||
<type>mapped_type&</type>
|
||||
</method>
|
||||
<?php else: ?>
|
||||
<method name="value" cv="const">
|
||||
<type>value_type&</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; ?>&</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; ?>&</paramtype>
|
||||
</parameter>
|
||||
<parameter name="y">
|
||||
<paramtype><?php echo $full_type; ?>&</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 +1205,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 +1213,6 @@ echo_node_handle_docs(false);
|
||||
<?php
|
||||
echo_unordered_docs(true, false);
|
||||
echo_unordered_docs(true, true);
|
||||
echo_node_handle_docs(true);
|
||||
?>
|
||||
</namespace>
|
||||
</header>
|
||||
|
||||
+8
-1698
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@
|
||||
|
||||
//[case_insensitive_functions
|
||||
struct iequal_to
|
||||
: std::binary_function<std::string, std::string, bool>
|
||||
{
|
||||
bool operator()(std::string const& x,
|
||||
std::string const& y) const
|
||||
@@ -19,6 +20,7 @@
|
||||
};
|
||||
|
||||
struct ihash
|
||||
: std::unary_function<std::string, std::size_t>
|
||||
{
|
||||
std::size_t operator()(std::string const& x) const
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
}
|
||||
|
||||
struct point_hash
|
||||
: std::unary_function<point, std::size_t>
|
||||
{
|
||||
std::size_t operator()(point const& p) const
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
namespace hash_examples
|
||||
{
|
||||
struct iequal_to
|
||||
: std::binary_function<std::string, std::string, bool>
|
||||
{
|
||||
iequal_to() {}
|
||||
explicit iequal_to(std::locale const& l) : locale_(l) {}
|
||||
@@ -33,6 +34,7 @@ namespace hash_examples
|
||||
};
|
||||
|
||||
struct ihash
|
||||
: std::unary_function<std::string, std::size_t>
|
||||
{
|
||||
ihash() {}
|
||||
explicit ihash(std::locale const& l) : locale_(l) {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,888 @@
|
||||
|
||||
// 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/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.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;
|
||||
|
||||
}}}
|
||||
|
||||
// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
|
||||
// in the detail namespace. It didn't work because the template parameters
|
||||
// were in detail. I'm not changing it at the moment to be safe. I might
|
||||
// do in the future if I change the iterator types.
|
||||
namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename Node> struct iterator;
|
||||
template <typename Node, typename ConstNodePointer> struct c_iterator;
|
||||
template <typename Node, typename Policy> struct l_iterator;
|
||||
template <typename Node, typename ConstNodePointer, typename Policy>
|
||||
struct cl_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename Node, typename Policy>
|
||||
struct l_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
typename Node::node_pointer,
|
||||
typename Node::value_type&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename Node2, typename ConstNodePointer, typename Policy2>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
private:
|
||||
#endif
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
l_iterator() BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
|
||||
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
value_type& operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
value_type* 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 BOOST_NOEXCEPT {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
|
||||
bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Node, typename ConstNodePointer, typename Policy>
|
||||
struct cl_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
ConstNodePointer,
|
||||
typename Node::value_type const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::l_iterator
|
||||
<Node, Policy>;
|
||||
private:
|
||||
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
|
||||
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
cl_iterator(boost::unordered::iterator_detail::l_iterator<
|
||||
Node, Policy> const& x) BOOST_NOEXCEPT :
|
||||
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
|
||||
{}
|
||||
|
||||
value_type const& operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
value_type 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)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.ptr_ == y.ptr_;
|
||||
}
|
||||
|
||||
friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.ptr_ != y.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Node>
|
||||
struct iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
typename Node::node_pointer,
|
||||
typename Node::value_type&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::c_iterator;
|
||||
template <typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::l_iterator;
|
||||
template <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 typename Node::node_pointer node_pointer;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
iterator() BOOST_NOEXCEPT : node_() {}
|
||||
|
||||
explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
|
||||
node_(static_cast<node_pointer>(x)) {}
|
||||
|
||||
value_type& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
value_type* 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 BOOST_NOEXCEPT {
|
||||
return node_ == x.node_;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
|
||||
return node_ != x.node_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Node, typename ConstNodePointer>
|
||||
struct c_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
ConstNodePointer,
|
||||
typename Node::value_type const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::iterator<Node>;
|
||||
|
||||
#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 typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
c_iterator() BOOST_NOEXCEPT : node_() {}
|
||||
|
||||
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
|
||||
node_(static_cast<node_pointer>(x)) {}
|
||||
|
||||
c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
|
||||
|
||||
value_type const& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
value_type 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)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.node_ == y.node_;
|
||||
}
|
||||
|
||||
friend bool operator!=(c_iterator const& x, c_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
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_;
|
||||
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::func::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::func::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::func::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(node_);
|
||||
node_constructed_ = true;
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_);
|
||||
|
||||
if (value_constructed_)
|
||||
{
|
||||
boost::unordered::detail::func::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> iterator;
|
||||
|
||||
node_pointer nodes_;
|
||||
|
||||
public:
|
||||
|
||||
template <typename Table>
|
||||
explicit node_holder(Table& b) :
|
||||
base(b.node_alloc()),
|
||||
nodes_()
|
||||
{
|
||||
if (b.size_) {
|
||||
typename Table::link_pointer prev = b.get_previous_start();
|
||||
nodes_ = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = link_pointer();
|
||||
b.size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~node_holder();
|
||||
|
||||
void node_for_assignment()
|
||||
{
|
||||
if (!this->node_ && nodes_) {
|
||||
this->node_ = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
this->node_->init(this->node_);
|
||||
this->node_->next_ = link_pointer();
|
||||
|
||||
this->node_constructed_ = true;
|
||||
this->value_constructed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void assign_impl(T const& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = v;
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void assign_impl(std::pair<T1 const, T2> const& v) {
|
||||
this->construct_with_value2(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_assign_impl(T& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = boost::move(v);
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
|
||||
node_pointer copy_of(value_type const& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
assign_impl(v);
|
||||
return base::release();
|
||||
}
|
||||
|
||||
node_pointer move_copy_of(value_type& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
move_assign_impl(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::func::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 link_pointer;
|
||||
link_pointer next_;
|
||||
|
||||
bucket() : next_() {}
|
||||
|
||||
link_pointer first_from_start()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
enum { extra_node = true };
|
||||
};
|
||||
|
||||
struct ptr_bucket
|
||||
{
|
||||
typedef ptr_bucket* link_pointer;
|
||||
link_pointer next_;
|
||||
|
||||
ptr_bucket() : next_(0) {}
|
||||
|
||||
link_pointer first_from_start()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
enum { extra_node = false };
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hash Policy
|
||||
|
||||
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, bool NoThrowMoveAssign>
|
||||
class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
class functions
|
||||
{
|
||||
public:
|
||||
static const bool nothrow_move_assignable =
|
||||
boost::is_nothrow_move_assignable<H>::value &&
|
||||
boost::is_nothrow_move_assignable<P>::value;
|
||||
static const bool nothrow_move_constructible =
|
||||
boost::is_nothrow_move_constructible<H>::value &&
|
||||
boost::is_nothrow_move_constructible<P>::value;
|
||||
|
||||
private:
|
||||
friend class boost::unordered::detail::set_hash_functions<H, P,
|
||||
nothrow_move_assignable>;
|
||||
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_]));
|
||||
}
|
||||
|
||||
function_pair& current() {
|
||||
return *static_cast<function_pair*>(
|
||||
static_cast<void*>(&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,
|
||||
boost::unordered::detail::false_type =
|
||||
boost::unordered::detail::false_type())
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair& f,
|
||||
boost::unordered::detail::true_type)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f,
|
||||
boost::unordered::detail::move_tag());
|
||||
}
|
||||
|
||||
void destroy(bool which)
|
||||
{
|
||||
boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef boost::unordered::detail::set_hash_functions<H, P,
|
||||
nothrow_move_assignable> set_hash_functions;
|
||||
|
||||
functions(H const& hf, P const& eq)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, hf, eq);
|
||||
}
|
||||
|
||||
functions(functions const& bf)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current());
|
||||
}
|
||||
|
||||
functions(functions& bf, boost::unordered::detail::move_tag)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current(),
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
nothrow_move_constructible>());
|
||||
}
|
||||
|
||||
~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<H, P, false>
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef functions<H, P> functions_type;
|
||||
|
||||
functions_type& functions_;
|
||||
bool tmp_functions_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(functions_type& f, H const& h, P const& p)
|
||||
: functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, h, p);
|
||||
}
|
||||
|
||||
set_hash_functions(functions_type& f, functions_type 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_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions<H, P, true>
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef functions<H, P> functions_type;
|
||||
|
||||
functions_type& functions_;
|
||||
H hash_;
|
||||
P pred_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(functions_type& f, H const& h, P const& p) :
|
||||
functions_(f),
|
||||
hash_(h),
|
||||
pred_(p) {}
|
||||
|
||||
set_hash_functions(functions_type& f, functions_type const& other) :
|
||||
functions_(f),
|
||||
hash_(other.hash_function()),
|
||||
pred_(other.key_eq()) {}
|
||||
|
||||
void commit()
|
||||
{
|
||||
functions_.current().first() = boost::move(hash_);
|
||||
functions_.current().second() = boost::move(pred_);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
|
||||
// e.g. for int
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_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,680 @@
|
||||
|
||||
// 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 allocator;
|
||||
typedef typename ::boost::unordered::detail::
|
||||
allocator_traits<allocator>::pointer node_pointer;
|
||||
typedef node_pointer link_pointer;
|
||||
|
||||
link_pointer next_;
|
||||
node_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
grouped_node() :
|
||||
next_(),
|
||||
group_prev_(),
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(node_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 grouped_ptr_node<T>* node_pointer;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
node_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
grouped_ptr_node() :
|
||||
bucket_base(),
|
||||
group_prev_(0),
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(node_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::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 = this->hash_to_bucket(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 (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
n = iterator(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 = 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(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(n1.node_->group_prev_->next_);
|
||||
iterator end2(n2.node_->group_prev_->next_);
|
||||
if (!group_equals(n1, end1, n2, end2)) return false;
|
||||
n1 = end1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Emplace/Insert
|
||||
|
||||
static inline void add_after_node(
|
||||
node_pointer n,
|
||||
node_pointer pos)
|
||||
{
|
||||
n->next_ = pos->group_prev_->next_;
|
||||
n->group_prev_ = pos->group_prev_;
|
||||
pos->group_prev_->next_ = n;
|
||||
pos->group_prev_ = 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 = this->hash_to_bucket(
|
||||
static_cast<node_pointer>(n->next_)->hash_);
|
||||
if (next_bucket != this->hash_to_bucket(key_hash)) {
|
||||
this->get_bucket(next_bucket)->next_ = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bucket_pointer b = this->get_bucket(
|
||||
this->hash_to_bucket(key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
link_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(this->hash_to_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_
|
||||
))->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
n->next_ = start_node->next_;
|
||||
start_node->next_ = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = 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_CXX11_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_CXX11_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 = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (this->hash_to_bucket(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<node_pointer>(prev->next_)->group_prev_;
|
||||
}
|
||||
|
||||
node_pointer first_node = static_cast<node_pointer>(prev->next_);
|
||||
link_pointer end = first_node->group_prev_->next_;
|
||||
|
||||
std::size_t count = this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return count;
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
{
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
erase_nodes(r.node_, next.node_);
|
||||
return next;
|
||||
}
|
||||
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
erase_nodes(r1.node_, r2.node_);
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
link_pointer erase_nodes(node_pointer begin, node_pointer end)
|
||||
{
|
||||
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
|
||||
|
||||
// Split the groups containing 'begin' and 'end'.
|
||||
// And get the pointer to the node before begin while
|
||||
// we're at it.
|
||||
link_pointer prev = split_groups(begin, end);
|
||||
|
||||
// If we don't have a 'prev' it means that begin is at the
|
||||
// beginning of a block, so search through the blocks in the
|
||||
// same bucket.
|
||||
if (!prev) {
|
||||
prev = this->get_previous_start(bucket_index);
|
||||
while (prev->next_ != begin)
|
||||
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
|
||||
}
|
||||
|
||||
// Delete the nodes.
|
||||
do {
|
||||
link_pointer group_end =
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
|
||||
this->delete_nodes(prev, group_end);
|
||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||
} while(prev->next_ != end);
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static link_pointer split_groups(node_pointer begin, node_pointer end)
|
||||
{
|
||||
node_pointer prev = begin->group_prev_;
|
||||
if (prev->next_ != begin) prev = node_pointer();
|
||||
|
||||
if (end) {
|
||||
node_pointer first = end;
|
||||
while (first != begin && first->group_prev_->next_ == first) {
|
||||
first = first->group_prev_;
|
||||
}
|
||||
|
||||
boost::swap(first->group_prev_, end->group_prev_);
|
||||
if (first == begin) return prev;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
node_pointer first = prev;
|
||||
while (first->group_prev_->next_ == first) {
|
||||
first = first->group_prev_;
|
||||
}
|
||||
boost::swap(first->group_prev_, begin->group_prev_);
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// fill_buckets
|
||||
|
||||
template <class NodeCreator>
|
||||
static void fill_buckets(iterator n, table& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
link_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
|
||||
node_pointer first_node = creator.create(*n);
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = 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);
|
||||
link_pointer prev = this->get_previous_start();
|
||||
while (prev->next_)
|
||||
prev = place_in_bucket(*this, prev,
|
||||
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 link_pointer place_in_bucket(table& dst,
|
||||
link_pointer prev, node_pointer end)
|
||||
{
|
||||
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
return 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,183 @@
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class Arg3, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
|
||||
Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
template <typename T2> \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_ tuple<> const&, T2 const&) \
|
||||
{ \
|
||||
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, T2 const&) \
|
||||
{ \
|
||||
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
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,56 +1,22 @@
|
||||
|
||||
// Copyright (C) 2008-2016 Daniel James.
|
||||
// Copyright (C) 2008-2011 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
|
||||
// Already defined.
|
||||
#elif defined(BOOST_LIBSTDCXX11)
|
||||
// https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70
|
||||
#if BOOST_LIBSTDCXX_VERSION > 40600
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
#endif
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
|
||||
#if LIBCPP_VERSION >= 3000
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
#endif
|
||||
#elif defined(BOOST_MSVC)
|
||||
// Apparently C++11 standard supported in Visual Studio 2012
|
||||
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
|
||||
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
|
||||
#if BOOST_MSVC >= 1700
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
using std::piecewise_construct_t;
|
||||
using std::piecewise_construct;
|
||||
#else
|
||||
struct piecewise_construct_t
|
||||
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
@@ -1,107 +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 typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<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, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
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 A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
typedef boost::unordered::detail::multimap<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;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<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, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_map<node, K, M, A> node_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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +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 typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
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 A, typename T, typename H, typename P> struct multiset
|
||||
{
|
||||
typedef boost::unordered::detail::multiset<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;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_set<node, T, A> node_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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,863 @@
|
||||
|
||||
// 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
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
|
||||
#if defined(__EDG__)
|
||||
#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
|
||||
#pragma message("Warning: BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported.")
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || \
|
||||
defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#warning "BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported."
|
||||
#endif
|
||||
|
||||
#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 :
|
||||
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 functions::set_hash_functions set_hash_functions;
|
||||
|
||||
typedef typename Types::allocator allocator;
|
||||
typedef typename boost::unordered::detail::
|
||||
rebind_wrap<allocator, node>::type node_allocator;
|
||||
typedef typename boost::unordered::detail::
|
||||
rebind_wrap<allocator, bucket>::type bucket_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<node_allocator>
|
||||
node_allocator_traits;
|
||||
typedef boost::unordered::detail::allocator_traits<bucket_allocator>
|
||||
bucket_allocator_traits;
|
||||
typedef typename node_allocator_traits::pointer
|
||||
node_pointer;
|
||||
typedef typename node_allocator_traits::const_pointer
|
||||
const_node_pointer;
|
||||
typedef typename bucket_allocator_traits::pointer
|
||||
bucket_pointer;
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<node, const_node_pointer> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<node, const_node_pointer, 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);
|
||||
}
|
||||
|
||||
link_pointer get_previous_start() const
|
||||
{
|
||||
return get_bucket(bucket_count_)->first_from_start();
|
||||
}
|
||||
|
||||
link_pointer get_previous_start(std::size_t bucket_index) const
|
||||
{
|
||||
return get_bucket(bucket_index)->next_;
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return size_ ? iterator(get_previous_start()->next_) : iterator();
|
||||
}
|
||||
|
||||
iterator begin(std::size_t bucket_index) const
|
||||
{
|
||||
if (!size_) return iterator();
|
||||
link_pointer prev = get_previous_start(bucket_index);
|
||||
return prev ? iterator(prev->next_) : iterator();
|
||||
}
|
||||
|
||||
std::size_t hash_to_bucket(std::size_t hash) const
|
||||
{
|
||||
return policy::to_bucket(bucket_count_, hash);
|
||||
}
|
||||
|
||||
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_ && hash_to_bucket(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, m),
|
||||
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 m) :
|
||||
functions(x, m),
|
||||
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)
|
||||
{
|
||||
boost::unordered::detail::func::ignore_unused_variable_warning(other);
|
||||
|
||||
// According to 23.2.1.8, if propagate_on_container_swap is
|
||||
// false the behaviour is undefined unless the allocators
|
||||
// are equal.
|
||||
BOOST_ASSERT(node_alloc() == other.node_alloc());
|
||||
}
|
||||
|
||||
void swap_allocators(table& other, true_type)
|
||||
{
|
||||
allocators_.swap(other.allocators_);
|
||||
}
|
||||
|
||||
// Only swaps the allocators if propagate_on_container_swap
|
||||
void swap(table& x)
|
||||
{
|
||||
set_hash_functions op1(*this, x);
|
||||
set_hash_functions op2(x, *this);
|
||||
|
||||
// I think swap can throw if Propagate::value,
|
||||
// since the allocators' swap can throw. Not sure though.
|
||||
swap_allocators(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_swap::value>());
|
||||
|
||||
boost::swap(buckets_, x.buckets_);
|
||||
boost::swap(bucket_count_, x.bucket_count_);
|
||||
boost::swap(size_, x.size_);
|
||||
std::swap(mlf_, x.mlf_);
|
||||
std::swap(max_load_, x.max_load_);
|
||||
op1.commit();
|
||||
op2.commit();
|
||||
}
|
||||
|
||||
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(link_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = n->next_;
|
||||
|
||||
boost::unordered::detail::func::destroy_value_impl(node_alloc(),
|
||||
n->value_ptr());
|
||||
node_allocator_traits::destroy(node_alloc(),
|
||||
boost::addressof(*n));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
--size_;
|
||||
}
|
||||
|
||||
std::size_t delete_nodes(link_pointer prev, link_pointer end)
|
||||
{
|
||||
BOOST_ASSERT(prev->next_ != end);
|
||||
|
||||
std::size_t count = 0;
|
||||
|
||||
do {
|
||||
delete_node(prev);
|
||||
++count;
|
||||
} while (prev->next_ != end);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void delete_buckets()
|
||||
{
|
||||
if(buckets_) {
|
||||
if (size_) delete_nodes(get_previous_start(), link_pointer());
|
||||
|
||||
if (bucket::extra_node) {
|
||||
node_pointer n = static_cast<node_pointer>(
|
||||
get_bucket(bucket_count_)->next_);
|
||||
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(get_previous_start(), link_pointer());
|
||||
clear_buckets();
|
||||
|
||||
BOOST_ASSERT(!size_);
|
||||
}
|
||||
|
||||
void clear_buckets()
|
||||
{
|
||||
bucket_pointer end = get_bucket(bucket_count_);
|
||||
for(bucket_pointer it = buckets_; it != end; ++it)
|
||||
{
|
||||
it->next_ = node_pointer();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_buckets()
|
||||
{
|
||||
bucket_pointer end = get_bucket(bucket_count_ + 1);
|
||||
for(bucket_pointer it = buckets_; it != end; ++it)
|
||||
{
|
||||
bucket_allocator_traits::destroy(bucket_alloc(),
|
||||
boost::addressof(*it));
|
||||
}
|
||||
|
||||
bucket_allocator_traits::deallocate(bucket_alloc(),
|
||||
buckets_, bucket_count_ + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Fix buckets after delete
|
||||
//
|
||||
|
||||
std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
|
||||
{
|
||||
link_pointer end = prev->next_;
|
||||
std::size_t bucket_index2 = bucket_index;
|
||||
|
||||
if (end)
|
||||
{
|
||||
bucket_index2 = hash_to_bucket(
|
||||
static_cast<node_pointer>(end)->hash_);
|
||||
|
||||
// If begin and end are in the same bucket, then
|
||||
// there's nothing to do.
|
||||
if (bucket_index == bucket_index2) return bucket_index2;
|
||||
|
||||
// Update the bucket containing end.
|
||||
get_bucket(bucket_index2)->next_ = prev;
|
||||
}
|
||||
|
||||
// Check if this bucket is now empty.
|
||||
bucket_pointer this_bucket = get_bucket(bucket_index);
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = link_pointer();
|
||||
|
||||
return bucket_index2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Assignment
|
||||
|
||||
void assign(table const& x)
|
||||
{
|
||||
if (this != boost::addressof(x))
|
||||
{
|
||||
assign(x,
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
allocator_traits<node_allocator>::
|
||||
propagate_on_container_copy_assignment::value>());
|
||||
}
|
||||
}
|
||||
|
||||
void assign(table const& x, false_type)
|
||||
{
|
||||
// Strong exception safety.
|
||||
set_hash_functions 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 {
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
|
||||
// Delete everything with current allocators before assigning
|
||||
// the new ones.
|
||||
delete_buckets();
|
||||
allocators_.assign(x.allocators_);
|
||||
|
||||
// Copy over other data, all no throw.
|
||||
new_func_this.commit();
|
||||
mlf_ = x.mlf_;
|
||||
bucket_count_ = min_buckets_for_size(x.size_);
|
||||
max_load_ = 0;
|
||||
|
||||
// Finally copy the elements.
|
||||
if (x.size_) {
|
||||
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 {
|
||||
set_hash_functions 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)
|
||||
{
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
// No throw from here.
|
||||
mlf_ = x.mlf_;
|
||||
max_load_ = x.max_load_;
|
||||
move_buckets_from(x);
|
||||
new_func_this.commit();
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,620 @@
|
||||
|
||||
// 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 node_pointer;
|
||||
typedef node_pointer link_pointer;
|
||||
|
||||
link_pointer next_;
|
||||
std::size_t hash_;
|
||||
|
||||
unique_node() :
|
||||
next_(),
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(node_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_node<T>* node_pointer;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
std::size_t hash_;
|
||||
|
||||
ptr_node() :
|
||||
bucket_base(),
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(node_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::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 = this->hash_to_bucket(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 (this->hash_to_bucket(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 (!n2.node_ || *n1 != *n2)
|
||||
return false;
|
||||
}
|
||||
|
||||
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(this->hash_to_bucket(key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
link_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(this->hash_to_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_)
|
||||
)->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
n->next_ = start_node->next_;
|
||||
start_node->next_ = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = n;
|
||||
}
|
||||
|
||||
++this->size_;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
value_type& operator[](key_type const& k)
|
||||
{
|
||||
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_CXX11_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_CXX11_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_CXX11_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_CXX11_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 = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (this->hash_to_bucket(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 = prev->next_;
|
||||
}
|
||||
|
||||
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
|
||||
|
||||
std::size_t count = this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return count;
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
{
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
erase_nodes(r.node_, next.node_);
|
||||
return next;
|
||||
}
|
||||
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
erase_nodes(r1.node_, r2.node_);
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
void erase_nodes(node_pointer begin, node_pointer end)
|
||||
{
|
||||
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
|
||||
|
||||
// Find the node before begin.
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
while(prev->next_ != begin) prev = prev->next_;
|
||||
|
||||
// Delete the nodes.
|
||||
do {
|
||||
this->delete_node(prev);
|
||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||
} while (prev->next_ != end);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// fill_buckets
|
||||
|
||||
template <class NodeCreator>
|
||||
static void fill_buckets(iterator n, table& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
link_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
node_pointer node = creator.create(*n);
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = 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);
|
||||
link_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 link_pointer place_in_bucket(table& dst, link_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
return n;
|
||||
}
|
||||
else {
|
||||
prev->next_ = n->next_;
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = n;
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
|
||||
// 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 {};
|
||||
|
||||
namespace func {
|
||||
template <class T>
|
||||
inline void ignore_unused_variable_warning(T const&) {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
+1561
-2121
File diff suppressed because it is too large
Load Diff
@@ -6,56 +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>&, unordered_map<K, T, H, P, A>&);
|
||||
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>&, unordered_multimap<K, T, H, P, A>&);
|
||||
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
|
||||
|
||||
+1458
-1796
File diff suppressed because it is too large
Load Diff
@@ -6,54 +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);
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_SET_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_set.hpp>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"key": "unordered",
|
||||
"name": "Unordered",
|
||||
"authors": [
|
||||
"Daniel James"
|
||||
],
|
||||
"maintainers": [
|
||||
"Daniel James <dnljms -at- gmail.com>"
|
||||
],
|
||||
"description": "Unordered associative containers.",
|
||||
"std": [
|
||||
"tr1"
|
||||
],
|
||||
"category": [
|
||||
"Containers"
|
||||
]
|
||||
}
|
||||
+2
-86
@@ -5,89 +5,5 @@
|
||||
|
||||
import testing ;
|
||||
|
||||
project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
# Would be nice to define -Wundef, but I'm getting warnings from
|
||||
# Boost.Preprocessor on trunk.
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>msvc:<cxxflags>"/wd4494"
|
||||
;
|
||||
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
alias framework : ;
|
||||
|
||||
test-suite unordered
|
||||
:
|
||||
[ run unordered/fwd_set_test.cpp ]
|
||||
[ run unordered/fwd_map_test.cpp ]
|
||||
[ run unordered/allocator_traits.cpp ]
|
||||
[ run unordered/minimal_allocator.cpp ]
|
||||
[ run unordered/compile_set.cpp ]
|
||||
[ run unordered/compile_map.cpp ]
|
||||
[ run unordered/compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
|
||||
: compile_map_unordered_allocator ]
|
||||
[ run unordered/noexcept_tests.cpp ]
|
||||
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
|
||||
[ run unordered/incomplete_test.cpp ]
|
||||
[ run unordered/simple_tests.cpp ]
|
||||
[ run unordered/equivalent_keys_tests.cpp ]
|
||||
[ run unordered/constructor_tests.cpp ]
|
||||
[ run unordered/copy_tests.cpp ]
|
||||
[ run unordered/move_tests.cpp ]
|
||||
[ run unordered/assign_tests.cpp ]
|
||||
[ run unordered/insert_tests.cpp ]
|
||||
[ run unordered/insert_stable_tests.cpp ]
|
||||
[ run unordered/insert_hint_tests.cpp ]
|
||||
[ run unordered/emplace_tests.cpp ]
|
||||
[ run unordered/unnecessary_copy_tests.cpp ]
|
||||
[ run unordered/erase_tests.cpp ]
|
||||
[ run unordered/erase_equiv_tests.cpp ]
|
||||
[ run unordered/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/compile_set.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_set ]
|
||||
[ run unordered/compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_map ]
|
||||
[ run unordered/copy_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_copy ]
|
||||
[ run unordered/move_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_move ]
|
||||
[ run unordered/assign_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_assign ]
|
||||
;
|
||||
|
||||
test-suite unordered-exception
|
||||
:
|
||||
[ run exception/constructor_exception_tests.cpp framework ]
|
||||
[ run exception/copy_exception_tests.cpp framework ]
|
||||
[ run exception/assign_exception_tests.cpp framework ]
|
||||
[ run exception/move_assign_exception_tests.cpp framework ]
|
||||
[ run exception/insert_exception_tests.cpp framework ]
|
||||
[ run exception/erase_exception_tests.cpp framework ]
|
||||
[ run exception/rehash_exception_tests.cpp framework ]
|
||||
[ run exception/swap_exception_tests.cpp framework : : :
|
||||
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
;
|
||||
build-project unordered ;
|
||||
build-project exception ;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
# Copyright 2006-2008 Daniel James.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import testing ;
|
||||
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
alias framework : ;
|
||||
|
||||
project unordered-test/exception-tests
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
#<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
test-suite unordered-exception
|
||||
:
|
||||
[ run constructor_exception_tests.cpp framework ]
|
||||
[ run copy_exception_tests.cpp framework ]
|
||||
[ run assign_exception_tests.cpp framework ]
|
||||
[ run insert_exception_tests.cpp framework ]
|
||||
[ run erase_exception_tests.cpp framework ]
|
||||
[ run rehash_exception_tests.cpp framework ]
|
||||
[ run swap_exception_tests.cpp framework : : :
|
||||
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
;
|
||||
@@ -4,52 +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/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) {}
|
||||
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; }
|
||||
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);
|
||||
@@ -63,76 +66,47 @@ template <class T> struct assign_base : public test::exception_base
|
||||
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,
|
||||
float mlf1 = 1.0, float mlf2 = 1.0)
|
||||
: assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
assign_test1() : assign_base<T>(0, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test1 : assign_values<T>
|
||||
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_test3 : assign_values<T>
|
||||
template <class T>
|
||||
struct assign_test4 : assign_base<T>
|
||||
{
|
||||
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
|
||||
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test4 : assign_values<T>
|
||||
template <class T>
|
||||
struct assign_test5 : assign_base<T>
|
||||
{
|
||||
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
|
||||
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test4a : assign_values<T>
|
||||
{
|
||||
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test5 : assign_values<T>
|
||||
{
|
||||
assign_test5() : assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
|
||||
};
|
||||
|
||||
template <class T> struct equivalent_test1 : assign_base<T>
|
||||
{
|
||||
equivalent_test1() : assign_base<T>(0, 0)
|
||||
{
|
||||
test::random_values<T> x_values2(10);
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
test::random_values<T> y_values2(10);
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((self_assign_test1)(self_assign_test2)(assign_test1)(
|
||||
assign_test2)(assign_test3)(assign_test4)(assign_test4a)(
|
||||
assign_test5)(equivalent_test1),
|
||||
EXCEPTION_TESTS(
|
||||
(self_assign_test1)(self_assign_test2)
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -4,9 +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/random_values.hpp"
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
@@ -20,61 +19,62 @@ 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;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
|
||||
@@ -82,37 +82,37 @@ template <class T> struct range : public test::exception_base
|
||||
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());
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
avoid_unused_warning(x);
|
||||
}
|
||||
@@ -120,51 +120,58 @@ template <class T> struct range_construct_test4 : public range<T>, objects
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
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),
|
||||
(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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -4,53 +4,53 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "./containers.hpp"
|
||||
|
||||
#include "../helpers/random_values.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);
|
||||
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), x(values.begin(), values.end()) {}
|
||||
|
||||
void run() const
|
||||
{
|
||||
void run() const {
|
||||
T y(x);
|
||||
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);
|
||||
avoid_unused_warning(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;
|
||||
@@ -58,13 +58,13 @@ 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);
|
||||
avoid_unused_warning(y);
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
|
||||
EXCEPTION_TESTS(
|
||||
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -4,47 +4,52 @@
|
||||
// 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) {}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
|
||||
EXCEPTION_TESTS(
|
||||
(erase_by_key_test1),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -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/strong.hpp"
|
||||
#include <cmath>
|
||||
#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);
|
||||
|
||||
template <class T> struct insert_test_base : public test::exception_base
|
||||
template <class T>
|
||||
struct insert_test_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
insert_test_base(unsigned int count = 5)
|
||||
: values(count, test::limited_range)
|
||||
{
|
||||
}
|
||||
insert_test_base(unsigned int count = 5) : values(count) {}
|
||||
|
||||
typedef T data_type;
|
||||
typedef test::strong<T> strong_type;
|
||||
|
||||
data_type init() const { return T(); }
|
||||
data_type init() const {
|
||||
return 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)
|
||||
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_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T> struct emplace_test1 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct emplace_test1 : public insert_test_base<T>
|
||||
{
|
||||
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) {
|
||||
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.emplace(*it);
|
||||
}
|
||||
@@ -59,98 +57,99 @@ template <class T> struct emplace_test1 : public insert_test_base<T>
|
||||
|
||||
#endif
|
||||
|
||||
template <class T> struct insert_test1 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct insert_test1 : public insert_test_base<T>
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test2 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct insert_test2 : public insert_test_base<T>
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test3 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct insert_test3 : public insert_test_base<T>
|
||||
{
|
||||
void run(T& x) const { x.insert(this->values.begin(), this->values.end()); }
|
||||
void run(T& x) const {
|
||||
x.insert(this->values.begin(), this->values.end());
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
|
||||
{
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test4 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct insert_test4 : public insert_test_base<T>
|
||||
{
|
||||
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) {
|
||||
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, test::next(it));
|
||||
x.insert(it, boost::next(it));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash1 : public insert_test_base<T>
|
||||
template <class T>
|
||||
struct insert_test_rehash1 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
insert_test_rehash1() : insert_test_base<T>(1000) {}
|
||||
|
||||
T init() const
|
||||
{
|
||||
T init() const {
|
||||
using namespace std;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
|
||||
|
||||
T x;
|
||||
x.max_load_factor(0.25);
|
||||
// TODO: This doesn't really work is bucket_count is 0
|
||||
size_type bucket_count = x.bucket_count();
|
||||
size_type initial_elements = static_cast<size_type>(
|
||||
ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
|
||||
ceil(bucket_count * (double) x.max_load_factor()) - 1);
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
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();
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = test::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count) {
|
||||
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);
|
||||
}
|
||||
@@ -161,19 +160,20 @@ template <class T> struct insert_test_rehash1 : public insert_test_base<T>
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash2 : public insert_test_rehash1<T>
|
||||
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
|
||||
{
|
||||
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 = test::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count) {
|
||||
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);
|
||||
}
|
||||
@@ -184,15 +184,15 @@ template <class T> struct insert_test_rehash2 : public insert_test_rehash1<T>
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash3 : public insert_test_base<T>
|
||||
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;
|
||||
BOOST_DEDUCED_TYPENAME T::size_type mutable
|
||||
rehash_bucket_count, original_bucket_count;
|
||||
|
||||
insert_test_rehash3() : insert_test_base<T>(1000) {}
|
||||
|
||||
T init() const
|
||||
{
|
||||
T init() const {
|
||||
using namespace std;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
|
||||
|
||||
@@ -200,108 +200,48 @@ template <class T> struct insert_test_rehash3 : public insert_test_base<T>
|
||||
x.max_load_factor(0.25);
|
||||
|
||||
original_bucket_count = x.bucket_count();
|
||||
rehash_bucket_count =
|
||||
static_cast<size_type>(ceil(
|
||||
(double)original_bucket_count * (double)x.max_load_factor())) -
|
||||
1;
|
||||
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(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
boost::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(original_bucket_count == x.bucket_count());
|
||||
return x;
|
||||
}
|
||||
|
||||
void run(T& x) const
|
||||
{
|
||||
void run(T& x) const {
|
||||
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
|
||||
|
||||
x.insert(test::next(this->values.begin(), x.size()),
|
||||
test::next(this->values.begin(), x.size() + 20));
|
||||
x.insert(boost::next(this->values.begin(), x.size()),
|
||||
boost::next(this->values.begin(), x.size() + 20));
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
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);
|
||||
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)
|
||||
#define BASIC_TESTS \
|
||||
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
|
||||
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define ALL_TESTS (emplace_test1) BASIC_TESTS
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define ALL_TESTS (emplace_test1)BASIC_TESTS
|
||||
#else
|
||||
#define ALL_TESTS BASIC_TESTS
|
||||
#endif
|
||||
|
||||
|
||||
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
|
||||
template <class T> struct pair_emplace_test1 : public insert_test_base<T>
|
||||
{
|
||||
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.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first), boost::make_tuple(it->second));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct pair_emplace_test2 : public insert_test_base<T>
|
||||
{
|
||||
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.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first),
|
||||
boost::make_tuple(it->second.tag1_, it->second.tag2_));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((pair_emplace_test1)(pair_emplace_test2), CONTAINER_PAIR_SEQ)
|
||||
|
||||
template <class T> struct index_insert_test1 : public insert_test_base<T>
|
||||
{
|
||||
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[it->first];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((index_insert_test1), (test_map))
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -1,123 +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 <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning( \
|
||||
disable : 4512) // move_assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t initialize_seed(12847);
|
||||
|
||||
template <class T> struct move_assign_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> x_values, y_values;
|
||||
T x, y;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
|
||||
: x_values(), y_values(),
|
||||
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
|
||||
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
|
||||
{
|
||||
x.max_load_factor(mlf1);
|
||||
y.max_load_factor(mlf2);
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(x); }
|
||||
void run(T& x1) const
|
||||
{
|
||||
test::exceptions_enable disable_exceptions(false);
|
||||
T y1 = y;
|
||||
disable_exceptions.release();
|
||||
x1 = boost::move(y1);
|
||||
}
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
|
||||
{
|
||||
test::check_equivalent_keys(x1);
|
||||
|
||||
// If the container is empty at the point of the exception, the
|
||||
// internal structure is hidden, this exposes it, at the cost of
|
||||
// messing up the data.
|
||||
if (x_values.size()) {
|
||||
T& x2 = const_cast<T&>(x1);
|
||||
x2.emplace(*x_values.begin());
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_values : move_assign_base<T>
|
||||
{
|
||||
move_assign_values(unsigned int count1, unsigned int count2, int tag1,
|
||||
int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
|
||||
: move_assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test1 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test2 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test3 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test4 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test4a : move_assign_values<T>
|
||||
{
|
||||
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T> struct move_assign_test5 : move_assign_values<T>
|
||||
{
|
||||
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
|
||||
};
|
||||
|
||||
template <class T> struct equivalent_test1 : move_assign_base<T>
|
||||
{
|
||||
equivalent_test1() : move_assign_base<T>(0, 0)
|
||||
{
|
||||
test::random_values<T> x_values2(10);
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
test::random_values<T> y_values2(10);
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((move_assign_test1)(move_assign_test2)(move_assign_test3)(
|
||||
move_assign_test4)(move_assign_test4a)(move_assign_test5)(
|
||||
equivalent_test1),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
@@ -4,73 +4,76 @@
|
||||
// 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 <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), 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); }
|
||||
};
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
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); }
|
||||
|
||||
@@ -4,48 +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/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) {}
|
||||
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); }
|
||||
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);
|
||||
|
||||
// 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;
|
||||
@@ -56,69 +57,69 @@ template <class T> struct swap_base : public test::exception_base
|
||||
|
||||
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
|
||||
: 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))
|
||||
{
|
||||
}
|
||||
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) {
|
||||
}
|
||||
} 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),
|
||||
EXCEPTION_TESTS(
|
||||
(self_swap_test1)(self_swap_test2)
|
||||
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -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
|
||||
|
||||
+59
-70
@@ -6,85 +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
@@ -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
|
||||
|
||||
+207
-227
@@ -6,266 +6,246 @@
|
||||
#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_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 EXCEPTION_TESTS(test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((1))(param_seq))
|
||||
|
||||
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
|
||||
EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
|
||||
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((n))(param_seq))
|
||||
|
||||
#define EXCEPTION_TESTS_OP(r, product) \
|
||||
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
|
||||
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 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,
|
||||
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;
|
||||
ENABLE_EXCEPTIONS;
|
||||
call_ignore_extra_parameters<
|
||||
Test,
|
||||
BOOST_DEDUCED_TYPENAME Test::data_type,
|
||||
BOOST_DEDUCED_TYPENAME Test::strong_type
|
||||
>(&Test::run, test_, x, strong);
|
||||
}
|
||||
throw;
|
||||
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));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Quick exception testing based on lightweight test
|
||||
|
||||
namespace lightweight {
|
||||
static int iteration;
|
||||
static int count;
|
||||
|
||||
struct test_exception {
|
||||
char const* name;
|
||||
test_exception(char const* n) : name(n) {}
|
||||
};
|
||||
|
||||
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;
|
||||
do {
|
||||
++iteration;
|
||||
count = 0;
|
||||
|
||||
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 end()
|
||||
{
|
||||
if (exception_in_check_) {
|
||||
BOOST_ERROR("Unexcpected exception in test_runner check call.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Quick exception testing based on lightweight test
|
||||
|
||||
namespace lightweight {
|
||||
static int iteration;
|
||||
static int count;
|
||||
|
||||
struct test_exception
|
||||
{
|
||||
char const* name;
|
||||
test_exception(char const* n) : name(n) {}
|
||||
};
|
||||
|
||||
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;
|
||||
char const* error_msg = 0;
|
||||
do {
|
||||
++iteration;
|
||||
count = 0;
|
||||
|
||||
try {
|
||||
runner.run();
|
||||
success = true;
|
||||
} catch (test_failure) {
|
||||
error_msg = "test_failure caught.";
|
||||
break;
|
||||
} catch (test_exception) {
|
||||
continue;
|
||||
} catch (...) {
|
||||
error_msg = "Unexpected exception.";
|
||||
break;
|
||||
}
|
||||
} while (!success);
|
||||
|
||||
if (error_msg) {
|
||||
BOOST_ERROR(error_msg);
|
||||
}
|
||||
runner.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+10
-18
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
+89
-88
@@ -9,113 +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);
|
||||
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)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for(; lit != lend; ++lit) {
|
||||
if(eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
"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 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)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for (; lit != lend; ++lit) {
|
||||
if (eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
"in bucket.");
|
||||
break;
|
||||
// Check the load factor.
|
||||
|
||||
float load_factor =
|
||||
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
|
||||
using namespace std;
|
||||
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
|
||||
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
|
||||
|
||||
// Check that size in the buckets matches up.
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME X::size_type
|
||||
i = 0; i < x1.bucket_count(); ++i)
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
|
||||
{
|
||||
++bucket_size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Check that size matches up.
|
||||
|
||||
if (x1.size() != size) {
|
||||
BOOST_ERROR("x1.size() doesn't match actual size.");
|
||||
std::cout << x1.size() << "/" << size << std::endl;
|
||||
}
|
||||
|
||||
// Check the load factor.
|
||||
|
||||
float load_factor =
|
||||
size == 0 ? 0 : static_cast<float>(size) /
|
||||
static_cast<float>(x1.bucket_count());
|
||||
using namespace std;
|
||||
if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
|
||||
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
|
||||
|
||||
// Check that size in the buckets matches up.
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count();
|
||||
++i) {
|
||||
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
begin2 = x1.begin(i),
|
||||
end2 = x1.end(i);
|
||||
begin2 != end2; ++begin2) {
|
||||
++bucket_size;
|
||||
if(x1.size() != bucket_size) {
|
||||
BOOST_ERROR("x1.size() doesn't match bucket size.");
|
||||
std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -123,3 +123,4 @@ template <class X> void check_equivalent_keys(X const& x1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+280
-282
@@ -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
-139
@@ -6,153 +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;
|
||||
|
||||
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);
|
||||
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*/)
|
||||
{
|
||||
++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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+70
-91
@@ -11,115 +11,94 @@
|
||||
#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::test_list::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**) \
|
||||
{ \
|
||||
::test::write_compiler_info(); \
|
||||
::test::test_list::run_tests(); \
|
||||
return boost::report_errors(); \
|
||||
}
|
||||
#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() {}
|
||||
};
|
||||
|
||||
namespace test_list {
|
||||
static inline registered_test_base*& first()
|
||||
{
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
namespace test_list {
|
||||
static inline registered_test_base*& first() {
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline registered_test_base*& last()
|
||||
{
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
static inline registered_test_base*& last() {
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void add_test(registered_test_base* test)
|
||||
{
|
||||
if (last()) {
|
||||
last()->next = test;
|
||||
} else {
|
||||
first() = test;
|
||||
}
|
||||
static inline void add_test(registered_test_base* test) {
|
||||
if(last()) {
|
||||
last()->next = test;
|
||||
}
|
||||
else {
|
||||
first() = test;
|
||||
}
|
||||
|
||||
last() = 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_compiler_info()
|
||||
{
|
||||
#if defined(BOOST_GCC_CXX11)
|
||||
char const* cpp11 = "true";
|
||||
#else
|
||||
char const* cpp11 = "false";
|
||||
#endif
|
||||
|
||||
std::cout << "Compiler: " << BOOST_COMPILER << "\n"
|
||||
<< "Library: " << BOOST_STDLIB << "\n"
|
||||
<< "C++11: " << cpp11 << "\n"
|
||||
<< "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/preprocessor/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))
|
||||
|
||||
#endif
|
||||
|
||||
+135
-122
@@ -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
|
||||
|
||||
|
||||
+251
-278
@@ -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
|
||||
{
|
||||
value = Flag::is_propagate_on_move
|
||||
};
|
||||
struct propagate_on_container_swap {
|
||||
enum { value = Flag::is_propagate_on_swap }; };
|
||||
};
|
||||
};
|
||||
|
||||
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 Flag>
|
||||
struct assign_allocator_base
|
||||
{
|
||||
force_equal_allocator_value = value;
|
||||
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;
|
||||
}
|
||||
|
||||
~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)
|
||||
struct force_equal_allocator
|
||||
{
|
||||
detail::tracker.allocator_ref();
|
||||
}
|
||||
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 Y>
|
||||
cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
|
||||
: tag_(x.tag_), selected_(x.selected_)
|
||||
template <typename T>
|
||||
struct cxx11_allocator_base
|
||||
{
|
||||
detail::tracker.allocator_ref();
|
||||
}
|
||||
int tag_;
|
||||
int selected_;
|
||||
|
||||
cxx11_allocator_base(cxx11_allocator_base const& x)
|
||||
: tag_(x.tag_), selected_(x.selected_)
|
||||
{
|
||||
detail::tracker.allocator_ref();
|
||||
}
|
||||
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_base() { detail::tracker.allocator_unref(); }
|
||||
explicit cxx11_allocator_base(int t)
|
||||
: tag_(t), selected_(0)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
pointer address(reference r) { return pointer(&r); }
|
||||
cxx11_allocator_base(cxx11_allocator_base const& x)
|
||||
: tag_(x.tag_), selected_(x.selected_)
|
||||
{
|
||||
detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
const_pointer address(const_reference r) { return const_pointer(&r); }
|
||||
~cxx11_allocator_base()
|
||||
{
|
||||
detail::tracker.allocator_unref();
|
||||
}
|
||||
|
||||
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 address(reference r)
|
||||
{
|
||||
return pointer(&r);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const_pointer address(const_reference r)
|
||||
{
|
||||
return const_pointer(&r);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t)
|
||||
{
|
||||
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
|
||||
new (p) T(t);
|
||||
}
|
||||
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_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)...);
|
||||
}
|
||||
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();
|
||||
}
|
||||
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;
|
||||
size_type max_size() const {
|
||||
return (std::numeric_limits<size_type>::max)();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
explicit cxx11_allocator(int t = 0) : cxx11_allocator_base<T>(t) {}
|
||||
template <typename T, typename Flags = propagate_swap,
|
||||
typename Enable = void>
|
||||
struct cxx11_allocator;
|
||||
|
||||
template <typename Y>
|
||||
cxx11_allocator(cxx11_allocator<Y, Flags> const& x)
|
||||
: cxx11_allocator_base<T>(x)
|
||||
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;
|
||||
};
|
||||
|
||||
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
// 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_);
|
||||
}
|
||||
cxx11_allocator(cxx11_allocator const& x)
|
||||
: cxx11_allocator_base<T>(x)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator!=(cxx11_allocator const& x) const { return !(*this == 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_);
|
||||
}
|
||||
|
||||
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;
|
||||
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>
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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_);
|
||||
template <typename T>
|
||||
convert_from_anything(T const&) {}
|
||||
};
|
||||
|
||||
inline int selected_count(convert_from_anything)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
template <typename T, typename Flags>
|
||||
int selected_count(cxx11_allocator<T, Flags> const& x)
|
||||
{
|
||||
return x.selected_;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+503
-630
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
+407
-517
File diff suppressed because it is too large
Load Diff
+544
-581
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
|
||||
# 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 noexcept_tests.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_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 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 ]
|
||||
;
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
@@ -20,19 +17,20 @@
|
||||
#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;
|
||||
|
||||
std::cerr << "assign_tests1.1\n";
|
||||
std::cerr<<"assign_tests1.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -43,7 +41,7 @@ template <class T> void assign_tests1(T*, test::random_generator generator)
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests1.2\n";
|
||||
std::cerr<<"assign_tests1.2\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -68,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);
|
||||
@@ -76,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;
|
||||
|
||||
std::cerr << "assign_tests2.0 - empty container\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x1(0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
test::check_container(x1, x2);
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.1\n";
|
||||
|
||||
std::cerr<<"assign_tests2.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -110,7 +95,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.1a\n";
|
||||
std::cerr<<"assign_tests2.1a\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -128,7 +113,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.2\n";
|
||||
std::cerr<<"assign_tests2.2\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -141,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));
|
||||
}
|
||||
@@ -150,7 +136,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.3\n";
|
||||
std::cerr<<"assign_tests2.3\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -163,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));
|
||||
}
|
||||
@@ -172,7 +159,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.4\n";
|
||||
std::cerr<<"assign_tests2.4\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -185,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));
|
||||
}
|
||||
@@ -195,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;
|
||||
}
|
||||
@@ -251,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)
|
||||
{
|
||||
std::cerr << "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;
|
||||
@@ -286,17 +285,18 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list)
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
UNORDERED_AUTO_TEST(assign_initializer_list)
|
||||
{
|
||||
std::cerr << "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()
|
||||
|
||||
@@ -3,22 +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;
|
||||
typedef boost::unordered_map<std::string, int>::iterator iterator;
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
|
||||
|
||||
@@ -35,11 +33,13 @@ UNORDERED_AUTO_TEST(at_tests)
|
||||
try {
|
||||
x.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()
|
||||
|
||||
@@ -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,61 +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())) {
|
||||
std::cerr << x.bucket_count() << "<=" << x.max_bucket_count() << "\n";
|
||||
}
|
||||
BOOST_TEST(x.bucket_count() < x.max_bucket_count());
|
||||
std::cerr<<x.bucket_count()<<"<"<<x.max_bucket_count()<<"\n";
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
|
||||
it = v.begin(),
|
||||
end = v.end();
|
||||
it != end; ++it) {
|
||||
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()
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
// 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"
|
||||
@@ -19,93 +17,99 @@
|
||||
|
||||
// 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);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
@@ -113,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);
|
||||
|
||||
std::cout << "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);
|
||||
@@ -157,13 +159,14 @@ UNORDERED_AUTO_TEST(test1)
|
||||
unordered_copyable_test(map2, value, map_value, hash, equal_to);
|
||||
unordered_map_functions(map2, value, value);
|
||||
|
||||
std::cout << "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);
|
||||
@@ -184,47 +187,45 @@ UNORDERED_AUTO_TEST(test2)
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::assignable>
|
||||
map_value_type;
|
||||
test::minimal::assignable> map_value_type;
|
||||
map_value_type map_value(assignable, assignable);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
// 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"
|
||||
@@ -19,22 +17,27 @@
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -42,61 +45,60 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
test::minimal::assignable assignable(x);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
@@ -104,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);
|
||||
@@ -128,13 +128,14 @@ UNORDERED_AUTO_TEST(test1)
|
||||
std::equal_to<int> equal_to;
|
||||
int value = 0;
|
||||
|
||||
std::cout << "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);
|
||||
@@ -144,13 +145,14 @@ UNORDERED_AUTO_TEST(test1)
|
||||
unordered_set_test(set2, value);
|
||||
unordered_copyable_test(set2, value, value, hash, equal_to);
|
||||
|
||||
std::cout << "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);
|
||||
@@ -164,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);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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)
|
||||
@@ -205,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);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
}
|
||||
@@ -238,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);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
}
|
||||
@@ -271,21 +271,21 @@ UNORDERED_AUTO_TEST(destructible_tests)
|
||||
test::minimal::hash<test::minimal::destructible> hash(x);
|
||||
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
|
||||
|
||||
std::cout << "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);
|
||||
|
||||
std::cout << "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);
|
||||
}
|
||||
|
||||
+112
-372
@@ -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,13 +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/static_assert.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;
|
||||
|
||||
@@ -30,28 +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(); }
|
||||
|
||||
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;
|
||||
|
||||
// value_type
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
|
||||
@@ -66,25 +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
|
||||
// TODO?
|
||||
|
||||
// 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
|
||||
|
||||
@@ -93,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);
|
||||
@@ -136,46 +120,16 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
|
||||
allocator_type m = a.get_allocator();
|
||||
sink(X(m));
|
||||
X c(m);
|
||||
sink(X(a_const, m));
|
||||
X c2(a_const, m);
|
||||
sink(X(rvalue(a_const), m));
|
||||
X c3(rvalue(a_const), m);
|
||||
|
||||
// node_type
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<allocator_type,
|
||||
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value));
|
||||
|
||||
node_type n1;
|
||||
node_type n2(rvalue_default<node_type>());
|
||||
node_type n3;
|
||||
n3 = boost::move(n2);
|
||||
n1.swap(n3);
|
||||
swap(n1, n3);
|
||||
|
||||
node_type const n_const;
|
||||
BOOST_TEST(n_const ? 0 : 1);
|
||||
test::check_return_type<bool>::equals(!n_const);
|
||||
test::check_return_type<bool>::equals(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;
|
||||
@@ -186,17 +140,16 @@ template <class X> void unordered_destructible_test(X&)
|
||||
#if !defined(BOOST_NO_CXX11_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());
|
||||
@@ -209,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());
|
||||
@@ -220,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>
|
||||
@@ -270,40 +188,8 @@ 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));
|
||||
|
||||
// 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));
|
||||
|
||||
@@ -313,25 +199,10 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
r.emplace(k, v);
|
||||
r.emplace(k_lvalue, v_lvalue);
|
||||
r.emplace(rvalue(k), rvalue(v));
|
||||
|
||||
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
|
||||
boost::make_tuple(v));
|
||||
|
||||
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());
|
||||
|
||||
r.insert(boost::move(n1));
|
||||
r.insert(r.end(), r.extract(r.begin()));
|
||||
}
|
||||
|
||||
template <class X> void equality_test(X& r)
|
||||
template <class X>
|
||||
void equality_test(X& r)
|
||||
{
|
||||
X const a = r, b = r;
|
||||
|
||||
@@ -341,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));
|
||||
@@ -378,29 +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.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));
|
||||
@@ -422,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));
|
||||
@@ -469,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> >();
|
||||
@@ -489,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);
|
||||
@@ -503,15 +348,6 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
X();
|
||||
X a4;
|
||||
|
||||
X(10, hf, eq, m);
|
||||
X a1a(10, hf, eq, m);
|
||||
X(10, hf, m);
|
||||
X a2a(10, hf, m);
|
||||
X(10, m);
|
||||
X a3a(10, m);
|
||||
(X(m));
|
||||
X a4a(m);
|
||||
|
||||
test::check_return_type<size_type>::equals(a.erase(k));
|
||||
|
||||
const_iterator q1 = a.cbegin(), q2 = a.cend();
|
||||
@@ -528,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));
|
||||
@@ -548,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>
|
||||
@@ -576,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);
|
||||
@@ -595,55 +418,17 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
X(i, j);
|
||||
X a8(i, j);
|
||||
|
||||
X(i, j, 10, hf, eq, m);
|
||||
X a5a(i, j, 10, hf, eq, m);
|
||||
X(i, j, 10, hf, m);
|
||||
X a6a(i, j, 10, hf, m);
|
||||
X(i, j, 10, m);
|
||||
X a7a(i, j, 10, m);
|
||||
|
||||
// Not specified for some reason (maybe ambiguity with another constructor?)
|
||||
// X(i, j, m);
|
||||
// X a8a(i, j, m);
|
||||
// sink(a8a);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
std::size_t min_buckets = 10;
|
||||
X({t});
|
||||
X({t}, min_buckets);
|
||||
X({t}, min_buckets, hf);
|
||||
X({t}, min_buckets, hf, eq);
|
||||
// X({t}, m);
|
||||
X({t}, min_buckets, m);
|
||||
X({t}, min_buckets, hf, m);
|
||||
X({t}, min_buckets, hf, eq, m);
|
||||
#endif
|
||||
|
||||
X const b;
|
||||
sink(X(b));
|
||||
X a9(b);
|
||||
a = b;
|
||||
|
||||
sink(X(b, m));
|
||||
X a9a(b, m);
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
|
||||
|
||||
a.insert(i, j);
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
std::initializer_list<T> list = {t};
|
||||
a.insert(list);
|
||||
a.insert({t, t, t});
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
||||
a.insert({});
|
||||
a.insert({t});
|
||||
a.insert({t, t});
|
||||
#endif
|
||||
#endif
|
||||
|
||||
X a10;
|
||||
a10.insert(t);
|
||||
@@ -658,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>
|
||||
@@ -676,7 +452,6 @@ 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)
|
||||
X x1(rvalue_default<X>());
|
||||
@@ -685,14 +460,9 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
||||
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);
|
||||
@@ -702,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();
|
||||
|
||||
@@ -726,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);
|
||||
|
||||
@@ -745,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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
std::cerr << "Construct 1\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 2\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 3\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 4\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 5\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 6\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 7\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 9\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 10\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 11\n";
|
||||
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);
|
||||
|
||||
std::cerr << "Construct 1\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 2\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 3\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 4\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 5\n";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 6\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 7\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8 - from input iterator\n";
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8.5 - from copy iterator\n";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 9\n";
|
||||
|
||||
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;
|
||||
|
||||
std::cerr << "Initializer list construct 1\n";
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 2\n";
|
||||
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));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 3\n";
|
||||
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));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 4\n";
|
||||
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));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 5\n";
|
||||
std::cerr<<"Initializer list construct 5\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -384,11 +383,14 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
template <class T>
|
||||
void map_constructor_test(T*, test::random_generator const& generator)
|
||||
{
|
||||
std::cerr << "map_constructor_test\n";
|
||||
std::cerr<<"map_constructor_test\n";
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type,
|
||||
BOOST_DEDUCED_TYPENAME T::mapped_type> >
|
||||
list;
|
||||
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());
|
||||
@@ -397,39 +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)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
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());
|
||||
@@ -439,15 +447,15 @@ UNORDERED_AUTO_TEST(test_default_initializer_list)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_initializer_list)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
+144
-128
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
@@ -27,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);
|
||||
@@ -39,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;
|
||||
@@ -61,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());
|
||||
}
|
||||
|
||||
@@ -6,24 +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
|
||||
@@ -31,46 +29,44 @@ struct write_pair_type
|
||||
template <class X1, class X2>
|
||||
void operator()(std::pair<X1, X2> const& x) const
|
||||
{
|
||||
std::cout << "(" << 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);
|
||||
std::cout << "\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.");
|
||||
std::cout << "Erase: [" << position << "," << position + length
|
||||
<< ")\n";
|
||||
std::cout<<"Erase: ["<<position<<","<<position + length<<")\n";
|
||||
write_container(init);
|
||||
write_container(y);
|
||||
}
|
||||
@@ -179,46 +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));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "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)
|
||||
{
|
||||
std::cout << "exhaustive_collide_tests:\n";
|
||||
std::cout<<"exhaustive_collide_tests:\n";
|
||||
collide_map m;
|
||||
exhaustive_erase_tests((collide_map*)0, 4, 4);
|
||||
std::cout << "\n";
|
||||
exhaustive_erase_tests((collide_map*) 0, 4, 4);
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
|
||||
{
|
||||
std::cout << "exhaustive_collide2_tests:\n";
|
||||
exhaustive_erase_tests((collide_map2*)0, 8, 4);
|
||||
std::cout << "\n";
|
||||
std::cout<<"exhaustive_collide2_tests:\n";
|
||||
exhaustive_erase_tests((collide_map2*) 0, 8, 4);
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
|
||||
{
|
||||
std::cout << "exhaustive_collide3_tests:\n";
|
||||
exhaustive_erase_tests((collide_map3*)0, 8, 4);
|
||||
std::cout << "\n";
|
||||
std::cout<<"exhaustive_collide3_tests:\n";
|
||||
exhaustive_erase_tests((collide_map3*) 0, 8, 4);
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
+77
-118
@@ -3,56 +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 <iostream>
|
||||
#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;
|
||||
|
||||
std::cerr << "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);
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "erase(begin()).\n";
|
||||
std::cerr<<"erase(begin()).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -60,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());
|
||||
}
|
||||
|
||||
std::cerr << "erase(random position).\n";
|
||||
std::cerr<<"erase(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -83,37 +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) {
|
||||
std::cerr << 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());
|
||||
}
|
||||
|
||||
std::cerr << "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);
|
||||
}
|
||||
|
||||
std::cerr << "erase(random ranges).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
Container x;
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
test::random_values<Container> v(1000, generator);
|
||||
x.insert(v.begin(), v.end());
|
||||
|
||||
// Note that erase only invalidates the erased iterators.
|
||||
std::vector<c_iterator> iterators;
|
||||
for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
|
||||
iterators.push_back(it);
|
||||
}
|
||||
iterators.push_back(x.cend());
|
||||
|
||||
while (iterators.size() > 1) {
|
||||
std::size_t start = test::random_value(iterators.size());
|
||||
std::size_t length =
|
||||
test::random_value(iterators.size() - start);
|
||||
x.erase(iterators[start], iterators[start + length]);
|
||||
iterators.erase(test::next(iterators.begin(), start),
|
||||
test::next(iterators.begin(), start + length));
|
||||
|
||||
BOOST_TEST(x.size() == iterators.size() - 1);
|
||||
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator
|
||||
i2 = iterators.begin();
|
||||
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
|
||||
BOOST_TEST(i1 == *i2);
|
||||
++i2;
|
||||
}
|
||||
BOOST_TEST(x.cend() == *i2);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "quick_erase(begin()).\n";
|
||||
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());
|
||||
}
|
||||
|
||||
std::cerr << "quick_erase(random position).\n";
|
||||
std::cerr<<"quick_erase(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -209,37 +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) {
|
||||
std::cerr << 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());
|
||||
}
|
||||
|
||||
std::cerr << "clear().\n";
|
||||
|
||||
std::cerr<<"clear().\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -250,25 +204,30 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
}
|
||||
|
||||
std::cerr << "\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()
|
||||
|
||||
@@ -1,140 +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>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace extract_tests {
|
||||
|
||||
test::seed_t initialize_seed(85638);
|
||||
|
||||
template <class Container>
|
||||
void extract_tests1(Container*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "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());
|
||||
}
|
||||
|
||||
std::cerr << "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());
|
||||
}
|
||||
|
||||
std::cerr << "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());
|
||||
}
|
||||
|
||||
std::cerr << "\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()
|
||||
@@ -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()
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
+124
-139
@@ -3,164 +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);
|
||||
|
||||
c1.x.insert(std::make_pair(c1, c1));
|
||||
c2.x.insert(std::make_pair(c2, c2));
|
||||
c3.x.insert(c3);
|
||||
c4.x.insert(c4);
|
||||
}
|
||||
};
|
||||
|
||||
// This is a dubious way to implement an allocator, but good enough
|
||||
// for this test.
|
||||
template <typename T> struct allocator : std::allocator<T>
|
||||
{
|
||||
allocator() {}
|
||||
// And finally define the operators required for comparing elements.
|
||||
|
||||
template <typename T2>
|
||||
allocator(const allocator<T2>& other) : std::allocator<T>(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
std::size_t hash_value(value const&) { return 0; }
|
||||
bool operator==(value const&, value const&) { return true; }
|
||||
|
||||
// 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()
|
||||
{
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,129 +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>
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_hint {
|
||||
UNORDERED_AUTO_TEST(insert_hint_empty)
|
||||
{
|
||||
typedef boost::unordered_multiset<int> container;
|
||||
container x;
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_empty2)
|
||||
{
|
||||
typedef boost::unordered_multimap<std::string, int> container;
|
||||
container x;
|
||||
x.emplace_hint(x.cbegin(), "hello", 50);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count("hello"), 1u);
|
||||
BOOST_TEST_EQ(x.find("hello")->second, 50);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_single)
|
||||
{
|
||||
typedef boost::unordered_multiset<std::string> container;
|
||||
container x;
|
||||
x.insert("equal");
|
||||
x.insert(x.cbegin(), "equal");
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count("equal"), 2u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_single2)
|
||||
{
|
||||
typedef boost::unordered_multimap<int, std::string> container;
|
||||
container x;
|
||||
x.emplace(10, "one");
|
||||
x.emplace_hint(x.cbegin(), 10, "two");
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count(10), 2u);
|
||||
|
||||
container::iterator it = x.find(10);
|
||||
std::string v0 = (it++)->second;
|
||||
std::string v1 = (it++)->second;
|
||||
|
||||
BOOST_TEST(v0 == "one" || v0 == "two");
|
||||
BOOST_TEST(v1 == "one" || v1 == "two");
|
||||
BOOST_TEST(v0 != v1);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_multiple)
|
||||
{
|
||||
for (unsigned int size = 0; size < 10; ++size) {
|
||||
for (unsigned int offset = 0; offset <= size; ++offset) {
|
||||
typedef boost::unordered_multiset<std::string> container;
|
||||
container x;
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
x.insert("multiple");
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ(x.size(), size);
|
||||
|
||||
container::const_iterator position = x.cbegin();
|
||||
for (unsigned int i = 0; i < offset; ++i) {
|
||||
++position;
|
||||
}
|
||||
|
||||
x.insert(position, "multiple");
|
||||
|
||||
BOOST_TEST_EQ(x.size(), size + 1u);
|
||||
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_unique)
|
||||
{
|
||||
typedef boost::unordered_set<int> container;
|
||||
container x;
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_hint_unique_single)
|
||||
{
|
||||
typedef boost::unordered_set<int> container;
|
||||
container x;
|
||||
x.insert(10);
|
||||
|
||||
x.insert(x.cbegin(), 10);
|
||||
BOOST_TEST_EQ(x.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
|
||||
x.insert(x.cbegin(), 20);
|
||||
BOOST_TEST_EQ(x.size(), 2u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
BOOST_TEST_EQ(x.count(20), 1u);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -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
|
||||
}
|
||||
@@ -3,36 +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"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_stable {
|
||||
struct member
|
||||
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
|
||||
@@ -41,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 now only supported when using grouped nodes. I can't see any
|
||||
// efficient way to do it otherwise.
|
||||
#if !BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
|
||||
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()
|
||||
|
||||
+200
-621
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,256 +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);
|
||||
}
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X> void merge_empty_test(X*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
X x1(v.begin(), v.end()), 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, 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 X> void unique_merge_test(X*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v1(1000, generator);
|
||||
test::random_values<X> v2(1000, generator);
|
||||
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
|
||||
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
|
||||
|
||||
X x1(v1.begin(), v1.end()), x2(v2.begin(), v2.end());
|
||||
x1.merge(x2);
|
||||
|
||||
test::ordered<X> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X> tracker2 = test::create_ordered(x2);
|
||||
test::ordered<X> tracker_tmp = test::create_ordered(x2);
|
||||
tracker1.insert(v1.begin(), v1.end());
|
||||
tracker_tmp.insert(v2.begin(), v2.end());
|
||||
for (BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator it =
|
||||
tracker_tmp.begin();
|
||||
it != tracker_tmp.end(); ++it) {
|
||||
if (!tracker1.insert(*it).second) {
|
||||
tracker2.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
tracker1.compare(x1);
|
||||
tracker2.compare(x2);
|
||||
test::check_equivalent_keys(x1);
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
|
||||
template <class X> void equiv_merge_test(X*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v1(1000, generator);
|
||||
test::random_values<X> v2(1000, generator);
|
||||
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
|
||||
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
|
||||
|
||||
X x1(v1.begin(), v1.end()), x2(v2.begin(), v2.end());
|
||||
x1.merge(x2);
|
||||
|
||||
test::ordered<X> tracker1 = test::create_ordered(x1);
|
||||
tracker1.insert(v1.begin(), v1.end());
|
||||
tracker1.insert(v2.begin(), v2.end());
|
||||
|
||||
tracker1.compare(x1);
|
||||
BOOST_TEST(x2.empty());
|
||||
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_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::movable, test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_multiset;
|
||||
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_map;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to, test::allocator1<test::object> >* test_multimap;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
|
||||
UNORDERED_TEST(merge_empty_test,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_multiset)(
|
||||
test_map)(test_multimap))((default_generator)(generate_collisions)))
|
||||
|
||||
UNORDERED_TEST(merge_into_empty_test,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_multiset)(
|
||||
test_map)(test_multimap))((default_generator)(generate_collisions)))
|
||||
|
||||
UNORDERED_TEST(unique_merge_test,
|
||||
((test_set_std_alloc)(test_set)(test_map))((default_generator)))
|
||||
|
||||
UNORDERED_TEST(equiv_merge_test, ((test_multimap_std_alloc)(test_multiset)(
|
||||
test_multimap))((default_generator)))
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -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
@@ -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_CXX11_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_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);
|
||||
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()
|
||||
|
||||
@@ -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()
|
||||
@@ -3,168 +3,123 @@
|
||||
// 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>
|
||||
namespace noexcept_tests
|
||||
{
|
||||
hash_possible_exception(hash_possible_exception const&) {}
|
||||
};
|
||||
|
||||
struct equal_to_possible_exception : std::equal_to<int>
|
||||
{
|
||||
equal_to_possible_exception(equal_to_possible_exception const&) {}
|
||||
};
|
||||
|
||||
// Test that the move constructor does actually move without throwing
|
||||
// an exception when it claims to.
|
||||
|
||||
struct test_exception
|
||||
{
|
||||
};
|
||||
|
||||
bool throwing_test_exception = false;
|
||||
void test_throw(char const* name)
|
||||
{
|
||||
if (throwing_test_exception) {
|
||||
std::cerr << "Throw exception in: " << name << std::endl;
|
||||
throw test_exception();
|
||||
}
|
||||
}
|
||||
|
||||
class hash_nothrow_move : boost::hash<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
|
||||
|
||||
typedef boost::hash<int> base;
|
||||
|
||||
public:
|
||||
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move)) BOOST_NOEXCEPT {}
|
||||
|
||||
hash_nothrow_move() { test_throw("Constructor"); }
|
||||
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
|
||||
hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
|
||||
// Test the noexcept is set correctly for the move constructor.
|
||||
|
||||
struct hash_possible_exception : boost::hash<int>
|
||||
{
|
||||
test_throw("Assign");
|
||||
return *this;
|
||||
}
|
||||
hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
|
||||
hash_possible_exception(hash_possible_exception const&) {}
|
||||
};
|
||||
|
||||
struct equal_to_possible_exception : std::equal_to<int>
|
||||
{
|
||||
test_throw("Move Assign");
|
||||
return *this;
|
||||
}
|
||||
std::size_t operator()(int x) const
|
||||
equal_to_possible_exception(equal_to_possible_exception const&) {}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(test_noexcept)
|
||||
{
|
||||
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);
|
||||
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
|
||||
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));
|
||||
#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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
// Test that the move constructor does actually move without throwing
|
||||
// an exception when it claims to.
|
||||
|
||||
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
|
||||
{
|
||||
typedef boost::unordered_set<int, hash_nothrow_move, equal_to_nothrow_move>
|
||||
throwing_set;
|
||||
struct test_exception {};
|
||||
|
||||
if (have_is_nothrow_move) {
|
||||
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
|
||||
bool throwing_test_exception = false;
|
||||
void test_throw(char const* name) {
|
||||
if (throwing_test_exception) {
|
||||
std::cerr << "Throw exception in: " << name << std::endl;
|
||||
throw test_exception();
|
||||
}
|
||||
}
|
||||
|
||||
throwing_test_exception = false;
|
||||
class hash_nothrow_move : boost::hash<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
|
||||
|
||||
throwing_set x1;
|
||||
x1.insert(10);
|
||||
x1.insert(50);
|
||||
typedef boost::hash<int> base;
|
||||
public:
|
||||
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
|
||||
BOOST_NOEXCEPT {}
|
||||
|
||||
try {
|
||||
throwing_test_exception = true;
|
||||
hash_nothrow_move() { test_throw("Constructor"); }
|
||||
hash_nothrow_move(hash_nothrow_move const& x) { test_throw("Copy"); }
|
||||
hash_nothrow_move& operator=(hash_nothrow_move const&)
|
||||
{ test_throw("Assign"); return *this; }
|
||||
std::size_t operator()(int x) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
|
||||
};
|
||||
|
||||
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);
|
||||
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& x)
|
||||
{ test_throw("Copy"); }
|
||||
equal_to_nothrow_move& operator=(equal_to_nothrow_move const&)
|
||||
{ test_throw("Assign"); return *this; }
|
||||
std::size_t operator()(int x, int y) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
|
||||
{
|
||||
typedef boost::unordered_set<int,
|
||||
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
throwing_test_exception = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -5,19 +5,18 @@
|
||||
|
||||
// This test checks the runtime requirements of containers.
|
||||
|
||||
// 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 <cstdlib>
|
||||
#include <algorithm>
|
||||
#include "../helpers/equivalent.hpp"
|
||||
|
||||
template <class X> void simple_test(X const& a)
|
||||
template <class X>
|
||||
void simple_test(X const& a)
|
||||
{
|
||||
test::unordered_equivalence_tester<X> equivalent(a);
|
||||
|
||||
@@ -73,8 +72,9 @@ template <class X> void simple_test(X const& a)
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST(a.size() == static_cast<BOOST_DEDUCED_TYPENAME X::size_type>(
|
||||
std::distance(a.begin(), a.end())));
|
||||
BOOST_TEST(a.size() ==
|
||||
static_cast<BOOST_DEDUCED_TYPENAME X::size_type>(
|
||||
std::distance(a.begin(), a.end())));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -93,40 +93,38 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
using namespace std;
|
||||
srand(14878);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
boost::unordered_set<int> set;
|
||||
simple_test(set);
|
||||
|
||||
set.insert(1);
|
||||
set.insert(2);
|
||||
set.insert(1456);
|
||||
set.insert(1); set.insert(2); set.insert(1456);
|
||||
simple_test(set);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
boost::unordered_multiset<int> multiset;
|
||||
simple_test(multiset);
|
||||
|
||||
for (int i1 = 0; i1 < 1000; ++i1) {
|
||||
|
||||
for(int i1 = 0; i1 < 1000; ++i1) {
|
||||
int count = rand() % 10, index = rand();
|
||||
for (int j = 0; j < count; ++j)
|
||||
for(int j = 0; j < count; ++j)
|
||||
multiset.insert(index);
|
||||
}
|
||||
simple_test(multiset);
|
||||
|
||||
std::cout << "Test unordered_map.\n";
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
boost::unordered_map<int, int> map;
|
||||
|
||||
for (int i2 = 0; i2 < 1000; ++i2) {
|
||||
for(int i2 = 0; i2 < 1000; ++i2) {
|
||||
map.insert(std::pair<const int, int>(rand(), rand()));
|
||||
}
|
||||
simple_test(map);
|
||||
|
||||
std::cout << "Test unordered_multimap.\n";
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
boost::unordered_multimap<int, int> multimap;
|
||||
|
||||
for (int i3 = 0; i3 < 1000; ++i3) {
|
||||
for(int i3 = 0; i3 < 1000; ++i3) {
|
||||
int count = rand() % 10, index = rand();
|
||||
for (int j = 0; j < count; ++j)
|
||||
for(int j = 0; j < count; ++j)
|
||||
multimap.insert(std::pair<const int, int>(index, rand()));
|
||||
}
|
||||
simple_test(multimap);
|
||||
|
||||
@@ -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 <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
@@ -21,14 +19,16 @@
|
||||
#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 swap_tests {
|
||||
namespace swap_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(783472);
|
||||
|
||||
template <class X> void swap_test_impl(X& x1, X& x2)
|
||||
template <class X>
|
||||
void swap_test_impl(X& x1, X& x2)
|
||||
{
|
||||
test::ordered<X> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X> tracker2 = test::create_ordered(x2);
|
||||
@@ -39,7 +39,8 @@ template <class X> void swap_test_impl(X& x1, X& x2)
|
||||
tracker2.compare(x1);
|
||||
}
|
||||
|
||||
template <class X> void swap_tests1(X*, test::random_generator generator)
|
||||
template <class X>
|
||||
void swap_tests1(X*, test::random_generator generator)
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
@@ -51,7 +52,7 @@ template <class X> void swap_tests1(X*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x, y;
|
||||
X x,y;
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
|
||||
@@ -74,7 +75,8 @@ template <class X> void swap_tests1(X*, test::random_generator generator)
|
||||
}
|
||||
}
|
||||
|
||||
template <class X> void swap_tests2(X* ptr, test::random_generator generator)
|
||||
template <class X>
|
||||
void swap_tests2(X* ptr, test::random_generator generator)
|
||||
{
|
||||
swap_tests1(ptr, generator);
|
||||
|
||||
@@ -119,7 +121,8 @@ template <class X> void swap_tests2(X* ptr, test::random_generator generator)
|
||||
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
|
||||
|
||||
if (allocator_type::is_propagate_on_swap ||
|
||||
x.get_allocator() == y.get_allocator()) {
|
||||
x.get_allocator() == y.get_allocator())
|
||||
{
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
}
|
||||
@@ -136,60 +139,73 @@ template <class X> void swap_tests2(X* ptr, test::random_generator generator)
|
||||
allocator_type(2));
|
||||
|
||||
if (allocator_type::is_propagate_on_swap ||
|
||||
x.get_allocator() == y.get_allocator()) {
|
||||
x.get_allocator() == y.get_allocator())
|
||||
{
|
||||
swap_test_impl(x, y);
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||
std::allocator<test::object> >* test_map_std_alloc;
|
||||
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::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;
|
||||
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;
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_set_prop_swap;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_multiset_prop_swap;
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_map_prop_swap;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_multimap_prop_swap;
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
test_set_no_prop_swap;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
test_multiset_no_prop_swap;
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
test_map_no_prop_swap;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
|
||||
test_multimap_no_prop_swap;
|
||||
|
||||
template <typename T> bool is_propagate(T*)
|
||||
template <typename T>
|
||||
bool is_propagate(T*)
|
||||
{
|
||||
return T::allocator_type::is_propagate_on_swap;
|
||||
}
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
UNORDERED_AUTO_TEST(check_traits)
|
||||
{
|
||||
@@ -198,19 +214,22 @@ UNORDERED_AUTO_TEST(check_traits)
|
||||
BOOST_TEST(!is_propagate(test_set_no_prop_swap));
|
||||
}
|
||||
|
||||
UNORDERED_TEST(swap_tests1,
|
||||
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
|
||||
test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(
|
||||
test_multimap_prop_swap)(test_set_no_prop_swap)(
|
||||
test_multiset_no_prop_swap)(test_map_no_prop_swap)(
|
||||
test_multimap_no_prop_swap))(
|
||||
(default_generator)(generate_collisions)(limited_range)))
|
||||
UNORDERED_TEST(swap_tests1, (
|
||||
(test_map_std_alloc)
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
)
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(swap_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
|
||||
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
|
||||
)
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(swap_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_swap)(
|
||||
test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)(
|
||||
test_set_no_prop_swap)(test_multiset_no_prop_swap)(
|
||||
test_map_no_prop_swap)(test_multimap_no_prop_swap))(
|
||||
(default_generator)(generate_collisions)(limited_range)))
|
||||
}
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -3,110 +3,109 @@
|
||||
// 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 <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
namespace unnecessary_copy_tests {
|
||||
struct count_copies
|
||||
namespace unnecessary_copy_tests
|
||||
{
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(count_copies)
|
||||
public:
|
||||
static int copies;
|
||||
static int moves;
|
||||
static int id_count;
|
||||
|
||||
count_copies() : tag_(0), id_(++id_count)
|
||||
struct count_copies
|
||||
{
|
||||
++copies;
|
||||
trace_op("Default construct");
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(count_copies)
|
||||
public:
|
||||
static int copies;
|
||||
static int moves;
|
||||
static int id_count;
|
||||
|
||||
count_copies() : tag_(0), id_(++id_count) {
|
||||
++copies;
|
||||
trace_op("Default construct");
|
||||
}
|
||||
|
||||
explicit count_copies(int tag) : tag_(tag), id_(++id_count) {
|
||||
++copies;
|
||||
trace_op("Tag construct");
|
||||
}
|
||||
|
||||
// This bizarre constructor is an attempt to confuse emplace.
|
||||
//
|
||||
// unordered_map<count_copies, count_copies> x:
|
||||
// x.emplace(count_copies(1), count_copies(2));
|
||||
// x.emplace(count_copies(1), count_copies(2), count_copies(3));
|
||||
//
|
||||
// The first emplace should use the single argument constructor twice.
|
||||
// The second emplace should use the single argument contructor for
|
||||
// the key, and this constructor for the value.
|
||||
count_copies(count_copies const&, count_copies const& x)
|
||||
: tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Pair construct");
|
||||
}
|
||||
|
||||
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Copy construct");
|
||||
}
|
||||
|
||||
count_copies(BOOST_RV_REF(count_copies) x) :
|
||||
tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
x.tag_ = -1; ++moves;
|
||||
trace_op("Move construct");
|
||||
}
|
||||
|
||||
count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++copies;
|
||||
trace_op("Copy assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
count_copies& operator=(BOOST_RV_REF(count_copies) p) //Move assignment
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++moves;
|
||||
trace_op("Move assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
~count_copies() {
|
||||
trace_op("Destruct");
|
||||
}
|
||||
|
||||
void trace_op(char const* str) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_
|
||||
<< " (#" << id_ << ")" <<std::endl;
|
||||
}
|
||||
|
||||
int tag_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
bool operator==(count_copies const& x, count_copies const& y) {
|
||||
return x.tag_ == y.tag_;
|
||||
}
|
||||
|
||||
explicit count_copies(int tag) : tag_(tag), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Tag construct");
|
||||
template <class T>
|
||||
T source() {
|
||||
return T();
|
||||
}
|
||||
|
||||
// This bizarre constructor is an attempt to confuse emplace.
|
||||
//
|
||||
// unordered_map<count_copies, count_copies> x:
|
||||
// x.emplace(count_copies(1), count_copies(2));
|
||||
// x.emplace(count_copies(1), count_copies(2), count_copies(3));
|
||||
//
|
||||
// The first emplace should use the single argument constructor twice.
|
||||
// The second emplace should use the single argument contructor for
|
||||
// the key, and this constructor for the value.
|
||||
count_copies(count_copies const&, count_copies const& x)
|
||||
: tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Pair construct");
|
||||
void reset() {
|
||||
count_copies::copies = 0;
|
||||
count_copies::moves = 0;
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
||||
<< "\nReset\n" << std::endl;
|
||||
}
|
||||
|
||||
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
++copies;
|
||||
trace_op("Copy construct");
|
||||
}
|
||||
|
||||
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count)
|
||||
{
|
||||
x.tag_ = -1;
|
||||
++moves;
|
||||
trace_op("Move construct");
|
||||
}
|
||||
|
||||
count_copies& operator=(
|
||||
BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++copies;
|
||||
trace_op("Copy assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment
|
||||
{
|
||||
tag_ = p.tag_;
|
||||
++moves;
|
||||
trace_op("Move assign");
|
||||
return *this;
|
||||
}
|
||||
|
||||
~count_copies() { trace_op("Destruct"); }
|
||||
|
||||
void trace_op(char const* str)
|
||||
{
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_
|
||||
<< ")" << std::endl;
|
||||
}
|
||||
|
||||
int tag_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
bool operator==(count_copies const& x, count_copies const& y)
|
||||
{
|
||||
return x.tag_ == y.tag_;
|
||||
}
|
||||
|
||||
template <class T> T source() { return T(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
count_copies::copies = 0;
|
||||
count_copies::moves = 0;
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\nReset\n" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
@@ -115,428 +114,380 @@ namespace boost
|
||||
namespace unnecessary_copy_tests
|
||||
#endif
|
||||
{
|
||||
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
|
||||
{
|
||||
return static_cast<std::size_t>(x.tag_);
|
||||
}
|
||||
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x) {
|
||||
return x.tag_;
|
||||
}
|
||||
}
|
||||
|
||||
// Boost.Move doesn't seem to work very well on this compiler.
|
||||
// For example for:
|
||||
//
|
||||
// T x;
|
||||
//
|
||||
// It will default construct T, and then move it in.
|
||||
// For 'T const' it seems to copy.
|
||||
|
||||
#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
|
||||
#define EXTRA_CONSTRUCT_COST 1
|
||||
#else
|
||||
#define EXTRA_CONSTRUCT_COST 0
|
||||
#endif
|
||||
|
||||
#define COPY_COUNT(n) \
|
||||
if (::unnecessary_copy_tests::count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr << "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
#define COPY_COUNT(n) \
|
||||
if(::unnecessary_copy_tests::count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT(n) \
|
||||
if (::unnecessary_copy_tests::count_copies::moves != n) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr << "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
#define MOVE_COUNT(n) \
|
||||
if(::unnecessary_copy_tests::count_copies::moves != n) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: " <<n << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_RANGE(a, b) \
|
||||
if (::unnecessary_copy_tests::count_copies::copies < a || \
|
||||
::unnecessary_copy_tests::count_copies::copies > b) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr << "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
#define COPY_COUNT_RANGE(a, b) \
|
||||
if(::unnecessary_copy_tests::count_copies::copies < a || \
|
||||
::unnecessary_copy_tests::count_copies::copies > b) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT_RANGE(a, b) \
|
||||
if (::unnecessary_copy_tests::count_copies::moves < a || \
|
||||
::unnecessary_copy_tests::count_copies::moves > b) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr << "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
#define MOVE_COUNT_RANGE(a, b) \
|
||||
if(::unnecessary_copy_tests::count_copies::moves < a || \
|
||||
::unnecessary_copy_tests::count_copies::moves > b) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
#define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
|
||||
namespace unnecessary_copy_tests {
|
||||
int count_copies::copies;
|
||||
int count_copies::moves;
|
||||
int count_copies::id_count;
|
||||
|
||||
template <class T> void unnecessary_copy_insert_test(T*)
|
||||
namespace unnecessary_copy_tests
|
||||
{
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
reset();
|
||||
x.insert(a);
|
||||
COPY_COUNT(1);
|
||||
}
|
||||
int count_copies::copies;
|
||||
int count_copies::moves;
|
||||
int count_copies::id_count;
|
||||
|
||||
boost::unordered_set<count_copies>* set;
|
||||
boost::unordered_multiset<count_copies>* multiset;
|
||||
boost::unordered_map<int, count_copies>* map;
|
||||
boost::unordered_multimap<int, count_copies>* multimap;
|
||||
template <class T>
|
||||
void unnecessary_copy_insert_test(T*)
|
||||
{
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
reset();
|
||||
x.insert(a);
|
||||
COPY_COUNT(1);
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
|
||||
boost::unordered_set<count_copies>* set;
|
||||
boost::unordered_multiset<count_copies>* multiset;
|
||||
boost::unordered_map<int, count_copies>* map;
|
||||
boost::unordered_multimap<int, count_copies>* multimap;
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
x.emplace(a);
|
||||
COPY_COUNT(2);
|
||||
}
|
||||
UNORDERED_TEST(unnecessary_copy_insert_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
x.emplace(a);
|
||||
COPY_COUNT(2);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_rvalue_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1);
|
||||
COPY_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT(2);
|
||||
COPY_COUNT(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(
|
||||
unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_move_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class T> void unnecessary_copy_emplace_std_move_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
x.emplace(std::move(a));
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1);
|
||||
}
|
||||
|
||||
UNORDERED_TEST(
|
||||
unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap)))
|
||||
#endif
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT_EXTRA(0, 1);
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1);
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#else
|
||||
// Since std::pair isn't movable, move only works for sets.
|
||||
COPY_COUNT_RANGE(1, 2);
|
||||
MOVE_COUNT_RANGE(0, 1);
|
||||
// Since std::pair isn't movable, move only works for sets.
|
||||
COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_TEST(
|
||||
unnecessary_copy_emplace_boost_move_test, ((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1);
|
||||
}
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_boost_move_set_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test,
|
||||
((set)(multiset)))
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT_EXTRA(0, 1);
|
||||
x.emplace(boost::move(a));
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_boost_move_map_test(T*)
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT_EXTRA(0, 1);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1);
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test,
|
||||
((map)(multimap)))
|
||||
|
||||
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
||||
{
|
||||
// When calling 'source' the object is moved on some compilers, but not
|
||||
// others. So count that here to adjust later.
|
||||
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
||||
{
|
||||
// When calling 'source' the object is moved on some compilers, but not
|
||||
// others. So count that here to adjust later.
|
||||
|
||||
reset();
|
||||
source<count_copies>();
|
||||
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
reset();
|
||||
source<count_copies>();
|
||||
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
reset();
|
||||
boost::unordered_set<count_copies> x;
|
||||
count_copies a;
|
||||
x.insert(a);
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(0);
|
||||
reset();
|
||||
boost::unordered_set<count_copies> x;
|
||||
count_copies a;
|
||||
x.insert(a);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 0 arguments
|
||||
//
|
||||
//
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(source_cost);
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#else
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1 + source_cost);
|
||||
COPY_COUNT(1); MOVE_COUNT(1 + source_cost);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// 1 argument
|
||||
//
|
||||
//
|
||||
// 1 argument
|
||||
//
|
||||
|
||||
// Emplace should be able to tell that there already is an element
|
||||
// without creating a new one.
|
||||
reset();
|
||||
x.emplace(a);
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
// Emplace should be able to tell that there already is an element
|
||||
// without creating a new one.
|
||||
reset();
|
||||
x.emplace(a);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
// A new object is created by source, but it shouldn't be moved or
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(source_cost);
|
||||
// A new object is created by source, but it shouldn't be moved or
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(1);
|
||||
COPY_COUNT(0); MOVE_COUNT(1);
|
||||
#endif
|
||||
|
||||
// Use a new value for cases where a did get moved...
|
||||
count_copies b;
|
||||
// Use a new value for cases where a did get moved...
|
||||
count_copies b;
|
||||
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace(b.tag_);
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace(b.tag_);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
|
||||
// The container will have to create b copy in order to compare with
|
||||
// the existing element.
|
||||
//
|
||||
// Note to self: If copy_count == 0 it's an error not an optimization.
|
||||
// TODO: Devise a better test.
|
||||
// The container will have to create b copy in order to compare with
|
||||
// the existing element.
|
||||
//
|
||||
// Note to self: If copy_count == 0 it's an error not an optimization.
|
||||
// TODO: Devise a better test.
|
||||
|
||||
reset();
|
||||
reset();
|
||||
|
||||
x.emplace(b, b);
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
}
|
||||
x.emplace(b, b);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
|
||||
{
|
||||
// When calling 'source' the object is moved on some compilers, but not
|
||||
// others. So count that here to adjust later.
|
||||
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
|
||||
{
|
||||
// When calling 'source' the object is moved on some compilers, but not
|
||||
// others. So count that here to adjust later.
|
||||
|
||||
reset();
|
||||
source<count_copies>();
|
||||
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
reset();
|
||||
source<count_copies>();
|
||||
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
|
||||
reset();
|
||||
source<std::pair<count_copies, count_copies> >();
|
||||
int source_pair_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
reset();
|
||||
source<std::pair<count_copies, count_copies> >();
|
||||
int source_pair_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
reset();
|
||||
boost::unordered_map<count_copies, count_copies> x;
|
||||
// TODO: Run tests for pairs without const etc.
|
||||
std::pair<count_copies const, count_copies> a;
|
||||
x.emplace(a);
|
||||
COPY_COUNT_EXTRA(4, 1);
|
||||
MOVE_COUNT_EXTRA(0, 1);
|
||||
reset();
|
||||
boost::unordered_map<count_copies, count_copies> x;
|
||||
// TODO: Run tests for pairs without const etc.
|
||||
std::pair<count_copies const, count_copies> a;
|
||||
x.emplace(a);
|
||||
COPY_COUNT(4); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 0 arguments
|
||||
//
|
||||
//
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
|
||||
// This is a little odd, Visual C++ 11 seems to move the pair, which
|
||||
// results in one copy (for the const key) and one move (for the
|
||||
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
|
||||
// has the normal result, it must be some odd consequence of how
|
||||
// Visual C++ 11 handles calling move for default arguments.
|
||||
COPY_COUNT(3);
|
||||
MOVE_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT_EXTRA(2, 1);
|
||||
MOVE_COUNT_EXTRA(0, 1);
|
||||
#endif
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
|
||||
// This is a little odd, Visual C++ 11 seems to move the pair, which
|
||||
// results in one copy (for the const key) and one move (for the
|
||||
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
|
||||
// has the normal result, it must be some odd consequence of how
|
||||
// Visual C++ 11 handles calling move for default arguments.
|
||||
COPY_COUNT(3); MOVE_COUNT(1);
|
||||
# else
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
|
||||
boost::make_tuple());
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(0);
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(),
|
||||
boost::make_tuple());
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 1 argument
|
||||
//
|
||||
|
||||
reset();
|
||||
x.emplace(a);
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
//
|
||||
// 1 argument
|
||||
//
|
||||
|
||||
// A new object is created by source, but it shouldn't be moved or
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(source_pair_cost);
|
||||
reset();
|
||||
x.emplace(a);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
|
||||
!(defined(_MSC_VER) && _MSC_VER < 1600)
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
x.emplace(a_ref);
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(0);
|
||||
// A new object is created by source, but it shouldn't be moved or
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || \
|
||||
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
|
||||
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
x.emplace(a_ref);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
#endif
|
||||
|
||||
// No move should take place.
|
||||
// (since a is already in the container)
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
// No move should take place.
|
||||
// (since a is already in the container)
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
|
||||
reset();
|
||||
x.emplace(b.first, b.second);
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
reset();
|
||||
x.emplace(b.first, b.second);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(source<count_copies>(), source<count_copies>());
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(source_cost * 2);
|
||||
reset();
|
||||
x.emplace(source<count_copies>(), source<count_copies>());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_cost * 2);
|
||||
|
||||
// source<count_copies> creates a single copy.
|
||||
reset();
|
||||
x.emplace(b.first, source<count_copies>());
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(source_cost);
|
||||
// source<count_copies> creates a single copy.
|
||||
reset();
|
||||
x.emplace(b.first, source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
|
||||
reset();
|
||||
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
|
||||
COPY_COUNT(2);
|
||||
MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(boost::ref(b.first)),
|
||||
boost::make_tuple(boost::ref(b.second)));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
reset();
|
||||
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(boost::ref(b.first)),
|
||||
boost::make_tuple(boost::ref(b.second)));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::make_tuple(std::ref(b.first)),
|
||||
std::make_tuple(std::ref(b.second)));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::make_tuple(std::ref(b.first)),
|
||||
std::make_tuple(std::ref(b.second)));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
std::pair<count_copies const, count_copies> move_source_trial;
|
||||
reset();
|
||||
std::make_tuple(std::move(move_source_trial.first));
|
||||
std::make_tuple(std::move(move_source_trial.second));
|
||||
int tuple_move_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
int tuple_copy_cost = ::unnecessary_copy_tests::count_copies::copies;
|
||||
std::pair<count_copies const, count_copies> move_source_trial;
|
||||
reset();
|
||||
std::make_tuple(std::move(move_source_trial.first));
|
||||
std::make_tuple(std::move(move_source_trial.second));
|
||||
int tuple_move_cost = ::unnecessary_copy_tests::count_copies::moves;
|
||||
int tuple_copy_cost = ::unnecessary_copy_tests::count_copies::copies;
|
||||
|
||||
std::pair<count_copies const, count_copies> move_source;
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::make_tuple(std::move(move_source.first)),
|
||||
std::make_tuple(std::move(move_source.second)));
|
||||
COPY_COUNT(tuple_copy_cost);
|
||||
MOVE_COUNT(tuple_move_cost);
|
||||
std::pair<count_copies const, count_copies> move_source;
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::make_tuple(std::move(move_source.first)),
|
||||
std::make_tuple(std::move(move_source.second)));
|
||||
COPY_COUNT(tuple_copy_cost);
|
||||
MOVE_COUNT(tuple_move_cost);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
|
||||
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
|
||||
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
#if defined(__GNUC__) && __GNUC__ > 4 || \
|
||||
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
std::forward_as_tuple(b.first),
|
||||
std::forward_as_tuple(b.second));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
Reference in New Issue
Block a user