Compare commits

..

1 Commits

Author SHA1 Message Date
Beman Dawes 81d2bd284c 1.36.0
[SVN r48100]
2008-08-12 12:44:50 +00:00
116 changed files with 10186 additions and 29760 deletions
-32
View File
@@ -1,32 +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://boost.org/LICENSE_1_0.txt)
version: 1.0.{build}-{branch}
shallow_clone: true
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0,msvc-14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
install:
- set BOOST_ROOT=c:\projects\boost
- cd c:\projects\
- python %APPVEYOR_BUILD_FOLDER%\ci\download-boost-snapshot.py master
- rd /s /q %BOOST_ROOT%\boost\unordered
- cd %BOOST_ROOT%\tools\build
- cmd /c bootstrap
- cd %APPVEYOR_BUILD_FOLDER%
- echo. 2>Jamroot.jam
build: off
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\test
- cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT%
-7
View File
@@ -1,7 +0,0 @@
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
[*.?pp]
indent_size = 2
-1
View File
@@ -1 +0,0 @@
/doc/html/
-87
View File
@@ -1,87 +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:
- libxml2-utils
- g++-multilib
matrix:
include:
- compiler: gcc
env: |
label="gcc C++03/11";
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address ;"
enable_coverage=1
CXXSTD=03,11
- compiler: gcc
env: |
label="gcc 32 bit C++11";
user_config="using gcc : : g++-4.8 -m32 -fsanitize=address ;"
CXXSTD=11
- compiler: clang
env: |
label="clang C++11/17";
user_config="using clang : : clang++ -fsanitize=address ;"
CXXSTD=11,17
# sanitized=address not available for 32-bit clang on travis.
- compiler: clang
env: |
label="clang 32 bit";
user_config="using clang : : clang++ -m32 ;"
CXXSTD=03
before_install:
- if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi
before_script:
- export BOOST_VERSION=1.67.0
- export BOOST_FILENAME=boost_1_67_0
- export BOOST_ROOT=${HOME}/boost
- cd ${TRAVIS_BUILD_DIR}
- touch Jamroot.jam
- cd $HOME
- echo $user_config > ~/user-config.jam
- cat ~/user-config.jam
- |
# Pick snapshot to use
if [ "$TRAVIS_EVENT_TYPE" == "cron" ]
then
if [ "$TRAVIS_BRANCH" == "master" ]
then
snapshot=master
else
snapshot=develop
fi
else
#snapshot=stable
snapshot=master
fi
# Download and extract snapshot
echo "Downloading ${download_url}"
mkdir $HOME/download
cd $HOME/download
python ${TRAVIS_BUILD_DIR}/ci/download-boost-snapshot.py $snapshot
mv * ${BOOST_ROOT}
- rm -r ${BOOST_ROOT}/boost/unordered
- cd ${BOOST_ROOT}/tools/build
- mkdir ${HOME}/opt
- bash bootstrap.sh
- ./b2 install --prefix=$HOME/opt
after_success:
if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi
script:
- cd ${TRAVIS_BUILD_DIR}/test
- ${HOME}/opt/bin/b2 -j 3 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
-38
View File
@@ -1,38 +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 4.0
# http://llvm.org/releases/4.0.0/tools/clang/docs/ClangFormatStyleOptions.html
# Becuase you have to start somewhere.
BasedOnStyle: LLVM
# Basic settings
ColumnLimit: 80
NamespaceIndentation: All
ContinuationIndentWidth: 2
IndentWidth: 2
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, UNORDERED_AUTO_TEST ]
-66
View File
@@ -1,66 +0,0 @@
#!/usr/bin/env python
import urllib, os, os.path, sys, json, tarfile, zipfile, tempfile
def download(snapshot):
if snapshot == 'stable':
# TODO: Default version/filename if not available?
downloads = [
"https://sourceforge.net/projects/boost/files/boost/%s/%s.tar.bz2/download" %
(os.environ['BOOST_VERSION'], os.environ['BOOST_FILENAME'])]
else:
json_response = urllib.urlopen('https://api.bintray.com/packages/boostorg/%s/snapshot/files' % (snapshot))
x = json.load(json_response)
extension_priorities = { '.bz2': 2, '.gz': 1, '.zip': 0 }
file_list = []
version_dates = {}
for file in x:
file_extension = os.path.splitext(file['path'])[1]
if (file_extension in extension_priorities):
file['priority'] = extension_priorities[file_extension]
file_list.append(file)
if not file['version'] in version_dates or file['created'] < version_dates[file['version']]:
version_dates[file['version']] = file['created']
file_list.sort(key=lambda x: (version_dates[x['version']], x['priority']), reverse=True)
downloads = ['http://dl.bintray.com/boostorg/%s/%s' % (snapshot, file['path']) for file in file_list]
filename = ''
for download_url in downloads:
try:
print "Downloading: " + download_url
(filename, headers) = urllib.urlretrieve(download_url)
print "Extracting: " + filename
dir = tempfile.mkdtemp()
extract(filename, dir)
os.remove(filename)
files = os.listdir(dir)
assert(len(files) == 1)
os.rename(os.path.join(dir, files[0]), 'boost')
return
except IOError:
print "Error opening URL: " + download_url
def extract(filename, path = '.'):
if (filename.endswith(".gz")):
tar = tarfile.open(filename, "r:gz")
tar.extractall(path)
tar.close
elif (filename.endswith(".bz2")):
tar = tarfile.open(filename, "r:bz2")
tar.extractall(path)
tar.close
elif (filename.endswith(".zip")):
zip = zipfile.ZipFile(filename, "r")
zip.extractall(path)
zip.close
else:
assert False
if len(sys.argv) == 1:
download('stable')
elif len(sys.argv) == 2:
download(sys.argv[1])
else:
print "Usage: %s [stable|branch-name]" % (sys.argv[0])
+14 -25
View File
@@ -3,16 +3,16 @@
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
using boostbook ;
using quickbook ;
path-constant images_location : ../ ;
path-constant admonishment_location : ../../../../doc/src/images ;
xml unordered : unordered.qbk :
<xsl:param>generate.consistent.ids=1 ;
xml unordered : unordered.qbk ;
boostbook standalone : unordered :
<xsl:param>admon.graphics.path=images/
<xsl:param>navig.graphics.path=images/
<xsl:param>html.stylesheet=boostbook.css
<xsl:param>boost.root=../../../..
<xsl:param>boost.libraries=../../../libraries.htm
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
<xsl:param>generate.section.toc.level=2
@@ -23,17 +23,10 @@ boostbook standalone : unordered :
<xsl:param>boost.compact.function=0
<xsl:param>boost.compact.enum=0
<xsl:param>generate.consistent.ids=1
# HTML Options:
<format>html:<xsl:param>boost.root=../../../..
<format>html:<xsl:param>img.src.path=../../../../doc/html/
<format>xhtml:<xsl:param>boost.root=../../../..
<format>xhtml:<xsl:param>img.src.path=../../../../doc/html/
<dependency>css
<dependency>images
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
<xsl:param>fop1.extensions=0
<format>pdf:<xsl:param>xep.extensions=1
@@ -58,15 +51,11 @@ boostbook standalone : unordered :
<format>pdf:<xsl:param>img.src.path=$(images_location)/
#<format>pdf:<xsl:param>admon.graphics.path=$(admonishment_location)
<format>pdf:<xsl:param>draft.mode="no"
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
;
###############################################################################
alias boostdoc
: unordered
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;
install css : [ glob $(BOOST_ROOT)/doc/src/*.css ]
: <location>html ;
install images : [ glob $(BOOST_ROOT)/doc/src/images/*.png ]
: <location>html/images ;
explicit css ;
explicit images ;
+1 -1
View File
@@ -1,5 +1,5 @@
<!--
Copyright Daniel James 2008-2009
Copyright Daniel James 2008
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)
-->
+11 -17
View File
@@ -17,7 +17,7 @@ the hash function, `Hash`, to the element's key (for `unordered_set` and
`unordered_multiset` the key is the whole element, but is referred to as the key
so that the same terminology can be used for sets and maps). This returns a
value of type `std::size_t`. `std::size_t` has a much greater range of values
then the number of buckets, so the container applies another transformation to
then the number of buckets, so that container applies another transformation to
that value to choose a bucket to place the element in.
Retrieving the elements for a given key is simple. The same process is applied
@@ -57,7 +57,7 @@ keep collisions to a minimum.
</row>
<row>
<entry>'''`size_type bucket(key_type const& k) const`'''</entry>
<entry>'''Returns the index of the bucket which would contain `k`.'''</entry>
<entry>'''Returns the index of the bucket which would contain k'''</entry>
</row>
<row>
<entry>'''`local_iterator begin(size_type n);`'''</entry>
@@ -92,7 +92,7 @@ You can also tell the container to change the bucket count (if required) by
calling `rehash`.
The standard leaves a lot of freedom to the implementer to decide how the
number of buckets is chosen, but it does make some requirements based on the
number of buckets are chosen, but it does make some requirements based on the
container's 'load factor', the average number of elements per bucket.
Containers also have a 'maximum load factor' which they should try to keep the
load factor below.
@@ -112,18 +112,9 @@ load factor is /required/ to be less than the maximum is following a call to
below the max load factor, and set the maximum load factor to be the same as
or close to the hint - unless your hint is unreasonably small or large.
[table:bucket_size Methods for Controlling Bucket Size
[table Methods for Controlling Bucket Size
[[Method] [Description]]
[
[`X(size_type n)`]
[Construct an empty container with at least `n` buckets (`X` is the container type).]
]
[
[`X(InputIterator i, InputIterator j, size_type n)`]
[Construct an empty container with at least `n` buckets and insert elements
from the range \[`i`, `j`) (`X` is the container type).]
]
[
[`float load_factor() const`]
[The average number of elements per bucket.]
@@ -138,7 +129,7 @@ or close to the hint - unless your hint is unreasonably small or large.
]
[
[`void rehash(size_type n)`]
[Changes the number of buckets so that there at least `n` buckets, and
[Changes the number of buckets so that there at least n buckets, and
so that the load factor is less than the maximum load factor.]
]
@@ -149,7 +140,7 @@ or close to the hint - unless your hint is unreasonably small or large.
It is not specified how member functions other than `rehash` affect
the bucket count, although `insert` is only allowed to invalidate iterators
when the insertion causes the load factor to be greater than or equal to the
maximum load factor. For most implementations this means that `insert` will only
maximum load factor. For most implementations this means that insert will only
change the number of buckets when this happens. While iterators can be
invalidated by calls to `insert` and `rehash`, pointers and references to the
container's elements are never invalidated.
@@ -160,9 +151,12 @@ the expensive rehashing out of the way and let you store iterators, safe in
the knowledge that they won't be invalidated. If you are inserting `n`
elements into container `x`, you could first call:
x.rehash((x.size() + n) / x.max_load_factor());
x.rehash((x.size() + n) / x.max_load_factor() + 1);
[blurb Note: `rehash`'s argument is the minimum number of buckets, not the
number of elements, which is why the new size is divided by the maximum load factor.]
number of elements, which is why the new size is divided by the maximum load factor. The
`+ 1` guarantees there is no invalidation; without it, reallocation could occur
if the number of bucket exactly divides the target size, since the container is
allowed to rehash when the load factor is equal to the maximum load factor.]
[endsect]
-324
View File
@@ -3,11 +3,6 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[template ticket[number]'''<ulink
url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
[template pull_request[number][@https://github.com/boostorg/unordered/pull/[number] GitHub #[number]]]
[section:changes Change Log]
[h2 Review Version]
@@ -38,323 +33,4 @@ First official release.
are available.
* Added equality operators.
[h2 Boost 1.37.0]
* Rename overload of `emplace` with hint, to `emplace_hint` as specified in
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2691.pdf n2691].
* Provide forwarding headers at `<boost/unordered/unordered_map_fwd.hpp>` and
`<boost/unordered/unordered_set_fwd.hpp>`.
* Move all the implementation inside `boost/unordered`, to assist
modularization and hopefully make it easier to track changes in subversion.
[h2 Boost 1.38.0]
* Use [@boost:/libs/core/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
Krügler.
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
Brönnimann.
* Use
[@boost:/libs/type_traits/doc/html/boost_typetraits/category/alignment.html
aligned storage] to store the types. This changes the way the allocator is
used to construct nodes. It used to construct the node with two calls to
the allocator's `construct` method - once for the pointers and once for the
value. It now constructs the node with a single call to construct and
then constructs the value using in place construction.
* Add support for C++0x initializer lists where they're available (currently
only g++ 4.4 in C++0x mode).
[h2 Boost 1.39.0]
* [@https://svn.boost.org/trac/boost/ticket/2756 Ticket 2756]: Avoid a warning
on Visual C++ 2009.
* Some other minor internal changes to the implementation, tests and
documentation.
* Avoid an unnecessary copy in `operator[]`.
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]: Fix length of
prime number list.
[h2 Boost 1.40.0]
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]:
Store the prime list as a preprocessor sequence - so that it will always get
the length right if it changes again in the future.
* [@https://svn.boost.org/trac/boost/ticket/1978 Ticket 1978]:
Implement `emplace` for all compilers.
* [@https://svn.boost.org/trac/boost/ticket/2908 Ticket 2908],
[@https://svn.boost.org/trac/boost/ticket/3096 Ticket 3096]:
Some workarounds for old versions of borland, including adding explicit
destructors to all containers.
* [@https://svn.boost.org/trac/boost/ticket/3082 Ticket 3082]:
Disable incorrect Visual C++ warnings.
* Better configuration for C++0x features when the headers aren't available.
* Create less buckets by default.
[h2 Boost 1.41.0 - Major update]
* The original version made heavy use of macros to sidestep some of the older
compilers' poor template support. But since I no longer support those
compilers and the macro use was starting to become a maintenance burden it
has been rewritten to use templates instead of macros for the implementation
classes.
* The container object is now smaller thanks to using `boost::compressed_pair`
for EBO and a slightly different function buffer - now using a bool instead
of a member pointer.
* Buckets are allocated lazily which means that constructing an empty container
will not allocate any memory.
[h2 Boost 1.42.0]
* Support instantiating the containers with incomplete value types.
* Reduced the number of warnings (mostly in tests).
* Improved codegear compatibility.
* [@http://svn.boost.org/trac/boost/ticket/3693 Ticket 3693]:
Add `erase_return_void` as a temporary workaround for the current
`erase` which can be inefficient because it has to find the next
element to return an iterator.
* Add templated find overload for compatible keys.
* [@http://svn.boost.org/trac/boost/ticket/3773 Ticket 3773]:
Add missing `std` qualifier to `ptrdiff_t`.
* Some code formatting changes to fit almost all lines into 80 characters.
[h2 Boost 1.43.0]
* [@http://svn.boost.org/trac/boost/ticket/3966 Ticket 3966]:
`erase_return_void` is now `quick_erase`, which is the
[@http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579
current forerunner for resolving the slow erase by iterator], although
there's a strong possibility that this may change in the future. The old
method name remains for backwards compatibility but is considered deprecated
and will be removed in a future release.
* Use Boost.Exception.
* Stop using deprecated `BOOST_HAS_*` macros.
[h2 Boost 1.45.0]
* Fix a bug when inserting into an `unordered_map` or `unordered_set` using
iterators which returns `value_type` by copy.
[h2 Boost 1.48.0 - Major update]
This is major change which has been converted to use Boost.Move's move
emulation, and be more compliant with the C++11 standard. See the
[link unordered.compliance compliance section] for details.
The container now meets C++11's complexity requirements, but to do so
uses a little more memory. This means that `quick_erase` and
`erase_return_void` are no longer required, they'll be removed in a
future version.
C++11 support has resulted in some breaking changes:
* Equality comparison has been changed to the C++11 specification.
In a container with equivalent keys, elements in a group with equal
keys used to have to be in the same order to be considered equal,
now they can be a permutation of each other. To use the old
behavior define the macro `BOOST_UNORDERED_DEPRECATED_EQUALITY`.
* The behaviour of swap is different when the two containers to be
swapped has unequal allocators. It used to allocate new nodes using
the appropriate allocators, it now swaps the allocators if
the allocator has a member structure `propagate_on_container_swap`,
such that `propagate_on_container_swap::value` is true.
* Allocator's `construct` and `destroy` functions are called with raw
pointers, rather than the allocator's `pointer` type.
* `emplace` used to emulate the variadic pair constructors that
appeared in early C++0x drafts. Since they were removed it no
longer does so. It does emulate the new `piecewise_construct`
pair constructors - only you need to use
`boost::piecewise_construct`. To use the old emulation of
the variadic constructors define
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
[h2 Boost 1.49.0]
* Fix warning due to accidental odd assignment.
* Slightly better error messages.
[h2 Boost 1.50.0]
* Fix equality for `unordered_multiset` and `unordered_multimap`.
* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
Implement `reserve`.
* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
Fix some Sun specific code.
* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
Avoid gcc's `-Wshadow` warning.
* [@https://svn.boost.org/trac/boost/ticket/6905 Ticket 6905]:
Make namespaces in macros compatible with `bcp` custom namespaces.
Fixed by Luke Elliott.
* Remove some of the smaller prime number of buckets, as they may make
collisions quite probable (e.g. multiples of 5 are very common because
we used base 10).
* On old versions of Visual C++, use the container library's implementation
of `allocator_traits`, as it's more likely to work.
* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas
Wang's hash function to pick which one to use. As modulus is very slow
for 64 bit values.
* Some internal changes.
[h2 Boost 1.51.0]
* Fix construction/destruction issue when using a C++11 compiler with a
C++03 allocator ([ticket 7100]).
* Remove a `try..catch` to support compiling without exceptions.
* Adjust SFINAE use to try to support g++ 3.4 ([ticket 7175]).
* Updated to use the new config macros.
[h2 Boost 1.52.0]
* Faster assign, which assigns to existing nodes where possible, rather than
creating entirely new nodes and copy constructing.
* Fixed bug in `erase_range` ([ticket 7471]).
* Reverted some of the internal changes to how nodes are created, especially
for C++11 compilers. 'construct' and 'destroy' should work a little better
for C++11 allocators.
* Simplified the implementation a bit. Hopefully more robust.
[h2 Boost 1.53.0]
* Remove support for the old pre-standard variadic pair constructors, and
equality implementation. Both have been deprecated since Boost 1.48.
* Remove use of deprecated config macros.
* More internal implementation changes, including a much simpler
implementation of `erase`.
[h2 Boost 1.54.0]
* Mark methods specified in standard as `noexpect`. More to come in the next
release.
* If the hash function and equality predicate are known to both have nothrow
move assignment or construction then use them.
[h2 Boost 1.55.0]
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
* Follow the standard by only using the allocators' construct and destroy
methods to construct and destroy stored elements. Don't use them for internal
data like pointers.
[h2 Boost 1.56.0]
* Fix some shadowed variable warnings ([ticket 9377]).
* Fix allocator use in documentation ([ticket 9719]).
* Always use prime number of buckets for integers. Fixes performance
regression when inserting consecutive integers, although makes other
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[h2 Boost 1.62.0]
* Remove use of deprecated `boost::iterator`.
* Remove `BOOST_NO_STD_DISTANCE` workaround.
* Remove `BOOST_UNORDERED_DEPRECATED_EQUALITY` warning.
* Simpler implementation of assignment, fixes an exception safety issue
for `unordered_multiset` and `unordered_multimap`. Might be a little slower.
* Stop using return value SFINAE which some older compilers have issues
with.
[h2 Boost 1.63.0]
* Check hint iterator in `insert`/`emplace_hint`.
* Fix some warnings, mostly in the tests.
* Manually write out `emplace_args` for small numbers of arguments -
should make template error messages a little more bearable.
* Remove superfluous use of `boost::forward` in emplace arguments,
which fixes emplacing string literals in old versions of Visual C++.
* Fix an exception safety issue in assignment. If bucket allocation
throws an exception, it can overwrite the hash and equality functions while
leaving the existing elements in place. This would mean that the function
objects wouldn't match the container elements, so elements might be in the
wrong bucket and equivalent elements would be incorrectly handled.
* Various reference documentation improvements.
* Better allocator support ([ticket 12459]).
* Make the no argument constructors implicit.
* Implement missing allocator aware constructors.
* Fix assigning the hash/key equality functions for empty containers.
* Remove unary/binary_function from the examples in the documentation.
They are removed in C++17.
* Support 10 constructor arguments in emplace. It was meant to support up to 10
arguments, but an off by one error in the preprocessor code meant it only
supported up to 9.
[h2 Boost 1.64.0]
* Initial support for new C++17 member functions:
`insert_or_assign` and `try_emplace` in `unordered_map`,
* Initial support for `merge` and `extract`.
Does not include transferring nodes between
`unordered_map` and `unordered_multimap` or between `unordered_set` and
`unordered_multiset` yet. That will hopefully be in the next version of
Boost.
[h2 Boost 1.65.0]
* Add deprecated attributes to `quick_erase` and `erase_return_void`.
I really will remove them in a future version this time.
* Small standards compliance fixes:
* `noexpect` specs for `swap` free functions.
* Add missing `insert(P&&)` methods.
[h2 Boost 1.66.0]
* Simpler move construction implementation.
* Documentation fixes ([pull_request 6]).
[h2 Boost 1.67.0]
* Improved C++17 support:
* Add template deduction guides from the standard.
* Use a simple implementation of `optional` in node handles, so
that they're closer to the standard.
* Add missing `noexcept` specifications to `swap`, `operator=`
and node handles, and change the implementation to match.
Using `std::allocator_traits::is_always_equal`, or our own
implementation when not available, and
`boost::is_nothrow_swappable` in the implementation.
* Improved C++20 support:
* Use `boost::to_address`, which has the proposed C++20 semantics,
rather than the old custom implementation.
* Add `element_type` to iterators, so that `std::pointer_traits`
will work.
* Use `std::piecewise_construct` on recent versions of Visual C++,
and other uses of the Dinkumware standard library,
now using Boost.Predef to check compiler and library versions.
* Use `std::iterator_traits` rather than the boost iterator traits
in order to remove dependency on Boost.Iterator.
* Remove iterators' inheritance from `std::iterator`, which is
deprecated in C++17, thanks to Daniela Engert
([@https://github.com/boostorg/unordered/pull/7 PR#7]).
* Stop using `BOOST_DEDUCED_TYPENAME`.
* Update some Boost include paths.
* Rename some internal methods, and variables.
* Various testing improvements.
* Miscellaneous internal changes.
[endsect]
+9 -6
View File
@@ -1,10 +1,10 @@
[/ Copyright 2006-2011 Daniel James.
[/ 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) ]
[section:comparison Comparison with Associative Containers]
[table:interface_differences Interface differences.
[table Interface differences.
[[Associative Containers] [Unordered Associative Containers]]
[
@@ -60,18 +60,21 @@
[Iterators iterate through the container in the order defined by
the comparison object.]
[Iterators iterate through the container in an arbitrary order, that
can change as elements are inserted, although equivalent elements
can change as elements are inserted. Although, equivalent elements
are always adjacent.]
]
[
[No equivalent]
[Local iterators can be used to iterate through individual buckets.
(The order of local iterators and iterators aren't
(I don't think that the order of local iterators and iterators are
required to have any correspondence.)]
]
[
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
[Can be compared using the `==` and `!=` operators.]
[No comparison operators are defined in the standard, although
[link unordered.rationale.equality_operators
implementations might extend the containers to support `==` and
`!=`].]
]
[
[]
@@ -85,7 +88,7 @@
]
]
[table:complexity_guarantees Complexity Guarantees
[table Complexity Guarantees
[[Operation] [Associative Containers] [Unordered Associative Containers]]
[
[Construction of empty container]
-128
View File
@@ -1,128 +0,0 @@
[/ Copyright 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) ]
[section:compliance Standard Compliance]
The intent of Boost.Unordered is to implement a close (but imperfect)
implementation of the C++17 standard, that will work with C++98 upwards.
The wide compatibility does mean some comprimises have to be made.
With a compiler and library that fully support C++11, the differences should
be minor.
[section:move Move emulation]
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Argument forwarding is not perfect.
[endsect]
[section:allocator_compliance Use of allocators]
C++11 introduced a new allocator system. It's backwards compatible due to
the lax requirements for allocators in the old standard, but might need
some changes for allocators which worked with the old versions of the
unordered containers.
It uses a traits class, `allocator_traits` to handle the allocator
adding extra functionality, and making some methods and types optional.
During development a stable release of
`allocator_traits` wasn't available so an internal partial implementation
is always used in this version. Hopefully a future version will use the
standard implementation where available.
The member functions `construct`, `destroy` and `max_size` are now
optional, if they're not available a fallback is used.
A full implementation of `allocator_traits` requires sophisticated
member function detection so that the fallback is used whenever the
member function call is not well formed.
This requires support for SFINAE expressions, which are available on
GCC from version 4.4 and Clang.
On other compilers, there's just a test to see if the allocator has
a member, but no check that it can be called. So rather than using a
fallback there will just be a compile error.
`propagate_on_container_copy_assignment`,
`propagate_on_container_move_assignment`,
`propagate_on_container_swap` and
`select_on_container_copy_construction` are also supported.
Due to imperfect move emulation, some assignments might check
`propagate_on_container_copy_assignment` on some compilers and
`propagate_on_container_move_assignment` on others.
[endsect]
[section:construction Construction/Destruction using allocators]
The following support is required for full use of C++11 style
construction/destruction:
* Variadic templates.
* Piecewise construction of `std::pair`.
* Either `std::allocator_traits` or expression SFINAE.
This is detected using Boost.Config. The macro
`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0
otherwise.
When this is the case `allocator_traits::construct` and
`allocator_traits::destroy` will always be used, apart from when piecewise
constructing a `std::pair` using `boost::tuple` (see [link
unordered.compliance.pairs below]), but that should be easily avoided.
When support is not available `allocator_traits::construct` and
`allocator_traits::destroy` are never called.
[endsect]
[section:pointer_traits Pointer Traits]
`pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators, this can cause problems if the allocator can't be
used with incomplete types. If `const_pointer` is not defined in the
allocator, `boost::pointer_to_other<pointer, const value_type>::type`
is used to obtain a const pointer.
[endsect]
[#unordered.compliance.pairs]
[section:pairs Pairs]
Since the containers use `std::pair` they're limited to the version
from the current standard library. But since C++11 `std::pair`'s
`piecewise_construct` based constructor is very useful, `emplace`
emulates it with a `piecewise_construct` in the `boost::unordered`
namespace. So for example, the following will work:
boost::unordered_multimap<std::string, std::complex> x;
x.emplace(
boost::unordered::piecewise_construct,
boost::make_tuple("key"), boost::make_tuple(1, 2));
Older drafts of the standard also supported variadic constructors
for `std::pair`, where the first argument would be used for the
first part of the pair, and the remaining for the second part.
[endsect]
[section:misc Miscellaneous]
When swapping, `Pred` and `Hash` are not currently swapped by calling
`swap`, their copy constructors are used. As a consequence when swapping
an exception may be thrown from their copy constructor.
Variadic constructor arguments for `emplace` are only used when both
rvalue references and variadic template parameters are available.
Otherwise `emplace` can only take up to 10 constructors arguments.
[endsect]
[endsect]
+5 -16
View File
@@ -13,7 +13,7 @@ is declared as:
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_map unordered_map]``;
The hash function comes first as you might want to change the hash function
@@ -23,7 +23,7 @@ but not the equality predicate. For example, if you wanted to use the
[import src_code/dictionary.cpp]
[case_sensitive_dictionary_fnv]
There is an [@boost:/libs/unordered/examples/fnv1.hpp implementation
There is an [@../../libs/unordered/examples/fnv1.hpp implementation
of FNV-1] in the examples directory.
If you wish to use a different equality function,
@@ -38,19 +38,9 @@ Which you can then use in a case insensitive dictionary:
[case_insensitive_dictionary]
This is a simplified version of the example at
[@boost:/libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
[@../../libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
which supports other locales and string types.
[caution
Be careful when using the equality (`==`) operator with custom equality
predicates, especially if you're using a function pointer. If you compare two
containers with different equality predicates then the result is undefined.
For most stateless function objects this is impossible - since you can only
compare objects with the same equality predicate you know the equality
predicates must be equal. But if you're using function pointers or a stateful
equality predicate (e.g. boost::function) then you can get into trouble.
]
[h2 Custom Types]
Similarly, a custom hash function can be used for custom types:
@@ -67,10 +57,9 @@ so that the hash function doesn't need to be explicitly given:
See the [link hash.custom Boost.Hash documentation] for more detail on how to
do this. Remember that it relies on extensions to the draft standard - so it
won't work for other implementations of the unordered associative containers,
you'll need to explicitly use Boost.Hash.
won't work on other implementations of the unordered associative containers.
[table:access_methods Methods for accessing the hash and equality functions.
[table Methods for accessing the hash and equality functions.
[[Method] [Description]]
[
+18 -7
View File
@@ -2,6 +2,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) ]
[def __tr1__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
C++ Standard Library Technical Report]]
[def __boost-tr1__
[@http://www.boost.org/doc/html/boost_tr1.html
Boost.TR1]]
[def __draft__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2461.pdf
Working Draft of the C++ Standard]]
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
hash table]]
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function
@@ -22,10 +31,12 @@ to order their elements. For some data types this is impossible to implement
or isn't practical. In contrast, a hash table only needs an equality function
and a hash function for the key.
With this in mind, unordered associative containers were added to the C++
standard. This is an implementation of the containers described in C++11,
with some [link unordered.compliance deviations from the standard] in
order to work with non-C++11 compilers and libraries.
With this in mind, the __tr1__ introduced the unordered associative containers,
which are implemented using hash tables, and they have now been added to the
__draft__.
This library supplies an almost complete implementation of the specification in
the __draft__.
`unordered_set` and `unordered_multiset` are defined in the header
<[headerref boost/unordered_set.hpp]>
@@ -54,14 +65,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]``;
}
@@ -84,7 +95,7 @@ can be in any order. For example, it might be:
one,1
three,3
To store an object in an unordered associative container requires both a
To store an object in an unordered associative container requires both an
key equality function and a hash function. The default function objects in
the standard containers support a few basic types including integer types,
floating point types, pointer types, and the standard strings. Since
+120 -28
View File
@@ -3,8 +3,14 @@
/ 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]]
[def __n2345__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2345.pdf
N2345, 'Placement Insert for Containers']]
[def __n2369__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2369.pdf
the August 2007 version of the working draft standard]]
[section:rationale Implementation Rationale]
@@ -13,7 +19,7 @@ containers in the draft standard, so the interface was fixed. But there are
still some implementation decisions to make. The priorities are
conformance to the standard and portability.
The [@http://en.wikipedia.org/wiki/Hash_table Wikipedia article on hash tables]
The [@http://en.wikipedia.org/wiki/Hash_table wikipedia article on hash tables]
has a good summary of the implementation issues for hash tables in general.
[h2 Data Structure]
@@ -23,7 +29,7 @@ standard pretty much requires that the hash table uses chained addressing.
It would be conceivable to write a hash table that uses another method. For
example, it could use open addressing, and use the lookup chain to act as a
bucket but there are some serious problems with this:
bucket but there are a some serious problems with this:
* The draft standard requires that pointers to elements aren't invalidated, so
the elements can't be stored in one array, but will need a layer of
@@ -44,8 +50,6 @@ bucket but there are some serious problems with this:
So chained addressing is used.
[/ (Removing for now as this is out of date)
For containers with unique keys I store the buckets in a single-linked list.
There are other possible data structures (such as a double-linked list)
that allow for some operations to be faster (such as erasing and iteration)
@@ -65,17 +69,6 @@ nodes in reverse order. This allows quick navigation to the end of a group (sinc
the first element points to the last) and can be quickly updated when elements
are inserted or erased. The main disadvantage of this approach is some hairy code
for erasing elements.
]
[/ (Starting to write up new structure, might not be ready in time)
The node used to be stored in a linked list for each bucket but that
didn't meet the complexity requirements for C++11, so now the nodes
are stored in one long single linked list. But there needs a way to get
the bucket from the node, to do that a copy of the key's hash value is
stored in the node. Another possibility would be to store a pointer to
the bucket, or the bucket's index, but storing the hash value allows
some operations to be faster.
]
[h2 Number of Buckets]
@@ -85,27 +78,126 @@ 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 losing the upper bits of the hash value.
to use, but at the expense of loosing the upper bits of the hash value.
For some specially designed hash functions it is possible to do this and
still get a good result but as the containers can take arbitrary hash
functions this can't be relied on.
To avoid this a transformation could be applied to the hash function, for an
example see __wang__. Unfortunately, a transformation like Wang's requires
knowledge of the number of bits in the hash value, so it isn't portable enough
to use as a default. It can applicable in certain cases so the containers
have a policy based implementation that can use this alternative technique.
knowledge of the number of bits in the hash value, so it isn't portable enough.
This leaves more expensive methods, such as Knuth's Multiplicative Method
(mentioned in Wang's article). These don't tend to work as well as taking the
modulus of a prime, and the extra computation required might negate
efficiency advantage of power of 2 hash tables.
Currently this is only done on 64 bit architectures, where prime number
modulus can be expensive. Although this varies depending on the architecture,
so I probably should revisit it.
So, this implementation uses a prime number for the hash table size.
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.
[h2 Equality operators]
`operator==` and `operator!=` are not included in the standard, but I've
added them as I think they could be useful and can be efficiently
implemented. They are specified
differently to the standard associative containers, comparing keys
using the equality predicate rather than `operator==`. This is inconsistent
with the other containers but it is probably closer to user's expectations.
[h2 Active Issues and Proposals]
[h3 Removing unused allocator functions]
In
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2257.html
N2257, removing unused allocator functions],
Matt Austern suggests removing the `construct`, `destroy` and `address` member
functions - all of which Boost.Unordered calls. Changing this will simplify the
implementation, as well as make supporting `emplace` easier, but means that the
containers won't support allocators which require these methods to be called.
Detlef Vollmann opposed this change in
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2339.htm N2339].
[h3 Swapping containers with unequal allocators]
It isn't clear how to swap containers when their allocators aren't equal.
This is
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431
Issue 431: Swapping containers with unequal allocators].
Howard Hinnant wrote about this in
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1599.html N1599]
and suggested swapping both the allocators and the containers' contents.
But the committee have now decided that `swap` should do a fast swap if the
allocator is Swappable and a slow swap using copy construction otherwise. To
make this distinction requires concepts.
In
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2387.pdf
N2387, Omnibus Allocator Fix-up Proposals],
Pablo Halpern suggests that there are actually two distinct allocator models,
"Moves with Value" and "Scoped" which behave differently:
[:
When allocators are allowed to have state, it is necessary to have a model for
determining from where an object obtains its allocator. Weve identified two such
models: the “Moves with Value” allocator model and the “Scoped” allocator model.
In the “Moves with Value” allocator model, the copy constructor of an allocator-aware
class will copy both the value and the allocator from its argument. This is the model
specified in the C++03 standard. With this model, inserting an object into a container
usually causes the new container item to copy the allocator from the object that was
inserted. This model can be useful in special circumstances, e.g., if the items within a
container use an allocator that is specially tuned to the items type.
In the “Scoped” allocator model, the allocator used to construct an object is determined
by the context of that object, much like a storage class. With this model, inserting an
object into a container causes the new container item to use the same allocator as the
container. To avoid allocators being used in the wrong context, the allocator is never
copied during copy or move construction. Thus, it is possible using this model to use
allocators based on short-lived resources without fear that an object will transfer its
allocator to a copy that might outlive the (shared) allocator resource. This model is
reasonably safe and generally useful on a large scale. There was strong support in the
2005 Tremblant meeting for pursuing an allocator model that propagates allocators
from container to contained objects.
]
With these models the choice becomes clearer:
[:
I introduced the “Moves with Value” allocator model and the
“Scoped” allocator model. In the former case, the allocator is copied when the container
is copy-constructed. In the latter case it is not. Swapping the allocators is the right thing
to do if the containers conform to the “Moves with Value” allocator model and
absolutely the wrong thing to do if the containers conform to the “Scoped” allocator
model. With the two allocator models well-defined, the desired behavior becomes clear.
]
The proposal is that allocators are swapped if the allocator follows the
"Moves with Value" model and the allocator is swappable. Otherwise a slow swap
is used. Since containers currently only support the "Moves with Value" model
this is consistent with the committee's current recommendation (although it
suggests using a trait to detect if the allocator is swappable rather than a
concept).
Since there is currently neither have a swappable trait or concept for
allocators this implementation always performs a slow swap.
[h3 Are insert and erase stable for unordered_multiset and unordered_multimap?]
It is not specified if `unordered_multiset` and `unordered_multimap` preserve the order
of elements with equivalent keys (i.e. if they're stable under `insert` and `erase`).
This is [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#518 issue 581].
The current proposal is that insert, erase and rehash are stable - so they are here.
(Update: during the release of this version, this requirement was added to
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
the lastest working draft]).
[h3 const_local_iterator cbegin, cend missing from TR1]
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2684.html#691
Issue 691] is that `cbegin` and `cend` are missing for local iterators.
The current resolution is that they'll be added, so I've added them.
[endsect]
-1788
View File
File diff suppressed because it is too large Load Diff
+171 -3067
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -4,12 +4,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered_map.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "../../examples/fnv1.hpp"
//[case_insensitive_functions
struct iequal_to
: std::binary_function<std::string, std::string, bool>
{
bool operator()(std::string const& x,
std::string const& y) const
@@ -19,6 +20,7 @@
};
struct ihash
: std::unary_function<std::string, std::size_t>
{
std::size_t operator()(std::string const& x) const
{
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
+3 -2
View File
@@ -1,10 +1,10 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include <boost/unordered_set.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/detail/lightweight_test.hpp>
//[point_example1
struct point {
@@ -18,6 +18,7 @@
}
struct point_hash
: std::unary_function<point, std::size_t>
{
std::size_t operator()(point const& p) const
{
+2 -2
View File
@@ -1,11 +1,11 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include <boost/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/detail/lightweight_test.hpp>
//[point_example2
struct point {
+2 -4
View File
@@ -3,8 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[library Boost.Unordered
[quickbook 1.7]
[compatibility-mode 1.5]
[quickbook 1.4]
[authors [James, Daniel]]
[copyright 2003 2004 Jeremy B. Maitin-Shepard]
[copyright 2005 2006 2007 2008 Daniel James]
@@ -14,7 +13,7 @@
[license
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])
[@http://www.boost.org/LICENSE_1_0.txt]
]
]
@@ -32,7 +31,6 @@
[include:unordered buckets.qbk]
[include:unordered hash_equality.qbk]
[include:unordered comparison.qbk]
[include:unordered compliance.qbk]
[include:unordered rationale.qbk]
[include:unordered changes.qbk]
[xinclude ref.xml]
+3 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
@@ -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) {}
+2 -2
View File
@@ -1,10 +1,10 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./case_insensitive.hpp"
#include <boost/core/lightweight_test.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/unordered_map.hpp>
struct word_info {
+4 -7
View File
@@ -1,5 +1,5 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -55,14 +55,11 @@ namespace hash
// For 128 bit machines:
// const std::size_t fnv_prime = 309485009821345068724781401u;
// const std::size_t fnv_offset_basis =
// 275519064689413815358837431229664493455u;
// const std::size_t fnv_offset_basis = 275519064689413815358837431229664493455u;
// For 256 bit machines:
// const std::size_t fnv_prime =
// 374144419156711147060143317175368453031918731002211u;
// const std::size_t fnv_offset_basis =
// 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
// const std::size_t fnv_prime = 374144419156711147060143317175368453031918731002211u;
// const std::size_t fnv_offset_basis = 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
typedef basic_fnv_1a<fnv_prime, fnv_offset_basis> fnv_1a;
@@ -0,0 +1,237 @@
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__)
# define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# include <boost/detail/allocator_utilities.hpp>
#endif
#include <boost/mpl/aux_/config/eti.hpp>
namespace boost {
namespace unordered_detail {
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <class Alloc, class T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
#else
template <class Alloc, class T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T>
inline void reset(T& x) { x = T(); }
template <class Ptr>
inline Ptr null_ptr() { return Ptr(); }
#else
template <class T>
inline void reset_impl(T& x, ...) { x = T(); }
template <class T>
inline void reset_impl(T*& x, int) { x = 0; }
template <class T>
inline void reset(T& x) { reset_impl(x); }
template <class Ptr>
inline Ptr null_ptr() { Ptr x; reset(x); return x; }
#endif
// Work around for Microsoft's ETI bug.
template <class Allocator> struct allocator_value_type
{
typedef BOOST_DEDUCED_TYPENAME Allocator::value_type type;
};
template <class Allocator> struct allocator_pointer
{
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer type;
};
template <class Allocator> struct allocator_const_pointer
{
typedef BOOST_DEDUCED_TYPENAME Allocator::const_pointer type;
};
template <class Allocator> struct allocator_reference
{
typedef BOOST_DEDUCED_TYPENAME Allocator::reference type;
};
template <class Allocator> struct allocator_const_reference
{
typedef BOOST_DEDUCED_TYPENAME Allocator::const_reference type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_value_type<int>
{
typedef int type;
};
template <>
struct allocator_pointer<int>
{
typedef int type;
};
template <>
struct allocator_const_pointer<int>
{
typedef int type;
};
template <>
struct allocator_reference<int>
{
typedef int type;
};
template <>
struct allocator_const_reference<int>
{
typedef int type;
};
#endif
template <class Allocator>
struct allocator_constructor
{
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Allocator>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
Allocator& alloc_;
pointer ptr_;
bool constructed_;
allocator_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(false)
{
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
unordered_detail::reset(ptr_);
#endif
}
~allocator_constructor() {
if(ptr_) {
if(constructed_) alloc_.destroy(ptr_);
alloc_.deallocate(ptr_, 1);
}
}
template <class V>
void construct(V const& v) {
BOOST_ASSERT(!ptr_ && !constructed_);
ptr_ = alloc_.allocate(1);
alloc_.construct(ptr_, value_type(v));
constructed_ = true;
}
void construct(value_type const& v) {
BOOST_ASSERT(!ptr_ && !constructed_);
ptr_ = alloc_.allocate(1);
alloc_.construct(ptr_, v);
constructed_ = true;
}
pointer get() const
{
return ptr_;
}
// no throw
pointer release()
{
pointer p = ptr_;
constructed_ = false;
unordered_detail::reset(ptr_);
return p;
}
};
template <class Allocator>
struct allocator_array_constructor
{
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
allocator_array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
unordered_detail::reset(constructed_);
unordered_detail::reset(ptr_);
#endif
}
~allocator_array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
alloc_.destroy(p);
alloc_.deallocate(ptr_, length_);
}
}
template <class V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = alloc_.allocate(length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
alloc_.construct(constructed_, v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
unordered_detail::reset(ptr_);
return p;
}
private:
allocator_array_constructor(allocator_array_constructor const&);
allocator_array_constructor& operator=(allocator_array_constructor const&);
};
}
}
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#endif
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_DETAIL_CONFIG_HEADER)
#define BOOST_UNORDERED_DETAIL_CONFIG_HEADER
#include <boost/config.hpp>
#if defined(BOOST_NO_SFINAE)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif defined(__GNUC__) && \
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#endif
#endif
-63
View File
@@ -1,63 +0,0 @@
// Copyright (C) 2008-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)
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/predef.h>
#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 BOOST_LIB_STD_CXX
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
#if BOOST_LIB_STD_CXX >= BOOST_VERSION_NUMBER(3, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif defined(BOOST_LIB_STD_DINKUMWARE)
// 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!
// I have no idea when Dinkumware added it, probably a lot
// earlier than this check.
#if BOOST_LIB_STD_DINKUMWARE >= BOOST_VERSION_NUMBER(6, 50, 0) || \
BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(17, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#endif
// Assume that an unknown library does not support piecewise construction.
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
#endif
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#include <utility>
#endif
namespace boost {
namespace unordered {
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
using std::piecewise_construct_t;
using std::piecewise_construct;
#else
struct piecewise_construct_t
{
};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
}
}
#endif
@@ -0,0 +1,307 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2008 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <cstddef>
#include <cmath>
#include <algorithm>
#include <utility>
#include <stdexcept>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/not.hpp>
#endif
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582)
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
#else
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
#define BOOST_UNORDERED_MSVC_RESET_PTR(x) unordered_detail::reset(x)
#else
#define BOOST_UNORDERED_MSVC_RESET_PTR(x)
#endif
namespace boost {
namespace unordered_detail {
template <class T> struct type_wrapper {};
static const std::size_t default_initial_bucket_count = 50;
static const float minimum_max_load_factor = 1e-3f;
template <class T>
inline void hash_swap(T& x, T& y)
{
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
std::swap(x,y);
#else
using std::swap;
swap(x, y);
#endif
}
inline std::size_t double_to_size_t(double f)
{
return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
(std::numeric_limits<std::size_t>::max)() :
static_cast<std::size_t>(f);
}
// prime number list, accessor
template<typename T> struct prime_list_template
{
static std::size_t const value[];
static std::ptrdiff_t const length;
};
template<typename T>
std::size_t const prime_list_template<T>::value[] = {
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul };
template<typename T>
std::ptrdiff_t const prime_list_template<T>::length = 28;
typedef prime_list_template<std::size_t> prime_list;
// no throw
inline std::size_t next_prime(std::size_t n) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::lower_bound(prime_list_begin, prime_list_end, n);
if(bound == prime_list_end)
bound--;
return *bound;
}
// no throw
inline std::size_t prev_prime(std::size_t n) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::upper_bound(prime_list_begin,prime_list_end, n);
if(bound != prime_list_begin)
bound--;
return *bound;
}
// Controls how many buckets are allocated and which buckets hash
// values map to. Does not contain the buckets themselves, or ever
// deal with them directly.
struct bucket_manager {
std::size_t bucket_count_;
bucket_manager()
: bucket_count_(0) {}
explicit bucket_manager(std::size_t n)
: bucket_count_(next_prime(n)) {}
std::size_t bucket_count() const {
return bucket_count_;
}
std::size_t bucket_from_hash(std::size_t hashed) const {
return hashed % bucket_count_;
}
std::size_t max_bucket_count(std::size_t max_size) const {
return prev_prime(max_size);
}
};
// pair_cast - used to convert between pair types.
template <class Dst1, class Dst2, class Src1, class Src2>
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
{
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
}
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
struct move_tag {};
// Both hasher and key_equal's copy/assign can throw so double
// buffering is used to copy them.
template <typename Hash, typename Pred>
struct buffered_functions
{
typedef Hash hasher;
typedef Pred key_equal;
class functions
{
std::pair<hasher, key_equal> functions_;
public:
functions(hasher const& h, key_equal const& k)
: functions_(h, k) {}
hasher const& hash_function() const
{
return functions_.first;
}
key_equal const& key_eq() const
{
return functions_.second;
}
};
typedef functions buffered_functions::*functions_ptr;
buffered_functions(hasher const& h, key_equal const& k)
: func1_(h, k), func2_(h, k), func_(&buffered_functions::func1_) {}
// This copies the given function objects into the currently unused
// function objects and returns a pointer, that func_ can later be
// set to, to commit the change.
//
// Strong exception safety (since only usued function objects are
// changed).
functions_ptr buffer(buffered_functions const& x) {
functions_ptr ptr = func_ == &buffered_functions::func1_
? &buffered_functions::func2_ : &buffered_functions::func1_;
this->*ptr = x.current();
return ptr;
}
void set(functions_ptr ptr) {
BOOST_ASSERT(ptr != func_);
func_ = ptr;
}
functions const& current() const {
return this->*func_;
}
private:
functions func1_;
functions func2_;
functions_ptr func_; // The currently active functions.
};
}
}
#define BOOST_UNORDERED_EQUIVALENT_KEYS 1
#include <boost/unordered/detail/hash_table_impl.hpp>
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
#define BOOST_UNORDERED_EQUIVALENT_KEYS 0
#include <boost/unordered/detail/hash_table_impl.hpp>
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
namespace boost {
namespace unordered_detail {
class iterator_access
{
public:
template <class Iterator>
static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
return it.base_;
}
};
template <class ValueType, class KeyType,
class Hash, class Pred, class Alloc>
class hash_types_unique_keys
{
public:
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
value_allocator;
typedef hash_table_unique_keys<ValueType, KeyType, Hash, Pred,
value_allocator> hash_table;
typedef hash_table_data_unique_keys<value_allocator> data;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
typedef hash_const_local_iterator_unique_keys<value_allocator> const_local_iterator;
typedef hash_local_iterator_unique_keys<value_allocator> local_iterator;
typedef hash_const_iterator_unique_keys<value_allocator> const_iterator;
typedef hash_iterator_unique_keys<value_allocator> iterator;
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
typedef std::ptrdiff_t difference_type;
};
template <class ValueType, class KeyType,
class Hash, class Pred, class Alloc>
class hash_types_equivalent_keys
{
public:
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
value_allocator;
typedef hash_table_equivalent_keys<ValueType, KeyType, Hash, Pred,
value_allocator> hash_table;
typedef hash_table_data_equivalent_keys<value_allocator> data;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
typedef hash_const_local_iterator_equivalent_keys<value_allocator> const_local_iterator;
typedef hash_local_iterator_equivalent_keys<value_allocator> local_iterator;
typedef hash_const_iterator_equivalent_keys<value_allocator> const_iterator;
typedef hash_iterator_equivalent_keys<value_allocator> iterator;
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
typedef std::ptrdiff_t difference_type;
};
} // namespace boost::unordered_detail
} // namespace boost
#undef BOOST_UNORDERED_BORLAND_BOOL
#undef BOOST_UNORDERED_MSVC_RESET_PTR
#endif // BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-67
View File
@@ -1,67 +0,0 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/implementation.hpp>
#include <boost/unordered/unordered_map_fwd.hpp>
namespace boost {
namespace unordered {
namespace detail {
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K const const_key_type;
typedef
typename ::boost::unordered::detail::rebind_wrap<A, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::map_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
typedef boost::unordered::insert_return_type_map<node, K, M, A>
insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map
{
typedef boost::unordered_map<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap
{
typedef boost::unordered_multimap<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
+228
View File
@@ -0,0 +1,228 @@
/*
Copyright 2005-2007 Adobe Systems Incorporated
Use, modification and distribution are subject to 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_MOVE_HEADER
#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/unordered/detail/config.hpp>
/*************************************************************************************************/
namespace boost {
namespace unordered_detail {
/*************************************************************************************************/
namespace move_detail {
/*************************************************************************************************/
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
/*************************************************************************************************/
template <typename T>
struct class_has_move_assign {
class type {
typedef T& (T::*E)(T t);
typedef char (&no_type)[1];
typedef char (&yes_type)[2];
template <E e> struct sfinae { typedef yes_type type; };
template <class U>
static typename sfinae<&U::operator=>::type test(int);
template <class U>
static no_type test(...);
public:
enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};
};
};
/*************************************************************************************************/
template<typename T>
struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
/*************************************************************************************************/
class test_can_convert_anything { };
/*************************************************************************************************/
#endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
/*************************************************************************************************/
/*
REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where
boost::is_convertible<T, T> fails to compile.
*/
template <typename T, typename U>
struct is_convertible : boost::mpl::or_<
boost::is_same<T, U>,
boost::is_convertible<T, U>
> { };
/*************************************************************************************************/
} //namespace move_detail
/*************************************************************************************************/
/*!
\ingroup move_related
\brief move_from is used for move_ctors.
*/
template <typename T>
struct move_from
{
explicit move_from(T& x) : source(x) { }
T& source;
};
/*************************************************************************************************/
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
/*************************************************************************************************/
/*!
\ingroup move_related
\brief The is_movable trait can be used to identify movable types.
*/
template <typename T>
struct is_movable : boost::mpl::and_<
boost::is_convertible<move_from<T>, T>,
move_detail::has_move_assign<T>,
boost::mpl::not_<boost::is_convertible<move_detail::test_can_convert_anything, T> >
> { };
/*************************************************************************************************/
#else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
// On compilers which don't have adequate SFINAE support, treat most types as unmovable,
// unless the trait is specialized.
template <typename T>
struct is_movable : boost::mpl::false_ { };
#endif
/*************************************************************************************************/
#if !defined(BOOST_NO_SFINAE)
/*************************************************************************************************/
/*!
\ingroup move_related
\brief copy_sink and move_sink are used to select between overloaded operations according to
whether type T is movable and convertible to type U.
\sa move
*/
template <typename T,
typename U = T,
typename R = void*>
struct copy_sink : boost::enable_if<
boost::mpl::and_<
boost::unordered_detail::move_detail::is_convertible<T, U>,
boost::mpl::not_<is_movable<T> >
>,
R
>
{ };
/*************************************************************************************************/
/*!
\ingroup move_related
\brief move_sink and copy_sink are used to select between overloaded operations according to
whether type T is movable and convertible to type U.
\sa move
*/
template <typename T,
typename U = T,
typename R = void*>
struct move_sink : boost::enable_if<
boost::mpl::and_<
boost::unordered_detail::move_detail::is_convertible<T, U>,
is_movable<T>
>,
R
>
{ };
/*************************************************************************************************/
/*!
\ingroup move_related
\brief This version of move is selected when T is_movable . It in turn calls the move
constructor. This call, with the help of the return value optimization, will cause x to be moved
instead of copied to its destination. See adobe/test/move/main.cpp for examples.
*/
template <typename T>
T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
/*************************************************************************************************/
/*!
\ingroup move_related
\brief This version of move is selected when T is not movable . The net result will be that
x gets copied.
*/
template <typename T>
T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
/*************************************************************************************************/
#else // BOOST_NO_SFINAE
// On compilers without SFINAE, define copy_sink to always use the copy function.
template <typename T,
typename U = T,
typename R = void*>
struct copy_sink
{
typedef R type;
};
// Always copy the element unless this is overloaded.
template <typename T>
T& move(T& x) {
return x;
}
#endif // BOOST_NO_SFINAE
} // namespace unordered_detail
} // namespace boost
/*************************************************************************************************/
#endif
/*************************************************************************************************/
-66
View File
@@ -1,66 +0,0 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/implementation.hpp>
#include <boost/unordered/unordered_set_fwd.hpp>
namespace boost {
namespace unordered {
namespace detail {
template <typename A, typename T, typename H, typename P> struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T const const_key_type;
typedef
typename ::boost::unordered::detail::rebind_wrap<A, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type;
typedef boost::unordered::insert_return_type_set<node, T, A>
insert_return_type;
};
template <typename T, typename H, typename P, typename A>
class instantiate_set
{
typedef boost::unordered_set<T, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename T, typename H, typename P, typename A>
class instantiate_multiset
{
typedef boost::unordered_multiset<T, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,64 +0,0 @@
// 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_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#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;
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class 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!=;
}
#endif
File diff suppressed because it is too large Load Diff
@@ -1,62 +0,0 @@
// 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_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#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;
template <class T, class H, class P, class A>
inline bool operator==(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(
unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class 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!=;
}
#endif
+809 -4
View File
@@ -9,11 +9,816 @@
#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>
#include <boost/config.hpp>
#include <functional>
#include <memory>
#include <boost/functional/hash.hpp>
#include <boost/unordered/detail/hash_table.hpp>
#if !defined(BOOST_HAS_RVALUE_REFS)
#include <boost/unordered/detail/move.hpp>
#endif
namespace boost
{
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_map;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
bool operator!=(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
void swap(unordered_multimap<K, T, H, P, A>&,
unordered_multimap<K, T, H, P, A>&);
template <class Key, class T, class Hash, class Pred, class Alloc>
class unordered_map
{
typedef boost::unordered_detail::hash_types_unique_keys<
std::pair<const Key, T>, Key, Hash, Pred, Alloc
> implementation;
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
public:
// types
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
// construct/destroy/copy
explicit unordered_map(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
explicit unordered_map(allocator_type const& a)
: base(boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), a)
{
}
unordered_map(unordered_map const& other, allocator_type const& a)
: base(other.base, a)
{
}
template <class InputIterator>
unordered_map(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_map(InputIterator f, InputIterator l,
size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
#if defined(BOOST_HAS_RVALUE_REFS)
unordered_map(unordered_map&& other)
: base(other.base, boost::unordered_detail::move_tag())
{
}
unordered_map(unordered_map&& other, allocator_type const& a)
: base(other.base, a, boost::unordered_detail::move_tag())
{
}
unordered_map& operator=(unordered_map&& x)
{
base.move(x.base);
return *this;
}
#else
unordered_map(boost::unordered_detail::move_from<unordered_map<Key, T, Hash, Pred, Alloc> > other)
: base(other.source.base, boost::unordered_detail::move_tag())
{
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
unordered_map& operator=(unordered_map x)
{
base.move(x.base);
return *this;
}
#endif
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.data_.begin());
}
const_iterator begin() const
{
return const_iterator(base.data_.begin());
}
iterator end()
{
return iterator(base.data_.end());
}
const_iterator end() const
{
return const_iterator(base.data_.end());
}
const_iterator cbegin() const
{
return const_iterator(base.data_.begin());
}
const_iterator cend() const
{
return const_iterator(base.data_.end());
}
// modifiers
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
{
return boost::unordered_detail::pair_cast<iterator, bool>(
base.insert(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace(const_iterator hint, Args&&... args)
{
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
}
#endif
std::pair<iterator, bool> insert(const value_type& obj)
{
return boost::unordered_detail::pair_cast<iterator, bool>(
base.insert(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
{
return iterator(base.insert_hint(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert_range(first, last);
}
iterator erase(const_iterator position)
{
return iterator(base.data_.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase_key(k);
}
iterator erase(const_iterator first, const_iterator last)
{
return iterator(base.data_.erase_range(get(first), get(last)));
}
void clear()
{
base.data_.clear();
}
void swap(unordered_map& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
mapped_type& operator[](const key_type &k)
{
return base[k].second;
}
mapped_type& at(const key_type& k)
{
return base.at(k).second;
}
mapped_type const& at(const key_type& k) const
{
return base.at(k).second;
}
// lookup
iterator find(const key_type& k)
{
return iterator(base.find(k));
}
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<iterator, iterator>
equal_range(const key_type& k)
{
return boost::unordered_detail::pair_cast<iterator, iterator>(
base.equal_range(k));
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.data_.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.data_.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.data_.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
friend bool operator==(unordered_map const&, unordered_map const&);
friend bool operator!=(unordered_map const&, unordered_map const&);
#else
friend bool operator==<>(unordered_map const&, unordered_map const&);
friend bool operator!=<>(unordered_map const&, unordered_map const&);
#endif
}; // class template unordered_map
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> const& m2)
{
return boost::unordered_detail::equals(m1.base, m2.base);
}
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> const& m2)
{
return !boost::unordered_detail::equals(m1.base, m2.base);
}
template <class K, class T, class H, class P, class A>
inline void swap(unordered_map<K, T, H, P, A> &m1,
unordered_map<K, T, H, P, A> &m2)
{
m1.swap(m2);
}
template <class Key, class T, class Hash, class Pred, class Alloc>
class unordered_multimap
{
typedef boost::unordered_detail::hash_types_equivalent_keys<
std::pair<const Key, T>, Key, Hash, Pred, Alloc
> implementation;
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
public:
// types
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
// construct/destroy/copy
explicit unordered_multimap(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
explicit unordered_multimap(allocator_type const& a)
: base(boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), a)
{
}
unordered_multimap(unordered_multimap const& other, allocator_type const& a)
: base(other.base, a)
{
}
template <class InputIterator>
unordered_multimap(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_multimap(InputIterator f, InputIterator l,
size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
#if defined(BOOST_HAS_RVALUE_REFS)
unordered_multimap(unordered_multimap&& other)
: base(other.base, boost::unordered_detail::move_tag())
{
}
unordered_multimap(unordered_multimap&& other, allocator_type const& a)
: base(other.base, a, boost::unordered_detail::move_tag())
{
}
unordered_multimap& operator=(unordered_multimap&& x)
{
base.move(x.base);
return *this;
}
#else
unordered_multimap(boost::unordered_detail::move_from<unordered_multimap<Key, T, Hash, Pred, Alloc> > other)
: base(other.source.base, boost::unordered_detail::move_tag())
{
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
unordered_multimap& operator=(unordered_multimap x)
{
base.move(x.base);
return *this;
}
#endif
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.data_.begin());
}
const_iterator begin() const
{
return const_iterator(base.data_.begin());
}
iterator end()
{
return iterator(base.data_.end());
}
const_iterator end() const
{
return const_iterator(base.data_.end());
}
const_iterator cbegin() const
{
return const_iterator(base.data_.begin());
}
const_iterator cend() const
{
return const_iterator(base.data_.end());
}
// modifiers
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class... Args>
iterator emplace(Args&&... args)
{
return iterator(base.insert(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace(const_iterator hint, Args&&... args)
{
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
}
#endif
iterator insert(const value_type& obj)
{
return iterator(base.insert(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
{
return iterator(base.insert_hint(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert_range(first, last);
}
iterator erase(const_iterator position)
{
return iterator(base.data_.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase_key(k);
}
iterator erase(const_iterator first, const_iterator last)
{
return iterator(base.data_.erase_range(get(first), get(last)));
}
void clear()
{
base.data_.clear();
}
void swap(unordered_multimap& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
// lookup
iterator find(const key_type& k)
{
return iterator(base.find(k));
}
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<iterator, iterator>
equal_range(const key_type& k)
{
return boost::unordered_detail::pair_cast<iterator, iterator>(
base.equal_range(k));
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.data_.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.data_.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.data_.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
friend bool operator==(unordered_multimap const&, unordered_multimap const&);
friend bool operator!=(unordered_multimap const&, unordered_multimap const&);
#else
friend bool operator==<>(unordered_multimap const&, unordered_multimap const&);
friend bool operator!=<>(unordered_multimap const&, unordered_multimap const&);
#endif
}; // class template unordered_multimap
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> const& m2)
{
return boost::unordered_detail::equals(m1.base, m2.base);
}
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> const& m2)
{
return !boost::unordered_detail::equals(m1.base, m2.base);
}
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A> &m1,
unordered_multimap<K, T, H, P, A> &m2)
{
m1.swap(m2);
}
} // namespace boost
#endif // BOOST_UNORDERED_MAP_HPP_INCLUDED
+764 -4
View File
@@ -9,11 +9,771 @@
#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>
#include <boost/config.hpp>
#include <functional>
#include <memory>
#include <boost/functional/hash.hpp>
#include <boost/unordered/detail/hash_table.hpp>
#if !defined(BOOST_HAS_RVALUE_REFS)
#include <boost/unordered/detail/move.hpp>
#endif
namespace boost
{
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
class unordered_set;
template <class T, class H, class P, class A>
bool operator==(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
bool operator!=(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
class unordered_multiset;
template <class T, class H, class P, class A>
bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2);
template <class Value, class Hash, class Pred, class Alloc>
class unordered_set
{
typedef boost::unordered_detail::hash_types_unique_keys<
Value, Value, Hash, Pred, Alloc
> implementation;
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
public:
// types
typedef Value key_type;
typedef Value value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
// construct/destroy/copy
explicit unordered_set(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
explicit unordered_set(allocator_type const& a)
: base(boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), a)
{
}
unordered_set(unordered_set const& other, allocator_type const& a)
: base(other.base, a)
{
}
template <class InputIterator>
unordered_set(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_set(InputIterator f, InputIterator l, size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
#if defined(BOOST_HAS_RVALUE_REFS)
unordered_set(unordered_set&& other)
: base(other.base, boost::unordered_detail::move_tag())
{
}
unordered_set(unordered_set&& other, allocator_type const& a)
: base(other.base, a, boost::unordered_detail::move_tag())
{
}
unordered_set& operator=(unordered_set&& x)
{
base.move(x.base);
return *this;
}
#else
unordered_set(boost::unordered_detail::move_from<unordered_set<Value, Hash, Pred, Alloc> > other)
: base(other.source.base, boost::unordered_detail::move_tag())
{
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
unordered_set& operator=(unordered_set x)
{
base.move(x.base);
return *this;
}
#endif
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.data_.begin());
}
const_iterator begin() const
{
return const_iterator(base.data_.begin());
}
iterator end()
{
return iterator(base.data_.end());
}
const_iterator end() const
{
return const_iterator(base.data_.end());
}
const_iterator cbegin() const
{
return const_iterator(base.data_.begin());
}
const_iterator cend() const
{
return const_iterator(base.data_.end());
}
// modifiers
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
{
return boost::unordered_detail::pair_cast<iterator, bool>(
base.insert(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace(const_iterator hint, Args&&... args)
{
return iterator(
base.insert_hint(get(hint), std::forward<Args>(args)...));
}
#endif
std::pair<iterator, bool> insert(const value_type& obj)
{
return boost::unordered_detail::pair_cast<iterator, bool>(
base.insert(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
{
return iterator(base.insert_hint(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert_range(first, last);
}
iterator erase(const_iterator position)
{
return iterator(base.data_.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase_key(k);
}
iterator erase(const_iterator first, const_iterator last)
{
return iterator(base.data_.erase_range(get(first), get(last)));
}
void clear()
{
base.data_.clear();
}
void swap(unordered_set& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
// lookup
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.data_.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.data_.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.data_.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
friend bool operator==(unordered_set const&, unordered_set const&);
friend bool operator!=(unordered_set const&, unordered_set const&);
#else
friend bool operator==<>(unordered_set const&, unordered_set const&);
friend bool operator!=<>(unordered_set const&, unordered_set const&);
#endif
}; // class template unordered_set
template <class T, class H, class P, class A>
inline bool operator==(unordered_set<T, H, P, A> const& m1,
unordered_set<T, H, P, A> const& m2)
{
return boost::unordered_detail::equals(m1.base, m2.base);
}
template <class T, class H, class P, class A>
inline bool operator!=(unordered_set<T, H, P, A> const& m1,
unordered_set<T, H, P, A> const& m2)
{
return !boost::unordered_detail::equals(m1.base, m2.base);
}
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2)
{
m1.swap(m2);
}
template <class Value, class Hash, class Pred, class Alloc>
class unordered_multiset
{
typedef boost::unordered_detail::hash_types_equivalent_keys<
Value, Value, Hash, Pred, Alloc
> implementation;
BOOST_DEDUCED_TYPENAME implementation::hash_table base;
public:
//types
typedef Value key_type;
typedef Value value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
// construct/destroy/copy
explicit unordered_multiset(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
explicit unordered_multiset(allocator_type const& a)
: base(boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), a)
{
}
unordered_multiset(unordered_multiset const& other, allocator_type const& a)
: base(other.base, a)
{
}
template <class InputIterator>
unordered_multiset(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_multiset(InputIterator f, InputIterator l, size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
#if defined(BOOST_HAS_RVALUE_REFS)
unordered_multiset(unordered_multiset&& other)
: base(other.base, boost::unordered_detail::move_tag())
{
}
unordered_multiset(unordered_multiset&& other, allocator_type const& a)
: base(other.base, a, boost::unordered_detail::move_tag())
{
}
unordered_multiset& operator=(unordered_multiset&& x)
{
base.move(x.base);
return *this;
}
#else
unordered_multiset(boost::unordered_detail::move_from<unordered_multiset<Value, Hash, Pred, Alloc> > other)
: base(other.source.base, boost::unordered_detail::move_tag())
{
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
unordered_multiset& operator=(unordered_multiset x)
{
base.move(x.base);
return *this;
}
#endif
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.data_.begin());
}
const_iterator begin() const
{
return const_iterator(base.data_.begin());
}
iterator end()
{
return iterator(base.data_.end());
}
const_iterator end() const
{
return const_iterator(base.data_.end());
}
const_iterator cbegin() const
{
return const_iterator(base.data_.begin());
}
const_iterator cend() const
{
return const_iterator(base.data_.end());
}
// modifiers
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class... Args>
iterator emplace(Args&&... args)
{
return iterator(base.insert(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace(const_iterator hint, Args&&... args)
{
return iterator(base.insert_hint(get(hint), std::forward<Args>(args)...));
}
#endif
iterator insert(const value_type& obj)
{
return iterator(base.insert(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
{
return iterator(base.insert_hint(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert_range(first, last);
}
iterator erase(const_iterator position)
{
return iterator(base.data_.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase_key(k);
}
iterator erase(const_iterator first, const_iterator last)
{
return iterator(base.data_.erase_range(get(first), get(last)));
}
void clear()
{
base.data_.clear();
}
void swap(unordered_multiset& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
// lookup
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.data_.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.data_.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.data_.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.data_.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.data_.end(n));
}
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
friend bool operator==(unordered_multiset const&, unordered_multiset const&);
friend bool operator!=(unordered_multiset const&, unordered_multiset const&);
#else
friend bool operator==<>(unordered_multiset const&, unordered_multiset const&);
friend bool operator!=<>(unordered_multiset const&, unordered_multiset const&);
#endif
}; // class template unordered_multiset
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> const& m2)
{
return boost::unordered_detail::equals(m1.base, m2.base);
}
template <class T, class H, class P, class A>
inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> const& m2)
{
return !boost::unordered_detail::equals(m1.base, m2.base);
}
template <class T, class H, class P, class A>
inline void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2)
{
m1.swap(m2);
}
} // namespace boost
#endif // BOOST_UNORDERED_SET_HPP_INCLUDED
-44
View File
@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2018 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)
-->
<explicit-failures-markup>
<!-- unordered -->
<library name="unordered">
<mark-expected-failures>
<test name="unnecessary_copy_tests"/>
<toolset name="borland-*"/>
<toolset name="sun-*"/>
<note author="Daniel James">
This tests whether inserting elements creates as few copies as I think
is possible. If this fails it just means that the container might be
a little inefficient.
</note>
</mark-expected-failures>
<mark-expected-failures>
<test name="compile_map_unordered_allocator"/>
<toolset name="msvc-7.1"/>
<note author="Daniel James">
This test fail because it's using unordered's internal
allocator traits, which doesn't work on Visual C++ 7.1.
It normally uses the one from Boost.Container by default.
</note>
</mark-expected-failures>
<mark-expected-failures>
<test name="noexcept_tests"/>
<toolset name="gcc-4.3c+"/>
<note author="Daniel James">
boost::is_nothrow_move_constructible and
boost::is_nothrow_move_assignable don't seem to work on this
compiler. I'd hope that anyone wanting noexcept support would
use a more recent compiler anyway.
</note>
</mark-expected-failures>
</library>
</explicit-failures-markup>
-17
View File
@@ -1,17 +0,0 @@
{
"key": "unordered",
"name": "Unordered",
"authors": [
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
]
}
+2 -92
View File
@@ -3,95 +3,5 @@
# 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 -Wfloat-equal -Wshadow"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
<toolset>msvc:<cxxflags>"/wd4494"
<toolset>gcc:<c++-template-depth>500
;
#alias framework : /boost/test//boost_unit_test_framework ;
alias framework : ;
test-suite unordered
:
[ run unordered/fwd_set_test.cpp ]
[ run unordered/fwd_map_test.cpp ]
[ run unordered/allocator_traits.cpp ]
[ run unordered/minimal_allocator.cpp ]
[ run unordered/compile_set.cpp ]
[ run unordered/compile_map.cpp ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
: compile_map_unordered_allocator ]
[ run unordered/noexcept_tests.cpp ]
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
[ run unordered/incomplete_test.cpp ]
[ run unordered/simple_tests.cpp ]
[ run unordered/equivalent_keys_tests.cpp ]
[ run unordered/constructor_tests.cpp ]
[ run unordered/copy_tests.cpp ]
[ run unordered/move_tests.cpp ]
[ run unordered/assign_tests.cpp ]
[ run unordered/insert_tests.cpp ]
[ run unordered/insert_stable_tests.cpp ]
[ run unordered/insert_hint_tests.cpp ]
[ run unordered/emplace_tests.cpp ]
[ run unordered/unnecessary_copy_tests.cpp ]
[ run unordered/erase_tests.cpp : : : <define>BOOST_UNORDERED_SUPPRESS_DEPRECATED ]
[ run unordered/erase_equiv_tests.cpp ]
[ run unordered/extract_tests.cpp ]
[ run unordered/node_handle_tests.cpp ]
[ run unordered/merge_tests.cpp ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MAP : insert_node_type_fail_map ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTIMAP : insert_node_type_fail_multimap ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_SET : insert_node_type_fail_set ]
[ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTISET : insert_node_type_fail_multiset ]
[ run unordered/find_tests.cpp ]
[ run unordered/at_tests.cpp ]
[ run unordered/bucket_tests.cpp ]
[ run unordered/load_factor_tests.cpp ]
[ run unordered/rehash_tests.cpp ]
[ run unordered/equality_tests.cpp ]
[ run unordered/swap_tests.cpp ]
[ run unordered/detail_tests.cpp ]
[ run unordered/deduction_tests.cpp ]
[ run unordered/compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run unordered/copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run unordered/move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run unordered/assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
test-suite unordered-exception
:
[ run exception/constructor_exception_tests.cpp framework ]
[ run exception/copy_exception_tests.cpp framework ]
[ run exception/assign_exception_tests.cpp framework ]
[ run exception/move_assign_exception_tests.cpp framework ]
[ run exception/insert_exception_tests.cpp framework ]
[ run exception/erase_exception_tests.cpp framework ]
[ run exception/rehash_exception_tests.cpp framework ]
[ run exception/swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
[ run exception/merge_exception_tests.cpp framework ]
;
build-project unordered ;
build-project exception ;
+27
View File
@@ -0,0 +1,27 @@
# 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
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
;
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 ]
;
+49 -153
View File
@@ -1,185 +1,81 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4512) // assignment operator could not be generated
#endif
test::seed_t seed(12847);
test::seed_t initialize_seed(12847);
template <class T> struct self_assign_base : public test::exception_base
template <class T>
struct self_assign_base : public test::exception_base
{
test::random_values<T> values;
self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
{
}
test::random_values<T> values;
self_assign_base(int count = 0) : values(count) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const
{
x = x;
DISABLE_EXCEPTIONS;
test::check_container(x, values);
test::check_equivalent_keys(x);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
test::check_equivalent_keys(x);
}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const { x = x; }
void check(T const& x) const { 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>
{
self_assign_test2() : self_assign_base<T>(100) {}
};
template <class T> struct self_assign_test2 : self_assign_base<T>
template <class T>
struct assign_base : public test::exception_base
{
self_assign_test2() : self_assign_base<T>(100) {}
const test::random_values<T> x_values, y_values;
const T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1), y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2), allocator_type(tag2)) {}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const { x1 = y; }
void check(T const& x1) const { test::check_equivalent_keys(x1); }
};
template <class T> struct assign_base : public test::exception_base
template <class T>
struct assign_test1 : assign_base<T>
{
test::random_values<T> x_values, y_values;
T x, y;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const
{
x1 = y;
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
void 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);
}
}
assign_test1() : assign_base<T>(0, 0, 0, 0) {}
};
template <class T> struct assign_values : assign_base<T>
template <class T>
struct assign_test2 : assign_base<T>
{
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
test::random_generator gen = test::default_generator, float mlf1 = 1.0,
float mlf2 = 1.0)
: assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1, gen);
this->y_values.fill(count2, gen);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
assign_test2() : assign_base<T>(60, 0, 0, 0) {}
};
template <class T> struct assign_test1 : assign_values<T>
template <class T>
struct assign_test3 : assign_base<T>
{
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
assign_test3() : assign_base<T>(0, 60, 0, 0) {}
};
template <class T> struct assign_test2 : assign_values<T>
template <class T>
struct assign_test4 : assign_base<T>
{
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
};
template <class T> struct assign_test2a : assign_values<T>
{
assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
};
template <class T> struct assign_test3 : assign_values<T>
{
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
};
template <class T> struct assign_test3a : assign_values<T>
{
assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
};
template <class T> struct assign_test4 : assign_values<T>
{
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
};
template <class T> struct assign_test4a : assign_values<T>
{
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
};
template <class T> struct assign_test4b : assign_values<T>
{
assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
};
template <class T> struct assign_test5 : assign_values<T>
{
assign_test5()
: assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f)
{
}
};
template <class T> struct equivalent_test1 : assign_base<T>
{
equivalent_test1() : assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
// clang-format off
EXCEPTION_TESTS_REPEAT(5,
RUN_EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test2a)
(assign_test3)(assign_test3a)
(assign_test4)(assign_test4a)(assign_test4b)
(assign_test5)
(equivalent_test1),
(assign_test1)(assign_test2)(assign_test3)(assign_test4),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+81 -156
View File
@@ -1,212 +1,137 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/input_iterator.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/input_iterator.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t initialize_seed(91274);
test::seed_t seed(91274);
struct objects
{
test::exception::object obj;
test::exception::hash hash;
test::exception::equal_to equal_to;
test::exception::allocator<test::exception::object> allocator;
test::exception::object obj;
test::exception::hash hash;
test::exception::equal_to equal_to;
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
{
T x;
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T 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
{
T x(300);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T x(300);
}
};
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
{
T x(0, hash);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T x(0, hash);
}
};
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
{
T x(0, hash, equal_to);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T x(0, hash, equal_to);
}
};
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
{
T x(50, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T x(50, hash, equal_to, allocator);
}
};
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
{
T x(allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void run() const {
T x(allocator);
}
};
template <class T> struct range : public test::exception_base
template <class T>
struct range : public test::exception_base
{
test::random_values<T> values;
test::random_values<T> values;
range() : values(5, test::limited_range) {}
range(unsigned int count) : values(count, test::limited_range) {}
range() : values(5) {}
range(unsigned int count) : values(count) {}
};
template <class T> struct range_construct_test1 : public range<T>, objects
template <class T>
struct range_construct_test1 : public range<T>, objects
{
void run() const
{
T x(this->values.begin(), this->values.end());
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(this->values.begin(), this->values.end());
}
};
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
{
T x(this->values.begin(), this->values.end(), 0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(this->values.begin(), this->values.end(), 0);
}
};
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
{
T x(this->values.begin(), this->values.end(), 0, hash);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash);
}
};
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
{
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
}
};
// 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) {}
range_construct_test5() : range<T>(60) {}
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
}
};
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) {}
input_range_construct_test() : range<T>(60) {}
void run() const
{
typename test::random_values<T>::const_iterator begin =
this->values.begin(),
end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void run() const {
T x(test::input_iterator(this->values.begin()),
test::input_iterator(this->values.end()),
0, hash, equal_to, allocator);
}
};
template <class T> struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
void run() const
{
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
// clang-format off
EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)
(construct_test5)(construct_test6)(range_construct_test1)
(range_construct_test2)(range_construct_test3)(range_construct_test4)
(range_construct_test5)(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
RUN_EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)(construct_test5)(construct_test6)
(range_construct_test1)(range_construct_test2)(range_construct_test3)(range_construct_test4)(range_construct_test5)
(input_range_construct_test),
CONTAINER_SEQ)
+21 -32
View File
@@ -1,44 +1,33 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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::allocator<test::exception::object> > test_multiset;
typedef boost::unordered_map<
test::exception::object,
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<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)
+35 -82
View File
@@ -1,110 +1,63 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(73041);
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;
T x;
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
BOOST_TEST(y.empty());
test::check_equivalent_keys(y);
}
void run() const {
T y(x);
}
};
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;
test::random_values<T> values;
T x;
copy_test2() : values(5, test::limited_range), x(values.begin(), values.end())
{
}
copy_test2() : values(5), x(values.begin(), values.end()) {}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
void run() const {
T y(x);
}
};
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;
test::random_values<T> values;
T x;
copy_test3() : values(100), x(values.begin(), values.end()) {}
copy_test3() : values(100), x(values.begin(), values.end()) {}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
void run() const {
T y(x);
}
};
template <class T> struct copy_test3a : public test::exception_base
template <class T>
struct copy_with_allocator_test : public test::exception_base
{
test::random_values<T> values;
T x;
test::random_values<T> values;
T x;
test::exception::allocator<test::exception::object> allocator;
copy_test3a()
: values(100, test::limited_range), x(values.begin(), values.end())
{
}
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
void run() const {
T y(x, allocator);
}
};
template <class T> struct copy_with_allocator_test : public test::exception_base
{
test::random_values<T> values;
T x;
test::exception::allocator<test::exception::object> allocator;
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
void run() const
{
T y(x, allocator);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
};
// clang-format off
EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_test3a)(copy_with_allocator_test),
RUN_EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+38 -40
View File
@@ -1,55 +1,53 @@
// Copyright 2006-2009 Daniel James.
// 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)
#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);
test::seed_t seed(835193);
template <class T> struct erase_test_base : public test::exception_base
template <class T>
struct erase_test_base : public test::exception_base
{
test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
{
}
test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count) {}
typedef T data_type;
typedef T data_type;
data_type init() const { return T(values.begin(), values.end()); }
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)");
test::check_equivalent_keys(x);
}
};
template <class T> struct erase_by_key_test1 : public erase_test_base<T>
{
void run(T& x) const
{
typedef typename test::random_values<T>::const_iterator iterator;
for (iterator it = this->values.begin(), end = this->values.end();
it != end; ++it) {
x.erase(test::get_key<T>(*it));
data_type init() const {
return T(values.begin(), values.end());
}
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
void check(T const& x) const {
std::string scope(test::scope);
BOOST_CHECK(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
test::check_equivalent_keys(x);
}
};
EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
RUN_TESTS()
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;
for(iterator it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
x.erase(test::get_key<T>(*it));
}
}
};
RUN_EXCEPTION_TESTS(
(erase_by_key_test1),
CONTAINER_SEQ)
+205 -384
View File
@@ -1,416 +1,237 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <cmath>
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/input_iterator.hpp"
#include <boost/utility.hpp>
#include <cmath>
test::seed_t initialize_seed(747373);
test::seed_t seed(747373);
// Fill in a container so that it's about to rehash
template <typename T> void rehash_prep(T& x)
template <class T>
struct insert_test_base : public test::exception_base
{
using namespace std;
typedef typename T::size_type size_type;
test::random_values<T> values;
insert_test_base(unsigned int count = 5) : values(count) {}
x.max_load_factor(0.25);
size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>(
ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
test::random_values<T> v(initial_elements);
x.insert(v.begin(), v.end());
BOOST_TEST(bucket_count == x.bucket_count());
}
typedef T data_type;
typedef test::strong<T> strong_type;
// Overload to generate inserters that need type information.
template <typename Inserter, typename T>
Inserter generate(Inserter inserter, T&)
{
return inserter;
}
// Get the iterator returned from an insert/emplace.
template <typename T> T get_iterator(T const& x) { return x; }
template <typename T> T get_iterator(std::pair<T, bool> const& x)
{
return x.first;
}
// Generic insert exception test for typical single element inserts..
template <typename T, typename Inserter, typename Values>
void insert_exception_test_impl(T x, Inserter insert, Values const& v)
{
test::strong<T> strong;
test::ordered<T> tracker;
tracker.insert(x.begin(), x.end());
try {
ENABLE_EXCEPTIONS;
for (typename Values::const_iterator it = v.begin(); it != v.end(); ++it) {
strong.store(x, test::detail::tracker.count_allocations);
insert(x, it);
data_type init() const {
return T();
}
} catch (...) {
test::check_equivalent_keys(x);
insert.exception_check(x, strong);
throw;
}
test::check_equivalent_keys(x);
insert.track(tracker, v.begin(), v.end());
tracker.compare(x);
}
void check(T const& x, strong_type const& strong) const {
std::string scope(test::scope);
// Simple insert exception test
template <typename T, typename Inserter>
void insert_exception_test(T*, Inserter insert, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen);
T x;
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
}
}
// Insert into a container which is about to hit its max load, so that it
// rehashes.
template <typename T, typename Inserter>
void insert_rehash_exception_test(
T*, Inserter insert, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
T x;
rehash_prep(x);
test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
}
}
// Various methods for inserting a single element
struct inserter_base
{
template <typename T> void exception_check(T& x, test::strong<T>& strong)
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
}
template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end)
{
tracker.insert(begin, end);
}
};
struct insert_lvalue_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(*it);
}
} insert_lvalue;
struct insert_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.begin(), *it);
}
} insert_lvalue_begin;
struct insert_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.end(), *it);
}
} insert_lvalue_end;
template <typename T> struct insert_lvalue_pos_type_impl : inserter_base
{
typename T::iterator pos;
insert_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.insert(pos, *it));
}
};
struct insert_lvalue_pos_type
{
template <typename T>
friend insert_lvalue_pos_type_impl<T> generate(insert_lvalue_pos_type, T& x)
{
return insert_lvalue_pos_type_impl<T>(x);
}
} insert_lvalue_pos;
struct insert_single_item_range_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(it, test::next(it));
}
} insert_single_item_range;
struct emplace_lvalue_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace(*it);
}
} emplace_lvalue;
struct emplace_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.begin(), *it);
}
} emplace_lvalue_begin;
struct emplace_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.end(), *it);
}
} emplace_lvalue_end;
template <typename T> struct emplace_lvalue_pos_type_impl : inserter_base
{
typename T::iterator pos;
emplace_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.emplace_hint(pos, *it));
}
};
struct emplace_lvalue_pos_type
{
template <typename T>
friend emplace_lvalue_pos_type_impl<T> generate(emplace_lvalue_pos_type, T& x)
{
return emplace_lvalue_pos_type_impl<T>(x);
}
} emplace_lvalue_pos;
// Run the exception tests in various combinations.
test_set* test_set_;
test_multiset* test_multiset_;
test_map* test_map_;
test_multimap* test_multimap_;
using test::default_generator;
using test::limited_range;
using test::generate_collisions;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
// Repeat insert tests with pairs
struct pair_emplace_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(it->first), boost::make_tuple(it->second));
}
} pair_emplace;
struct pair_emplace2_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(it->first),
boost::make_tuple(it->second.tag1_, it->second.tag2_));
}
} pair_emplace2;
test_pair_set* test_pair_set_;
test_pair_multiset* test_pair_multiset_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
// Test inserting using operator[]
struct try_emplace_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.try_emplace(it->first, it->second);
}
} try_emplace;
struct try_emplace2_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
}
} try_emplace2;
struct map_inserter_base
{
template <typename T> void exception_check(T& x, test::strong<T>& strong)
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos &&
scope.find("::operator=") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
}
template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end)
{
for (; begin != end; ++begin) {
tracker[begin->first] = begin->second;
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x);
test::check_equivalent_keys(x);
}
}
};
struct map_insert_operator_type : map_inserter_base
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class T>
struct emplace_test1 : public insert_test_base<T>
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x[it->first] = it->second;
}
} map_insert_operator;
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
struct map_insert_or_assign_type : map_inserter_base
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);
x.emplace(*it);
}
}
};
#endif
template <class T>
struct insert_test1 : public insert_test_base<T>
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert_or_assign(it->first, it->second);
}
} map_insert_or_assign;
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
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);
x.insert(*it);
}
}
};
// Range insert tests
template <typename T, typename Values>
void insert_range_exception_test_impl(T x, Values const& v)
template <class T>
struct insert_test2 : public insert_test_base<T>
{
test::ordered<T> tracker;
tracker.insert(x.begin(), x.end());
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
try {
ENABLE_EXCEPTIONS;
x.insert(v.begin(), v.end());
} catch (...) {
test::check_equivalent_keys(x);
throw;
}
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);
x.insert(x.begin(), *it);
}
}
};
test::check_equivalent_keys(x);
tracker.insert(v.begin(), v.end());
tracker.compare(x);
}
template <typename T>
void insert_range_exception_test(T*, test::random_generator gen)
template <class T>
struct insert_test3 : public insert_test_base<T>
{
for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen);
T x;
void run(T& x) const {
x.insert(this->values.begin(), this->values.end());
}
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
}
}
void check(T const& x) const {
test::check_equivalent_keys(x);
}
};
template <typename T>
void insert_range_rehash_exception_test(T*, test::random_generator gen)
template <class T>
struct insert_test4 : public insert_test_base<T>
{
for (int i = 0; i < 5; ++i) {
T x;
rehash_prep(x);
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
}
}
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);
x.insert(it, boost::next(it));
}
}
};
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((default_generator)(limited_range)(generate_collisions))
)
template <class T>
struct insert_test_rehash1 : public insert_test_base<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
UNORDERED_TEST(insert_range_rehash_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
insert_test_rehash1() : insert_test_base<T>(1000) {}
RUN_TESTS()
T init() const {
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
T x;
x.max_load_factor(0.25);
size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>(
ceil(bucket_count * (double) x.max_load_factor()) - 1);
BOOST_REQUIRE(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_REQUIRE(bucket_count == x.bucket_count());
return x;
}
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 = boost::next(this->values.begin(), x.size()), end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x);
pos = x.insert(pos, *it);
}
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
}
};
template <class T>
struct insert_test_rehash2 : public insert_test_rehash1<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
int count = 0;
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = boost::next(this->values.begin(), x.size()), end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x);
x.insert(*it);
}
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
}
};
template <class T>
struct insert_test_rehash3 : public insert_test_base<T>
{
BOOST_DEDUCED_TYPENAME T::size_type mutable rehash_bucket_count, original_bucket_count;
insert_test_rehash3() : insert_test_base<T>(1000) {}
T init() const {
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
T x;
x.max_load_factor(0.25);
original_bucket_count = x.bucket_count();
rehash_bucket_count = static_cast<size_type>(
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
size_type initial_elements = rehash_bucket_count - 5;
BOOST_REQUIRE(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_REQUIRE(original_bucket_count == x.bucket_count());
return x;
}
void run(T& x) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
x.insert(boost::next(this->values.begin(), x.size()),
boost::next(this->values.begin(), x.size() + 20));
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
}
void check(T const& x) const {
if(x.size() < rehash_bucket_count) {
//BOOST_CHECK(x.bucket_count() == original_bucket_count);
}
test::check_equivalent_keys(x);
}
};
#define BASIC_TESTS \
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#define ALL_TESTS (emplace_test1)BASIC_TESTS
#else
#define ALL_TESTS BASIC_TESTS
#endif
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
-108
View File
@@ -1,108 +0,0 @@
// Copyright 2017-2018 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/exception_test.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/random_values.hpp"
#include "./containers.hpp"
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
{
std::size_t size = x.size() + y.size();
try {
ENABLE_EXCEPTIONS;
x.merge(y);
} catch (...) {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <typename T1, typename T2>
void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
test::random_generator gen1, test::random_generator gen2)
{
std::size_t count1 = count12 / 256;
std::size_t count2 = count12 % 256;
int tag1 = tag12 / 256;
int tag2 = tag12 % 256;
test::random_values<T1> v1(count1, gen1);
test::random_values<T2> v2(count2, gen2);
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
test::exception::equal_to(tag1));
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
test::exception::equal_to(tag2));
EXCEPTION_LOOP(merge_exception_test(x, y))
}
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_multiset<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_multiset_;
boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0101)(0x0200)(0x0201))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
// clang-format on
RUN_TESTS_QUIET()
@@ -1,132 +0,0 @@
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#if defined(BOOST_MSVC)
#pragma warning( \
disable : 4512) // move_assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
template <class T> struct move_assign_base : public test::exception_base
{
test::random_values<T> x_values, y_values;
T x, y;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const
{
test::exceptions_enable disable_exceptions(false);
T y1 = y;
disable_exceptions.release();
x1 = boost::move(y1);
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
}
};
template <class T> struct move_assign_values : move_assign_base<T>
{
move_assign_values(unsigned int count1, unsigned int count2, int tag1,
int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: move_assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1, test::limited_range);
this->y_values.fill(count2, test::limited_range);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
template <class T> struct move_assign_test1 : move_assign_values<T>
{
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
};
template <class T> struct move_assign_test2 : move_assign_values<T>
{
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
};
template <class T> struct move_assign_test3 : move_assign_values<T>
{
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
};
template <class T> struct move_assign_test4 : move_assign_values<T>
{
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
};
template <class T> struct move_assign_test4a : move_assign_values<T>
{
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
};
template <class T> struct move_assign_test5 : move_assign_values<T>
{
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
};
template <class T> struct equivalent_test1 : move_assign_base<T>
{
equivalent_test1() : move_assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10, test::limited_range);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10, test::limited_range);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
// clang-format off
EXCEPTION_TESTS(
(move_assign_test1)(move_assign_test2)(move_assign_test3)
(move_assign_test4)(move_assign_test4a)(move_assign_test5)
(equivalent_test1),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+49 -101
View File
@@ -1,133 +1,81 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
test::seed_t initialize_seed(3298597);
#include <iostream>
template <class T> struct rehash_test_base : public test::exception_base
test::seed_t seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
{
test::random_values<T> values;
unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count, test::limited_range), n(n_)
{
}
test::random_values<T> values;
unsigned int 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;
typedef T data_type;
typedef test::strong<T> strong_type;
data_type init() const
{
T x(values.begin(), values.end(), n);
return x;
}
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
{
std::string scope(test::scope);
void check(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)")
strong.test(x);
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);
}
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test0 : rehash_test_base<T>
template <class T>
struct rehash_test0 : rehash_test_base<T>
{
rehash_test0() : rehash_test_base<T>(0) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
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);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
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);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
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);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
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);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
rehash_test4() : rehash_test_base<T>(10, 200) {}
void run(T& x) const { x.rehash(0); }
};
template <class T> struct rehash_test5 : rehash_test_base<T>
{
rehash_test5() : rehash_test_base<T>(200, 10) {}
void run(T& x) const
{
x.rehash(0);
RUN_EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
CONTAINER_SEQ)
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
// clang-format off
EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4)
(rehash_test5),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+94 -120
View File
@@ -1,145 +1,119 @@
// Copyright 2006-2009 Daniel James.
// 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)
#include "./containers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4512) // assignment operator could not be generated
test::seed_t seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
{
test::random_values<T> values;
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(T const& x) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_CHECK(
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::seed_t initialize_seed(9387);
template <class T> struct self_swap_base : public test::exception_base
{
test::random_values<T> values;
self_swap_base(std::size_t count = 0) : values(count, test::limited_range) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const
{
x.swap(x);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
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)");
test::check_equivalent_keys(x);
}
};
template <class T> struct self_swap_test1 : 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
{
const test::random_values<T> x_values, y_values;
const T initial_x, initial_y;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1, test::limited_range),
y_values(count2, test::limited_range),
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
key_equal(tag1), allocator_type(tag1)),
initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
key_equal(tag2),
allocator_type(T::allocator_type::propagate_on_container_swap::value
? tag2
: tag1))
{
}
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
{
try {
d.x.swap(d.y);
} catch (std::runtime_error&) {
test::check_equivalent_keys(x);
}
DISABLE_EXCEPTIONS;
test::check_container(d.x, this->y_values);
test::check_equivalent_keys(d.x);
test::check_container(d.y, this->x_values);
test::check_equivalent_keys(d.y);
}
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)");
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 self_swap_test1 : self_swap_base<T> {};
template <class T>
struct self_swap_test2 : self_swap_base<T>
{
swap_test1() : swap_base<T>(0, 0, 0, 0) {}
self_swap_test2() : self_swap_base<T>(100) {}
};
template <class T> struct swap_test2 : swap_base<T>
template <class T>
struct swap_base : public test::exception_base
{
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
const test::random_values<T> x_values, y_values;
const T initial_x, initial_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;
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(tag2))
{}
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 {
try {
d.x.swap(d.y);
} catch (std::runtime_error) {}
}
void check(data_type const& d) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_CHECK(
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
}
};
template <class T> struct swap_test3 : swap_base<T>
template <class T>
struct swap_test1 : swap_base<T>
{
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
swap_test1() : swap_base<T>(0, 0, 0, 0) {}
};
template <class T> struct swap_test4 : swap_base<T>
template <class T>
struct swap_test2 : swap_base<T>
{
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
};
// clang-format off
EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
// clang-format on
template <class T>
struct swap_test3 : swap_base<T>
{
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
};
RUN_TESTS()
template <class T>
struct swap_test4 : swap_base<T>
{
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
};
RUN_EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
+84
View File
@@ -0,0 +1,84 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER
#include <cstddef>
#include <cstdlib>
#include <boost/limits.hpp>
#include <new>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace test
{
template <class T>
struct malloc_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef malloc_allocator<U> other; };
malloc_allocator() {}
template <class Y> malloc_allocator(malloc_allocator<Y> const&) {}
malloc_allocator(malloc_allocator const&) {}
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
pointer allocate(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(T)));
if(!ptr) throw std::bad_alloc();
return ptr;
}
pointer allocate(size_type n, void const* u) { return allocate(n); }
void deallocate(pointer p, size_type) {
using namespace std;
free(p);
}
void construct(pointer p, T const& t) { new(p) T(t); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const& x) const { return true; }
bool operator!=(malloc_allocator const& x) const { return false; }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void deallocate(T* p, size_type) {
using namespace std;
free(p);
}
char* _Charalloc(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(char)));
if(!ptr) throw std::bad_alloc();
return (char*) ptr;
}
#endif
};
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#endif
+23 -18
View File
@@ -1,33 +1,38 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
namespace test {
template <class T1> struct check_return_type
{
template <class T2> static void equals(T2)
namespace test
{
template <class T1>
struct check_return_type
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals(T2)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
}
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_MPL_ASSERT((boost::is_same<T1, T2>));
}
template <class T2> static void convertible(T2)
{
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
template <class T2>
static void convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
}
};
}
#endif
+51 -74
View File
@@ -1,89 +1,66 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
#include <boost/core/lightweight_test.hpp>
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()
void construct() {
++instances;
++constructions;
}
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);
}
};
template <class T>
struct counted_object
{
++instances;
++constructions;
static object_count count_;
counted_object() { count_.construct(); }
counted_object(counted_object const&) { count_.construct(); }
~counted_object() { count_.destruct(); }
};
template <class T> object_count counted_object<T>::count_;
struct globally_counted_object
: counted_object<globally_counted_object> {};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count& global_object_count = globally_counted_object::count_;
}
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
{
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_;
}
};
}
#endif
+76 -78
View File
@@ -1,96 +1,94 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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/core/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)
{
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() {}
namespace test
{
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
{
typename Container::size_type size_;
typename Container::hasher hasher_;
typename Container::key_equal key_equal_;
float max_load_factor_;
typedef test::list<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
{
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;
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&, derived_type) {
return true;
}
private:
unordered_equivalence_tester();
};
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;
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
}
private:
unordered_equivalence_tester();
};
}
#endif
+201 -306
View File
@@ -1,348 +1,243 @@
// Copyright 2006-2009 Daniel James.
// 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)
#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>
#if defined(BOOST_UNORDERED_FULL_TEST)
# define BOOST_TEST_MAIN
# include <boost/test/exception_safety.hpp>
# include <boost/test/unit_test.hpp>
#endif
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/cat.hpp>
#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST (name) { \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
}
#define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
UNORDERED_AUTO_TEST (name) { \
for (unsigned i = 0; i < n; ++i) { \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
}
#define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#if defined(BOOST_UNORDERED_FULL_TEST)
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
}
# define UNORDERED_EPOINT_IMPL BOOST_ITEST_EPOINT
#else
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::lightweight::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
}
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#endif
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
#define EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
#define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, (test_seq)(param_seq)) \
RUN_TESTS()
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
#define RUN_EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product) \
)
#define EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product))
#define UNORDERED_SCOPE(scope_name) \
for(::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); \
unordered_test_guard.dismiss())
#define UNORDERED_SCOPE(scope_name) \
for (::test::scope_guard unordered_test_guard(BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
#define UNORDERED_EPOINT(name) \
if(::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
#define UNORDERED_EPOINT(name) \
if (::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
#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)
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;
}
}
void release()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
}
};
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)();
}
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()
{
DISABLE_EXCEPTIONS;
test::check_instances check;
test::scope = "";
typename Test::data_type x(test_.init());
typename Test::strong_type strong;
strong.store(x);
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, typename Test::data_type,
typename Test::strong_type>(&Test::run, test_, x, strong);
} catch (...) {
try {
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, typename Test::data_type const,
typename Test::strong_type const>(
&Test::check, test_, constant(x), constant(strong));
} catch (...) {
exception_in_check_ = 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_;
}
throw;
}
}
void end()
{
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
}
};
// Quick exception testing based on lightweight test
~scope_guard() {
if(dismissed_) scope = old_scope_;
}
namespace lightweight {
static int iteration;
static int count;
void dismiss() {
dismissed_ = true;
}
struct test_exception
{
char const* name;
test_exception(char const* n) : name(n) {}
bool dismissed() const {
return dismissed_;
}
};
struct test_failure
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_;
}
};
void epoint(char const* name)
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() 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&)
{
++count;
if (count == iteration) {
throw test_exception(name);
}
(obj.*fn)();
}
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>
void exception_safety(Test const& f, char const* /*name*/)
class test_runner
{
test_runner<Test> runner(f);
iteration = 0;
bool success = false;
unsigned int failure_count = 0;
char const* error_msg = 0;
do {
int error_count = boost::detail::test_errors();
++iteration;
count = 0;
try {
runner.run();
success = true;
} catch (test_failure) {
error_msg = "test_failure caught.";
break;
} catch (test_exception e) {
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
}
} catch (...) {
error_msg = "Unexpected exception.";
break;
Test const& test_;
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 {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, BOOST_DEDUCED_TYPENAME Test::data_type, BOOST_DEDUCED_TYPENAME Test::strong_type>(&Test::run, test_, x, strong);
}
catch(...) {
call_ignore_extra_parameters<Test, BOOST_DEDUCED_TYPENAME Test::data_type const, BOOST_DEDUCED_TYPENAME Test::strong_type const>(&Test::check, test_,
constant(x), constant(strong));
throw;
}
}
if (error_count != boost::detail::test_errors()) {
++failure_count;
}
} while (!success && failure_count < 5);
if (error_msg) {
BOOST_ERROR(error_msg);
}
runner.end();
}
//
// An alternative way to run exception tests.
// See merge_exception_tests.cpp for an example.
struct exception_looper
{
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{
return !error_msg && !success && failure_count < 5;
}
void start_iteration()
{
error_count = boost::detail::test_errors();
++iteration;
count = 0;
}
void successful_run() { success = true; }
void test_failure_caught(test_failure const&)
{
error_msg = "test_failure caught.";
}
void test_exception_caught(test_exception const& e)
{
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
}
}
void unexpected_exception_caught()
{
error_msg = "Unexpected exception.";
}
void end()
{
if (error_msg) {
BOOST_ERROR(error_msg);
}
}
};
#define EXCEPTION_LOOP(op) \
test::lightweight::exception_looper looper; \
looper.start(); \
while (looper.loop_condition()) { \
looper.start_iteration(); \
try { \
op; \
looper.successful_run(); \
} catch (test::lightweight::test_failure e) { \
looper.test_failure_caught(e); \
} catch (test::lightweight::test_exception e) { \
looper.test_exception_caught(e); \
} catch (...) { \
looper.unexpected_exception_caught(); \
} \
} \
looper.end();
}
#if defined(BOOST_UNORDERED_FULL_TEST)
template <class Test>
void exception_safety(Test const& f, char const* name) {
test_runner<Test> runner(f);
::boost::itest::exception_safety(runner, name);
}
#else
// Quick exception testing based on lightweight test
namespace lightweight {
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);
}
}
#endif
}
#endif
+11 -19
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
@@ -8,25 +8,17 @@
#include <string>
namespace test {
typedef enum {
default_generator,
generate_collisions,
limited_range
} random_generator;
namespace test
{
int generate(int const*);
char generate(char const*);
signed char generate(signed char const*);
std::string generate(std::string*);
float generate(float const*);
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
{
} base;
struct derived_type : base_type
{
} derived;
struct base_type {} base;
struct derived_type : base_type {} derived;
}
#endif
+48 -71
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,83 +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
{
seed_t(unsigned int x)
namespace test
{
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);
}
using namespace std;
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 -42
View File
@@ -1,56 +1,41 @@
// Copyright 2006-2009 Daniel James.
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_HEADER
#include <iterator>
namespace test {
template <class Container> struct get_key_impl
{
typedef 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)
namespace test
{
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 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.
// Mainly because boost::next uses an MPL file
// which causes warnings.
template <typename Iterator> Iterator next(Iterator it) { return ++it; }
template <typename Iterator, typename IntType>
Iterator next(Iterator it, IntType x)
{
std::advance(it,
static_cast<typename std::iterator_traits<Iterator>::difference_type>(x));
return it;
}
}
#endif
+20 -150
View File
@@ -1,165 +1,35 @@
// Copyright 2005-2010 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/config.hpp>
#include <iterator>
#include <boost/iterator_adaptors.hpp>
namespace test {
template <class Iterator> struct proxy
{
typedef typename Iterator::value_type value_type;
namespace test
{
template <class Iterator>
struct input_iterator_adaptor
: boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag>
{
typedef boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag> base;
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
operator value_type const&() const { return v_; }
explicit input_iterator_adaptor(Iterator it = Iterator())
: base(it) {}
};
value_type v_;
private:
proxy& operator=(proxy const&);
};
template <class Iterator> struct input_iterator_adaptor
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef proxy<Iterator> reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
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>
input_iterator_adaptor<Iterator> input_iterator(Iterator it)
{
++*base_;
return *this;
return input_iterator_adaptor<Iterator>(it);
}
// 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 input_iterator_adaptor<Iterator>(it);
}
template <class Iterator> struct copy_iterator_adaptor
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef
typename std::iterator_traits<Iterator>::difference_type difference_type;
typedef typename std::iterator_traits<Iterator>::iterator_category
iterator_category;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef proxy<Iterator> reference;
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>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
return copy_iterator_adaptor<Iterator>(it);
}
}
#endif
+74 -99
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
@@ -9,118 +9,92 @@
#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"
#include "./allocator.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',
// possible loss of data
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace test {
template <class X> void check_equivalent_keys(X const& x1)
{
typename X::key_equal eq = x1.key_eq();
typedef typename X::key_type key_type;
std::set<key_type, std::less<key_type> > found_;
namespace test
{
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;
// Boost.Test was reporting memory leaks for std::set on g++-3.3.
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>, test::malloc_allocator<key_type> > found_;
typename X::const_iterator it = x1.begin(), end = x1.end();
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 occured 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.
typename X::size_type bucket = x1.bucket(key);
typename X::const_local_iterator lit = x1.begin(bucket),
lend = x1.end(bucket);
// I'm not bothering with the following test for now, as the
// previous test is probably more enough to catch the kind of
// errors that this would catch (if an element was in the wrong
// bucket it not be found by the call to count, if elements are not
// adjacent then they would be caught when checking against
// found_.
unsigned int count_checked = 0;
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
++count_checked;
}
// // 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;
// }
// }
};
if (lit == lend) {
BOOST_ERROR("Unable to find element with a local_iterator");
std::cerr << "Checked: " << count_checked << " elements" << std::endl;
} else {
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;
// Finally, check that size matches up.
if(x1.size() != size)
BOOST_ERROR("x1.size() doesn't match actual size.");
float load_factor = static_cast<float>(size) / static_cast<float>(x1.bucket_count());
using namespace std;
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
}
// Check the load factor.
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.
typename X::size_type bucket_size = 0;
for (typename X::size_type i = 0; i < x1.bucket_count(); ++i) {
for (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 defined(BOOST_MSVC)
@@ -128,3 +102,4 @@ namespace test {
#endif
#endif
+232 -293
View File
@@ -1,5 +1,5 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,317 +11,256 @@
#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)
{
for (; begin != end; ++begin, ++compare)
if (*begin != *compare)
return false;
return true;
}
namespace test
{
template <typename T> class list;
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
namespace test_detail
{
list_node(list_node const&);
list_node& operator=(list_node const&);
template <typename T> struct list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
public:
T value_;
list_node* next_;
template <typename T>
struct list_node
{
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) {}
};
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;
template <typename T> class list_data
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 list_node<T> node;
typedef unsigned int size_type;
typedef T value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
typedef test::test_detail::list_iterator<T> iterator;
typedef test::test_detail::list_const_iterator<T> const_iterator;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
list() : data_() {}
~list_data()
{
while (first_) {
node* tmp = first_;
first_ = first_->next_;
delete tmp;
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());
}
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_) 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_.last_ptr_ = &data_.first_;
}
void erase(const_iterator start, const_iterator end) {
node** ptr = &data_.first_;
while(*ptr != start.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != end.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
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() &&
std::equal(begin(), end(), y.begin());
}
bool operator!=(list const& y) const {
return !(*this == y);
}
}
private:
list_data(list_data const&);
list_data& operator=(list_data const&);
};
template <typename T> class list_iterator
{
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:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
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
{
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:
typedef T value_type;
typedef T const* pointer;
typedef T const& reference;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
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_)
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_.last_ptr_ = &data_.first_;
}
void erase(const_iterator i, const_iterator j)
{
node** ptr = &data_.first_;
while (*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while (*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
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)
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)
{
while(first != second) {
if(less((*second)->value_, (*first)->value_)) {
swap_adjacent_ranges(first, second, third);
std::swap(second, third);
}
first = &(*first)->next_;
}
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_;
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;
}
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
+138 -157
View File
@@ -1,189 +1,170 @@
// Copyright 2006-2009 Daniel James.
// 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)
#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/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include "../helpers/test.hpp"
namespace test {
namespace detail {
struct memory_area
namespace test
{
namespace detail
{
void const* start;
void const* end;
// This annoymous namespace won't cause ODR violations as I won't
// be linking multiple translation units together. I'll probably
// move this into a cpp file before a full release, but for now it's
// the most convenient way.
memory_area(void const* s, void const* e) : start(s), end(e)
{
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) {}
memory_area(void const* s, void const* e)
: start(s), end(e)
{
BOOST_ASSERT(start != end);
}
};
int constructed_;
int tag_;
};
struct memory_track {
explicit memory_track(int tag = -1) :
constructed_(0),
tag_(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.
int constructed_;
int tag_;
};
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
{
return x.end <= y.start;
}
};
// 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_tracker
{
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> > >
allocated_memory_type;
struct memory_area_compare {
bool operator()(memory_area const& x, memory_area const& y) const {
return x.end <= y.start;
}
};
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
bool tracking_constructions;
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
Alloc> type;
};
memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0),
tracking_constructions(true)
{
}
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_memory_type_gen<int> {
typedef std::map<memory_area, memory_track, memory_area_compare> type;
};
#endif
~memory_tracker() { BOOST_TEST(count_allocators == 0); }
template <class Alloc = std::allocator<int> >
struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc,
std::pair<memory_area const, memory_track> >::type
allocator_type;
void allocator_ref()
{
if (count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
typedef BOOST_DEDUCED_TYPENAME allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
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();
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
memory_tracker() :
count_allocators(0), count_allocations(0),
count_constructions(0)
{}
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
}
void allocator_ref()
{
if(count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
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 allocator_unref()
{
BOOST_CHECK(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();
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;
}
// Clearing the data before the checks terminate the tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
++count_constructions;
}
}
BOOST_CHECK(no_allocations_left);
BOOST_CHECK(no_constructions_left);
BOOST_CHECK(allocated_memory_empty);
}
}
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
--count_constructions;
}
}
};
}
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)));
}
}
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_deallocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
BOOST_DEDUCED_TYPENAME 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_CHECK(pos->first.start == ptr);
BOOST_CHECK(pos->first.end == (char*) ptr + n * size);
BOOST_CHECK(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_CHECK(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_CHECK(count_constructions > 0);
if(count_constructions > 0) --count_constructions;
}
};
}
}
namespace detail {
struct disable_construction_tracking
{
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{
test::detail::tracker.tracking_constructions = false;
}
~disable_construction_tracking()
{
test::detail::tracker.tracking_constructions = old_value;
}
private:
disable_construction_tracking(disable_construction_tracking const&);
disable_construction_tracking& operator=(
disable_construction_tracking const&);
};
}
}
#endif
+67 -16
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,23 +8,74 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test {
template <class Container>
struct is_set : public boost::is_same<typename Container::key_type,
typename Container::value_type>
{
};
namespace test
{
/*
struct unordered_set_type { char x[100]; };
struct unordered_multiset_type { char x[200]; };
struct unordered_map_type { char x[300]; };
struct unordered_multimap_type { char x[400]; };
template <class Container> struct has_unique_keys
{
static char flip(typename Container::iterator const&);
static long flip(std::pair<typename Container::iterator, bool> const&);
BOOST_STATIC_CONSTANT(bool,
value = sizeof(long) ==
sizeof(flip(
((Container*)0)->insert(*(typename Container::value_type*)0))));
};
template <class V, class H, class P, class A>
unordered_set_type container_type(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
unordered_multiset_type container_type(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_map_type container_type(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_multimap_type container_type(
boost::unordered_multimap<K, M, H, P, A> const*);
*/
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 is_map
: public boost::mpl::not_<is_set<Container> > {};
struct yes_type { char x[100]; };
struct no_type { char x[200]; };
template <class V, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(yes_type));
};
template <class Container>
struct has_equivalent_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
};
}
#endif
-10
View File
@@ -1,10 +0,0 @@
// Copyright 2012 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 this after the boost headers, but before other test headers.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
-11
View File
@@ -1,11 +0,0 @@
// Copyright 2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if defined(_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 :
// nameless struct/union
#endif
+80 -78
View File
@@ -1,109 +1,111 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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 <boost/mpl/if.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
namespace test {
template <class X> struct unordered_generator_set
{
typedef typename X::value_type value_type;
namespace test
{
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;
for(std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr);
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(value);
}
}
}
}
}
};
};
template <class X> struct unordered_generator_map
{
typedef typename X::key_type key_type;
typedef 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);
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(std::pair<key_type const, mapped_type>(key, generate(mapped_ptr)));
}
}
}
}
}
};
};
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 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::mpl::if_<
test::is_set<X>,
test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
{
}
};
};
template <class X>
struct random_values : public test::list<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)
{
static test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
}
#endif
+24 -27
View File
@@ -1,42 +1,39 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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 "./metafunctions.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
namespace test {
template <class X> class strong
{
typedef test::list<typename X::value_type> values_type;
values_type values_;
unsigned int allocations_;
public:
void store(X const& x, unsigned int allocations = 0)
namespace test
{
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_;
public:
void store(X const& x) {
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
}
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) const {
if(!(x.size() == values_.size() &&
std::equal(x.cbegin(), x.cend(), values_.begin(),
test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
}
};
}
#endif
+71 -170
View File
@@ -1,201 +1,102 @@
// Copyright 2006-2009 Daniel James.
// 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)
#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
#define BOOST_UNORDERED_TEST_TEST_HEADER
#include <boost/core/lightweight_test.hpp>
#if defined(BOOST_UNORDERED_FULL_TEST)
#include <boost/test/test_tools.hpp>
#define UNORDERED_AUTO_TEST(x) BOOST_AUTO_TEST_CASE(x)
#define RUN_TESTS()
#else
#include <boost/test/minimal.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \
BOOST_PP_CAT(x, _type) \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::get_state().add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
#define RUN_TESTS() \
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(); \
return boost::report_errors(); \
}
#define RUN_TESTS_QUIET() \
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(true); \
return boost::report_errors(); \
}
#define UNORDERED_SUB_TEST(x) \
for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
UNORDERED_SUB_TEST_VALUE; \
UNORDERED_SUB_TEST_VALUE = \
::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
#define 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 test_main(int, char**) { ::test::test_list::run_tests(); return 0; }
namespace test {
struct registered_test_base {
registered_test_base* next;
char const* name;
explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0;
virtual ~registered_test_base() {}
};
struct registered_test_base
{
registered_test_base* next;
char const* name;
explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0;
virtual ~registered_test_base() {}
};
struct state
{
bool is_quiet;
registered_test_base* first_test;
registered_test_base* last_test;
state() : is_quiet(false), first_test(0), last_test(0) {}
void add_test(registered_test_base* test)
{
if (last_test) {
last_test->next = test;
} else {
first_test = test;
}
last_test = test;
}
void run_tests(bool quiet = false)
{
is_quiet = quiet;
for (registered_test_base* i = first_test; i; i = i->next) {
int error_count = boost::detail::test_errors();
if (!quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
<< std::flush;
namespace test_list {
static inline registered_test_base*& first() {
static registered_test_base* ptr = 0;
return ptr;
}
i->run();
BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
if (quiet && error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name << "\n"
<< std::flush;
static inline registered_test_base*& last() {
static registered_test_base* ptr = 0;
return ptr;
}
}
}
int start_sub_test(char const* name)
{
if (!is_quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
<< std::flush;
}
// Add one because it's used as a loop condition.
return boost::detail::test_errors() + 1;
}
static inline void add_test(registered_test_base* test) {
if(last()) {
last()->next = test;
}
else {
first() = test;
}
int end_sub_test(char const* name, int value)
{
if (is_quiet && value != boost::detail::test_errors() + 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name << "\n"
<< std::flush;
}
return 0;
}
};
last() = test;
}
// Get the currnet translation unit's test state.
static inline state& get_state()
{
static state instance;
return instance;
}
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;
}
}
}
}
#if defined(__cplusplus)
#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
#else
#define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
#endif
#define BOOST_UNORDERED_TEST_COMPILER_INFO() \
{ \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Compiler: " << BOOST_COMPILER << "\n" \
<< "Library: " << BOOST_STDLIB << "\n" \
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
<< "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
<< "\n" \
<< "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
<< BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
<< BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
<< std::flush; \
}
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/cat.hpp>
// Run test with every combination of the parameters (a sequence of sequences)
#define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
#define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name)) 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_HEAD(product), \
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, params) \
UNORDERED_AUTO_TEST(BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
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_MULTI_TEST(name, impl, parameters) \
UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
UNORDERED_AUTO_TEST (name) { \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
}
#define UNORDERED_MULTI_TEST_OP(r, product) \
UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
#define UNORDERED_MULTI_TEST_OP2(name, n, params) \
{ \
UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
{ \
for (int i = 0; i < n; ++i) \
name BOOST_PP_SEQ_TO_TUPLE(params); \
} \
}
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#endif
+134 -115
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
@@ -9,130 +9,149 @@
#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/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#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
{
typedef std::less<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<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<typename X::value_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, true, false>
{
typedef std::multiset<typename X::value_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, true>
{
typedef std::map<typename X::key_type, typename X::mapped_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, false>
{
typedef std::multimap<typename X::key_type, typename X::mapped_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <class X> class ordered : public ordered_base<X>::type
{
typedef typename ordered_base<X>::type base;
public:
typedef 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, typename X::value_type const& val)
namespace test
{
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
{
compare_pairs(x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)), (typename X::value_type*)0);
};
template <class X>
struct equals_to_compare
: public boost::mpl::eval_if<
boost::is_same<X, test::equal_to>,
boost::mpl::identity<test::less>,
equals_to_compare2<X>
>
{
};
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_CHECK(values1.size() == values2.size() &&
std::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_CHECK(values1.size() == values2.size() &&
std::equal(values1.begin(), values1.end(), values2.begin(), test::equivalent));
}
};
template <class Equals>
typename equals_to_compare<Equals>::type create_compare(Equals const&)
{
typename equals_to_compare<Equals>::type x;
return x;
}
template <class X>
struct ordered_set
: public boost::mpl::if_<
test::has_unique_keys<X>,
std::set<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>,
std::multiset<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
> {};
template <class X> ordered<X> create_ordered(X const& container)
{
return ordered<X>(create_compare(container.key_eq()));
}
template <class X>
struct ordered_map
: public boost::mpl::if_<
test::has_unique_keys<X>,
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>,
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>
> {};
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 X>
struct ordered_base
: public boost::mpl::eval_if<
test::is_set<X>,
test::ordered_set<X>,
test::ordered_map<X> >
{
};
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& compare)
: base(compare)
{}
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 begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
}
}
};
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 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
-344
View File
@@ -1,344 +0,0 @@
// Copyright 2006-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)
#if !defined(BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <cstddef>
#include "../helpers/fwd.hpp"
#include "../helpers/memory.hpp"
namespace test {
struct allocator_false
{
enum
{
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
};
};
};
template <typename Flag> struct assign_allocator_base
{
struct propagate_on_container_copy_assignment
{
enum
{
value = Flag::is_propagate_on_assign
};
};
};
template <typename Flag> struct move_allocator_base
{
struct propagate_on_container_move_assignment
{
enum
{
value = Flag::is_propagate_on_move
};
};
};
namespace {
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
struct force_equal_allocator
{
bool old_value_;
explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value)
{
force_equal_allocator_value = value;
}
~force_equal_allocator() { force_equal_allocator_value = old_value_; }
};
template <typename T> struct cxx11_allocator_base
{
int tag_;
int selected_;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
explicit cxx11_allocator_base(int t) : tag_(t), selected_(0)
{
detail::tracker.allocator_ref();
}
template <typename Y>
cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer allocate(size_type n)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate(
(void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
::operator delete((void*)p);
}
void construct(T* p, T const& t)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... Args>
void construct(T* p, BOOST_FWD_REF(Args)... args)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const
{
return (std::numeric_limits<size_type>::max)();
}
};
template <typename T, typename Flags = propagate_swap, typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind
{
typedef cxx11_allocator<U, Flags> other;
};
#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)
{
}
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>
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;
};
#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)
{
}
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_;
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
template <typename T> convert_from_anything(T const&) {}
};
inline int selected_count(convert_from_anything) { return 0; }
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
return x.selected_;
}
}
#endif
+292 -631
View File
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -1,17 +1,18 @@
// Copyright 2006-2009 Daniel James.
// 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)
#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
+158 -496
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2009 Daniel James.
// 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)
@@ -10,616 +10,278 @@
#if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER)
#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
#include <boost/move/move.hpp>
#include <cstddef>
#include <utility>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4100) // unreferenced formal parameter
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test {
namespace minimal {
class destructible;
namespace test
{
namespace minimal
{
class copy_constructible;
class copy_constructible_equality_comparable;
class default_assignable;
class default_copy_constructible;
class assignable;
struct ampersand_operator_used
{
ampersand_operator_used() { BOOST_TEST(false); }
};
template <class T> class hash;
template <class T> class equal_to;
template <class T> class ptr;
template <class T> class const_ptr;
template <class T> class allocator;
template <class T> class cxx11_allocator;
struct constructor_param
{
operator int() const { return 0; }
};
class destructible
{
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
};
class copy_constructible
{
public:
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
static copy_constructible create() { return copy_constructible(); }
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
};
class copy_constructible_equality_comparable
{
public:
copy_constructible_equality_comparable(constructor_param const&) {}
copy_constructible_equality_comparable(
copy_constructible_equality_comparable const&)
{
}
~copy_constructible_equality_comparable() {}
void dummy_member() const {}
static copy_constructible_equality_comparable create() { return copy_constructible_equality_comparable(); }
copy_constructible_equality_comparable(copy_constructible_equality_comparable const&) {}
~copy_constructible_equality_comparable() {}
private:
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
copy_constructible_equality_comparable& operator=(copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
};
bool operator==(copy_constructible_equality_comparable,
copy_constructible_equality_comparable)
{
return true;
bool operator==(copy_constructible_equality_comparable, copy_constructible_equality_comparable) {
return true;
}
bool operator!=(copy_constructible_equality_comparable,
copy_constructible_equality_comparable)
{
return false;
bool operator!=(copy_constructible_equality_comparable, copy_constructible_equality_comparable) {
return false;
}
class default_assignable
class default_copy_constructible
{
public:
default_assignable(constructor_param const&) {}
default_assignable() {}
default_assignable(default_assignable const&) {}
default_assignable& operator=(default_assignable const&) { return *this; }
~default_assignable() {}
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
static default_copy_constructible create() { return default_copy_constructible(); }
default_copy_constructible() {}
default_copy_constructible(default_copy_constructible const&) {}
~default_copy_constructible() {}
private:
default_copy_constructible& operator=(default_copy_constructible const&);
};
class assignable
{
public:
assignable(constructor_param const&) {}
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
void dummy_member() const {}
static assignable create() { return assignable(); }
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
private:
assignable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
assignable() {}
};
struct movable_init
{
};
class movable1
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1)
public:
movable1(constructor_param const&) {}
movable1() {}
explicit movable1(movable_init) {}
movable1(BOOST_RV_REF(movable1)) {}
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
~movable1() {}
void dummy_member() const {}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
class movable2
template <class T>
class hash
{
public:
movable2(constructor_param const&) {}
explicit movable2(movable_init) {}
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
static hash create() { return hash<T>(); }
hash() {}
hash(hash const&) {}
hash& operator=(hash const&) { return *this; }
~hash() {}
private:
movable2() {}
movable2(movable2 const&);
movable2& operator=(movable2 const&);
};
#else
typedef movable1 movable2;
#endif
template <class T> class hash
{
public:
hash(constructor_param const&) {}
hash() {}
hash(hash const&) {}
hash& operator=(hash const&) { return *this; }
~hash() {}
std::size_t operator()(T const&) const { return 0; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
std::size_t operator()(T const&) const { return 0; }
};
template <class T> class equal_to
template <class T>
class equal_to
{
public:
equal_to(constructor_param const&) {}
equal_to() {}
equal_to(equal_to const&) {}
equal_to& operator=(equal_to const&) { return *this; }
~equal_to() {}
static equal_to create() { return equal_to<T>(); }
equal_to() {}
equal_to(equal_to const&) {}
equal_to& operator=(equal_to const&) { return *this; }
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
bool operator()(T const&, T const&) const { return true; }
};
template <class T> class ptr;
template <class T> class const_ptr;
struct void_ptr
template <class T>
class ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class ptr;
friend class allocator<T>;
friend class const_ptr<T>;
private:
#endif
void* ptr_;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
void_ptr() : ptr_(0) {}
ptr() : ptr_(0) {}
template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
ptr& operator++() { ++ptr_; return *this; }
ptr operator++(int) { ptr tmp(*this); ++ptr_; return tmp; }
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator==(const_ptr<T> const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr<T> const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr<T> const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr<T> const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr<T> const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr<T> const& x) const { return ptr_ >= x.ptr_; }
};
class void_const_ptr
template <class T>
class const_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class const_ptr;
friend class allocator<T>;
private:
#endif
void* ptr_;
T const* ptr_;
const_ptr(T const* ptr) : ptr_(ptr) {}
public:
void_const_ptr() : ptr_(0) {}
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
template <typename T>
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_)
{
}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
const_ptr& operator++() { ++ptr_; return *this; }
const_ptr operator++(int) { const_ptr tmp(*this); ++ptr_; return tmp; }
const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); }
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) { return ptr<T>(s + p.ptr_); }
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
operator bool() const { return !!ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(ptr<T> const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr<T> const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr<T> const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr<T> const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr<T> const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr<T> const& x) const { return ptr_ >= x.ptr_; }
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
};
template <class T> class ptr
{
friend class allocator<T>;
friend class const_ptr<T>;
friend struct void_ptr;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
ptr& operator++()
{
++ptr_;
return *this;
}
ptr operator++(int)
{
ptr tmp(*this);
++ptr_;
return tmp;
}
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p)
{
return ptr<T>(s + p.ptr_);
}
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
};
template <class T> class const_ptr
{
friend class allocator<T>;
friend struct const_void_ptr;
T const* ptr_;
const_ptr(T const* ptr) : ptr_(ptr) {}
public:
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
const_ptr& operator++()
{
++ptr_;
return *this;
}
const_ptr operator++(int)
{
const_ptr tmp(*this);
++ptr_;
return tmp;
}
const_ptr operator+(std::ptrdiff_t s) const
{
return const_ptr(ptr_ + s);
}
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
{
return ptr<T>(s + p.ptr_);
}
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
operator bool() const { return !!ptr_; }
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
};
template <class T> class allocator
template <class T>
class allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind
{
typedef allocator<U> other;
};
template <class U> struct rebind { typedef allocator<U> other; };
allocator() {}
template <class Y> allocator(allocator<Y> const&) {}
allocator(allocator const&) {}
~allocator() {}
allocator() {}
template <class Y> allocator(allocator<Y> const&) {}
allocator(allocator const&) {}
~allocator() {}
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer allocate(size_type n)
{
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n) {
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
template <class Y> pointer allocate(size_type n, const_ptr<Y>)
{
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
template <class Y>
pointer allocate(size_type n, const_ptr<Y> u)
{
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
void deallocate(pointer p, size_type)
{
::operator delete((void*)p.ptr_);
}
void deallocate(pointer p, size_type)
{
::operator delete((void*) p.ptr_);
}
void construct(T* p, T const& t) { new ((void*)p) T(t); }
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
{
new ((void*)p) T(boost::forward<Args>(args)...);
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template<class... Args> void construct(pointer p, Args&&... args) {
new((void*)p.ptr_) T(std::forward<Args>(args)...);
}
#endif
void destroy(T* p) { p->~T(); }
void destroy(pointer p) { ((T*)p.ptr_)->~T(); }
size_type max_size() const { return 1000; }
size_type max_size() const { return 1000; }
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
public:
allocator& operator=(allocator const&) { return *this; }
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
BOOST_WORKAROUND(MSVC, <= 1300)
public: allocator& operator=(allocator const&) { return *this;}
#else
private:
allocator& operator=(allocator const&);
#endif
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
#endif
};
template <class T> class allocator<T const>
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
// Maybe these two should be const_ptr<T>
typedef ptr<T const> pointer;
typedef const_ptr<T const> const_pointer;
typedef T const& reference;
typedef T const& const_reference;
typedef T const value_type;
template <class U> struct rebind
{
typedef allocator<U> other;
};
allocator() {}
template <class Y> allocator(allocator<Y> const&) {}
allocator(allocator const&) {}
~allocator() {}
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer allocate(size_type n)
{
return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
}
template <class Y> pointer allocate(size_type n, const_ptr<Y>)
{
return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
}
void deallocate(pointer p, size_type)
{
::operator delete((void*)p.ptr_);
}
void construct(T const* p, T const& t) { new ((void*)p) T(t); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
void construct(T const* p, BOOST_FWD_REF(Args)... args)
{
new ((void*)p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T const* p) { p->~T(); }
size_type max_size() const { return 1000; }
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
public:
allocator& operator=(allocator const&) { return *this; }
#else
private:
allocator& operator=(allocator const&);
#endif
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const
{
return ampersand_operator_used();
}
private: allocator& operator=(allocator const&);
#endif
};
template <class T>
inline bool operator==(allocator<T> const&, allocator<T> const&)
{
return true;
return true;
}
template <class T>
inline bool operator!=(allocator<T> const&, allocator<T> const&)
{
return false;
}
template <class T> void swap(allocator<T>&, allocator<T>&) {}
// C++11 allocator
//
// Not a fully minimal C++11 allocator, just what I support. Hopefully will
// cut down further in the future.
template <class T> class cxx11_allocator
{
public:
typedef T value_type;
// template <class U> struct rebind { typedef cxx11_allocator<U> other; };
cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
cxx11_allocator(cxx11_allocator const&) {}
~cxx11_allocator() {}
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)));
}
template <class Y> T* allocate(std::size_t n, const_ptr<Y>)
{
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 ((void*)p) T(t); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
{
new ((void*)p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p) { p->~T(); }
std::size_t max_size() const { return 1000u; }
};
template <class T>
inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
{
return true;
return false;
}
template <class T>
inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
void swap(allocator<T>&, allocator<T>&)
{
return false;
}
template <class T> void swap(cxx11_allocator<T>&, cxx11_allocator<T>&) {}
}
}
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost {
#else
namespace test {
namespace minimal {
namespace minimal {
#endif
std::size_t hash_value(test::minimal::copy_constructible_equality_comparable)
{
return 1;
}
std::size_t hash_value(test::minimal::copy_constructible_equality_comparable) {
return 1;
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
}
}
}}
#else
}
}
#endif
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
+241 -649
View File
@@ -1,700 +1,292 @@
// Copyright 2006-2009 Daniel James.
// 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)
#if !defined(BOOST_UNORDERED_TEST_OBJECTS_HEADER)
#define BOOST_UNORDERED_TEST_OBJECTS_HEADER
#include "../helpers/count.hpp"
#include "../helpers/fwd.hpp"
#include "../helpers/memory.hpp"
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <cstddef>
#include <iostream>
#include "../helpers/fwd.hpp"
#include "../helpers/count.hpp"
#include "../helpers/memory.hpp"
#include <map>
namespace test {
// Note that the default hash function will work for any equal_to (but not
// very well).
class object;
class movable;
class implicitly_convertible;
class hash;
class less;
class equal_to;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*, random_generator);
movable generate(movable const*, random_generator);
implicitly_convertible generate(
implicitly_convertible const*, random_generator);
namespace test
{
// Note that the default hash function will work for any equal_to (but not
// very well).
class object;
class hash;
class less;
class equal_to;
template <class T> class allocator;
object generate(object const*);
inline void ignore_variable(void const*) {}
class object : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
int tag1_, tag2_;
public:
explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
~object()
class object : globally_counted_object
{
tag1_ = -1;
tag2_ = -1;
}
friend class hash;
friend class equal_to;
friend class less;
int tag1_, tag2_;
public:
explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
friend bool operator==(object const& x1, object const& x2)
{
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
~object() {
tag1_ = -1;
tag2_ = -1;
}
friend bool operator!=(object const& x1, object const& x2)
{
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend bool operator==(object const& x1, object const& x2) {
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
friend bool operator<(object const& x1, object const& x2)
{
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend bool operator!=(object const& x1, object const& x2) {
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend object generate(object const*, random_generator g)
{
int* x = 0;
return object(generate(x, g), generate(x, g));
}
friend bool operator<(object const& x1, object const& x2) {
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend std::ostream& operator<<(std::ostream& out, object const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
friend object generate(object const*) {
int* x = 0;
return object(generate(x), generate(x));
}
class movable : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
int tag1_, tag2_;
BOOST_COPYABLE_AND_MOVABLE(movable)
public:
explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
movable(movable const& x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
}
movable(BOOST_RV_REF(movable) x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
x.tag1_ = -1;
x.tag2_ = -1;
}
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
return *this;
}
movable& operator=(BOOST_RV_REF(movable) x) // Move assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
x.tag1_ = -1;
x.tag2_ = -1;
return *this;
}
~movable()
{
tag1_ = -1;
tag2_ = -1;
}
friend bool operator==(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
friend bool operator!=(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend bool operator<(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend movable generate(movable const*, random_generator g)
{
int* x = 0;
return movable(generate(x, g), generate(x, g));
}
friend std::ostream& operator<<(std::ostream& out, movable const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
class implicitly_convertible : private counted_object
{
int tag1_, tag2_;
public:
explicit implicitly_convertible(int t1 = 0, int t2 = 0)
: tag1_(t1), tag2_(t2)
{
}
operator object() const { return object(tag1_, tag2_); }
operator movable() const { return movable(tag1_, tag2_); }
friend implicitly_convertible generate(
implicitly_convertible const*, random_generator g)
{
int* x = 0;
return implicitly_convertible(generate(x, g), generate(x, g));
}
friend std::ostream& operator<<(
std::ostream& out, implicitly_convertible const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
// Note: This is a deliberately bad hash function.
class hash
{
int type_;
public:
hash() : type_(0) {}
explicit hash(int t) : type_(t) {}
std::size_t operator()(object const& x) const
{
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(movable const& x) const
{
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(int x) const
{
int result;
switch (type_) {
case 1:
result = x;
break;
case 2:
result = x * 7;
break;
default:
result = x * 256;
}
return static_cast<std::size_t>(result);
}
friend bool operator==(hash const& x1, hash const& x2)
{
return x1.type_ == x2.type_;
}
friend bool operator!=(hash const& x1, hash const& x2)
{
return x1.type_ != x2.type_;
}
};
std::size_t hash_value(test::object const& x) { return hash()(x); }
std::size_t hash_value(test::movable const& x) { return hash()(x); }
class less
{
int type_;
public:
explicit less(int t = 0) : type_(t) {}
bool operator()(object const& x1, object const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
bool operator()(movable const& x1, movable const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
std::size_t operator()(int x1, int x2) const { return x1 < x2; }
friend bool operator==(less const& x1, less const& x2)
{
return x1.type_ == x2.type_;
}
};
class equal_to
{
int type_;
public:
equal_to() : type_(0) {}
explicit equal_to(int t) : type_(t) {}
bool operator()(object const& x1, object const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
bool operator()(movable const& x1, movable const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
std::size_t operator()(int x1, int x2) const { return x1 == x2; }
friend bool operator==(equal_to const& x1, equal_to const& x2)
{
return x1.type_ == x2.type_;
}
friend bool operator!=(equal_to const& x1, equal_to const& x2)
{
return x1.type_ != x2.type_;
}
friend less create_compare(equal_to x) { return less(x.type_); }
};
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class.
template <class T> class allocator1
{
public:
int tag_;
typedef T value_type;
template <class U> struct rebind
{
typedef allocator1<U> other;
friend std::ostream& operator<<(std::ostream& out, object const& o)
{
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
}
};
allocator1() : tag_(0) { detail::tracker.allocator_ref(); }
explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_)
class hash
{
detail::tracker.allocator_ref();
}
int type_;
public:
explicit hash(int t = 0) : type_(t) {}
allocator1(allocator1 const& x) : tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
std::size_t operator()(object const& x) const {
switch(type_) {
case 1:
return x.tag1_;
case 2:
return x.tag2_;
default:
return x.tag1_ + x.tag2_;
}
}
~allocator1() { detail::tracker.allocator_unref(); }
std::size_t operator()(int x) const {
return x;
}
T* allocate(std::size_t n)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
friend bool operator==(hash const& x1, hash const& x2) {
return x1.type_ == x2.type_;
}
T* allocate(std::size_t n, void const*)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(T* p, std::size_t n)
{
detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
::operator delete((void*)p);
}
#if BOOST_UNORDERED_CXX11_CONSTRUCTION
template <typename U, typename... Args> void construct(U* p, Args&&... args)
{
detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...);
}
template <typename U> void destroy(U* p)
{
detail::tracker.track_destroy((void*)p, sizeof(U), tag_);
p->~U();
// Work around MSVC buggy unused parameter warning.
ignore_variable(&p);
}
#else
private:
// I'm going to claim in the documentation that construct/destroy
// is never used when C++11 support isn't available, so might as
// well check that in the text.
// TODO: Or maybe just disallow them for values?
template <typename U> void construct(U* p);
template <typename U, typename A0> void construct(U* p, A0 const&);
template <typename U, typename A0, typename A1>
void construct(U* p, A0 const&, A1 const&);
template <typename U, typename A0, typename A1, typename A2>
void construct(U* p, A0 const&, A1 const&, A2 const&);
template <typename U> void destroy(U* p);
public:
#endif
bool operator==(allocator1 const& x) const { return tag_ == x.tag_; }
bool operator!=(allocator1 const& x) const { return tag_ != x.tag_; }
enum
{
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
template <class T> class ptr;
template <class T> class const_ptr;
struct void_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class ptr;
private:
#endif
void* ptr_;
public:
void_ptr() : ptr_(0) {}
template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
};
class void_const_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class const_ptr;
private:
#endif
void* ptr_;
public:
void_const_ptr() : ptr_(0) {}
template <typename T>
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_)
{
}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
};
template <class T> class ptr
{
friend class allocator2<T>;
friend class const_ptr<T>;
friend struct void_ptr;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
ptr& operator++()
{
++ptr_;
return *this;
}
ptr operator++(int)
{
ptr tmp(*this);
++ptr_;
return tmp;
}
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
};
template <class T> class const_ptr
{
friend class allocator2<T>;
friend struct const_void_ptr;
T const* ptr_;
const_ptr(T const* ptr) : ptr_(ptr) {}
public:
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
const_ptr& operator++()
{
++ptr_;
return *this;
}
const_ptr operator++(int)
{
const_ptr tmp(*this);
++ptr_;
return tmp;
}
const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); }
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
{
return ptr<T>(s + p.ptr_);
}
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
operator bool() const { return !!ptr_; }
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
};
template <class T> class allocator2
{
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
#else
template <class> friend class allocator2;
#endif
int tag_;
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind
{
typedef allocator2<U> other;
friend bool operator!=(hash const& x1, hash const& x2) {
return x1.type_ != x2.type_;
}
};
allocator2() : tag_(0) { detail::tracker.allocator_ref(); }
explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
class less
{
detail::tracker.allocator_ref();
int type_;
public:
explicit less(int t = 0) : type_(t) {}
bool operator()(object const& x1, object const& x2) const {
switch(type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 < x2;
}
friend bool operator==(less const& x1, less const& x2) {
return x1.type_ == x2.type_;
}
};
class equal_to
{
int type_;
public:
explicit equal_to(int t = 0) : type_(t) {}
bool operator()(object const& x1, object const& x2) const {
switch(type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 == x2;
}
friend bool operator==(equal_to const& x1, equal_to const& x2) {
return x1.type_ == x2.type_;
}
friend bool operator!=(equal_to const& x1, equal_to const& x2) {
return x1.type_ != x2.type_;
}
friend less create_compare(equal_to x) {
return less(x.type_);
}
};
namespace detail
{
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker<std::allocator<int> > tracker;
}
}
allocator2(allocator2 const& x) : tag_(x.tag_)
template <class T>
class allocator
{
detail::tracker.allocator_ref();
}
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
# else
template <class> friend class allocator;
# endif
int tag_;
public:
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;
~allocator2() { detail::tracker.allocator_unref(); }
template <class U> struct rebind { typedef allocator<U> other; };
pointer address(reference r) { return pointer(&r); }
explicit allocator(int t = 0) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); }
allocator(allocator const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); }
~allocator() { detail::tracker.allocator_unref(); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
pointer allocate(size_type n)
{
pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_);
return p;
}
pointer allocate(size_type n) {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
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)
{
detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_);
::operator delete((void*)p.ptr_);
}
void deallocate(pointer p, size_type n)
{
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
::operator delete((void*) p);
}
void construct(T* p, T const& t)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
}
void construct(pointer 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 <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template<class... Args> void construct(pointer p, Args&&... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(std::forward<Args>(args)...);
}
#endif
void destroy(T* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
}
void destroy(pointer p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const
{
return (std::numeric_limits<size_type>::max)();
}
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator2 const& x) const { return tag_ == x.tag_; }
bool operator==(allocator const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator2 const& x) const { return tag_ != x.tag_; }
enum
{
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
bool operator!=(allocator const& x) const
{
return tag_ != x.tag_;
}
};
};
template <class T>
bool equivalent_impl(
allocator1<T> const& x, allocator1<T> const& y, test::derived_type)
{
return x == y;
}
template <class T>
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y, test::derived_type) {
return x == y;
}
template <class T>
bool equivalent_impl(
allocator2<T> const& x, allocator2<T> const& y, test::derived_type)
{
return x == y;
}
#if BOOST_WORKAROUND(__GNUC__, < 3)
void swap(test::object& x, test::object& y) {
test::object tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::hash& x, test::hash& y) {
test::hash tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::less& x, test::less& y) {
test::less tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::equal_to& x, test::equal_to& y) {
test::equal_to tmp;
tmp = x;
x = y;
y = tmp;
}
template <class T>
void swap(test::allocator<T>& x, test::allocator<T>& y) {
test::allocator<T> tmp;
tmp = x;
x = y;
y = tmp;
}
#endif
}
#endif
+38
View File
@@ -0,0 +1,38 @@
# 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
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
#<toolset>msvc:<cxxflags>/W4
;
test-suite unordered
:
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run simple_tests.cpp ]
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
[ run copy_tests.cpp ]
[ run move_tests.cpp : : : <test-info>always_show_run_output ]
[ 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 : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
-288
View File
@@ -1,288 +0,0 @@
// Copyright 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)
#include <boost/core/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>
// 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&) const { return true; } \
bool operator!=(name<T> const&) 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; } \
/**/
struct yes_type
{
enum
{
value = true
};
};
struct no_type
{
enum
{
value = false
};
};
// For tracking calls...
static int selected;
void reset() { selected = 0; }
template <typename Allocator> int call_select()
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected;
}
// Empty allocator test
template <typename T> struct empty_allocator
{
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
};
void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
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));
#endif
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::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 0);
}
// allocator 1
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;
typedef yes_type is_always_equal;
allocator1<T> select_on_container_copy_construction() const
{
++selected;
return allocator1<T>();
}
};
void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
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));
#endif
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::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 2
template <typename Alloc> struct allocator2_base
{
Alloc select_on_container_copy_construction() const
{
++selected;
return Alloc();
}
};
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;
typedef no_type is_always_equal;
};
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::pointer, int*>::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);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 3
template <typename T> struct ptr
{
T* value_;
ptr(void* v) : value_((T*)v) {}
T& operator*() const { return *value_; }
};
template <> struct ptr<void>
{
void* value_;
ptr(void* v) : value_(v) {}
};
template <> struct ptr<const void>
{
void const* value_;
ptr(void const* v) : value_(v) {}
};
template <typename T> struct allocator3
{
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
int x; // Just to make it non-empty, so that is_always_equal is false.
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
{
++selected;
return allocator3<T>();
}
};
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::pointer, ptr<int> >::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);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
int main()
{
test_empty_allocator();
test_allocator1();
test_allocator2();
test_allocator3();
return boost::report_errors();
}
+68 -257
View File
@@ -1,297 +1,108 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
#include <iostream>
namespace assign_tests {
test::seed_t initialize_seed(96785);
test::seed_t seed(96785);
template <class T> void assign_tests1(T*, test::random_generator generator)
{
typename T::hasher hf;
typename T::key_equal eq;
template <class T>
void assign_tests1(T*, test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
std::cerr<<"assign_tests1.1\n";
{
test::check_instances check_;
T x;
x = x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
T x;
x = x;
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
std::cerr<<"assign_tests1.2\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
test::ordered<T> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
test::ordered<T> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
x = x;
tracker.compare(x);
x = x;
tracker.compare(x);
T y;
y.max_load_factor(x.max_load_factor() / 20);
float mlf = x.max_load_factor();
y = x;
tracker.compare(x);
tracker.compare(y);
BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf);
BOOST_TEST(y.load_factor() <= y.max_load_factor());
T y;
y.max_load_factor(x.max_load_factor() / 20);
y = x;
tracker.compare(y);
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
}
}
}
template <class T> void assign_tests2(T*, test::random_generator generator)
{
typename T::hasher hf1(1);
typename T::hasher hf2(2);
typename T::key_equal eq1(1);
typename T::key_equal eq2(2);
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
template <class T>
void assign_tests2(T*, test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
BOOST_DEDUCED_TYPENAME T::key_equal eq1(1);
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 typename T::allocator_type allocator_type;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n";
std::cerr<<"assign_tests2.1\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);
test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
test::check_container(x2, v);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
std::cerr<<"assign_tests2.2\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, v);
test::check_container(x2, v);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x2.get_allocator(), al2));
test::check_container(x2, v1);
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
{
test::check_instances check_;
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
test::random_values<T> v1(0, generator);
test::random_values<T> v2(1000, generator);
T x1(0, hf2, eq2);
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
using test::default_generator;
using test::generate_collisions;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
{
test::check_instances check_;
UNORDERED_TEST(assign_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
UNORDERED_TEST(assign_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
{
test::check_instances check_;
test::random_values<T> v1(100, generator), v2(1000, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
{
test::check_instances check_;
test::random_values<T> v1(1000, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
}
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::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_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> >*
test_multiset_prop_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> >*
test_multimap_prop_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> >*
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> >*
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> >*
test_multimap_no_prop_assign;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
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_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)))
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (assign_default_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init;
boost::unordered_map<int, int> x1;
x1[25] = 3;
x1[16] = 10;
BOOST_TEST(!x1.empty());
x1 = init;
BOOST_TEST(x1.empty());
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (assign_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
boost::unordered_set<int> x;
x.insert(10);
x.insert(20);
x = {1, 2, -10};
BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end());
}
#endif
}
RUN_TESTS()
+9 -44
View File
@@ -1,67 +1,32 @@
// Copyright 2007-2009 Daniel James.
// Copyright 2007-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)
// 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) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
UNORDERED_AUTO_TEST(at_tests) {
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
try {
x.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
try {
x_const.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
typedef boost::unordered_map<std::string, int>::iterator iterator;
x["one"] = 1;
x["two"] = 2;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl;
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
BOOST_TEST(x_const.at("one") == 1);
BOOST_TEST(x_const.at("two") == 2);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
BOOST_CHECK(x.at("one") == 1);
BOOST_CHECK(x.at("two") == 2);
try {
x.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
x.at("three");
BOOST_ERROR("Should have thrown.");
}
try {
x_const.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
catch(std::out_of_range) {
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
RUN_TESTS()
+31 -63
View File
@@ -1,94 +1,62 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
#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.
#endif
namespace bucket_tests {
test::seed_t initialize_seed(54635);
test::seed_t seed(54635);
template <class X> void tests(X*, test::random_generator generator)
{
test::check_instances check_;
typedef typename X::size_type size_type;
typedef typename X::const_local_iterator const_local_iterator;
template <class X>
void tests(X* = 0, test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
test::random_values<X> v(1000, generator);
X x(v.begin(), v.end());
BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
if (!(x.bucket_count() <= x.max_bucket_count())) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x.bucket_count()
<< "<=" << x.max_bucket_count() << "\n";
}
BOOST_CHECK(x.bucket_count() < x.max_bucket_count());
std::cerr<<x.bucket_count()<<"<"<<x.max_bucket_count()<<"\n";
for (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));
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()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while (lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) {
++lit;
BOOST_CHECK(bucket < x.bucket_count());
if(bucket < x.max_bucket_count()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while(lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) ++lit;
BOOST_CHECK(lit != lend);
}
BOOST_TEST(lit != lend);
}
}
for (size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_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))));
for(size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.begin(i), x.end(i)));
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.cbegin(i), x.cend(i)));
X const& x_ref = x;
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.begin(i), x_ref.end(i)));
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.cbegin(i), x_ref.cend(i)));
}
}
}
boost::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::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
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;
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(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)))
}
RUN_TESTS()
+145 -218
View File
@@ -1,248 +1,175 @@
// Copyright 2006-2009 Daniel James.
// 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)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <iostream>
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
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,
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::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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<test::minimal::assignable, test::minimal::assignable,
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
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<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;
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) {
typedef std::pair<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<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;
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
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<
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;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
UNORDERED_AUTO_TEST (test1) {
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
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;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
}
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);
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
map_value_type;
map_value_type map_value(assignable, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
test::minimal::allocator<test::minimal::assignable> >;
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,
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::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
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;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
UNORDERED_AUTO_TEST(test0)
{
int value;
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> value_type;
value_type value(
test::minimal::assignable::create(),
test::minimal::copy_constructible::create());
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::cout<<"Test unordered_map.\n";
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
boost::unordered_map<int, int> int_map;
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(map, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(multimap, value);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(equality_tests) {
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> value_type;
UNORDERED_AUTO_TEST (lwg2059) {
{
boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
boost::unordered_map<int, int> int_map;
{
boost::unordered_multimap<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > map;
equality_test(int_map);
equality_test(map);
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multimap;
equality_test(int_multimap);
equality_test(multimap);
}
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";
boost::unordered_map<int, int> map;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_test(multimap, value, map_value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::assignable assignable
= test::minimal::assignable::create();
test::minimal::copy_constructible copy_constructible
= test::minimal::copy_constructible::create();
test::minimal::hash<test::minimal::assignable> hash
= test::minimal::hash<test::minimal::assignable>::create();
test::minimal::equal_to<test::minimal::assignable> equal_to
= test::minimal::equal_to<test::minimal::assignable>::create();
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> map_value_type;
map_value_type map_value(assignable, copy_constructible);
std::cout<<"Test unordered_map.\n";
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > map;
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, copy_constructible);
unordered_test(map, assignable, map_value, hash, equal_to);
boost::unordered_map<
test::minimal::assignable,
test::minimal::default_copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > map2;
test::minimal::default_copy_constructible default_copy_constructible;
unordered_map_functions(map2, assignable, default_copy_constructible);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, copy_constructible);
unordered_test(multimap, assignable, map_value, hash, equal_to);
}
RUN_TESTS()
+111 -283
View File
@@ -1,313 +1,141 @@
// Copyright 2006-2009 Daniel James.
// 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)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include <iostream>
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
INSTANTIATE(set)<test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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<test::minimal::assignable,
template class boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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<test::minimal::assignable,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
test::minimal::allocator<test::minimal::assignable> >;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
}
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<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;
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
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<
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;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
}
UNORDERED_AUTO_TEST (test1) {
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_unique_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST (test2) {
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
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;
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
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;
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) {
test::minimal::constructor_param x;
test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
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;
// unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
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;
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
}
UNORDERED_AUTO_TEST (movable2_tests) {
test::minimal::constructor_param x;
test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
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;
// unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
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;
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
}
UNORDERED_AUTO_TEST (destructible_tests) {
test::minimal::constructor_param x;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
unordered_destructible_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
unordered_destructible_test(multiset);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
UNORDERED_AUTO_TEST(test0)
{
int value;
test::minimal::assignable assignable = test::minimal::assignable::create();
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> int_set;
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;
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
container_test(int_set, 0);
container_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
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;
container_test(int_multiset, 0);
container_test(multiset, assignable);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(equality_tests) {
typedef test::minimal::assignable value_type;
UNORDERED_AUTO_TEST (lwg2059) {
{
boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
boost::unordered_set<int> int_set;
{
boost::unordered_multiset<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > set;
equality_test(int_set);
equality_test(set);
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multiset;
equality_test(int_multiset);
equality_test(multiset);
}
UNORDERED_AUTO_TEST(test1)
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> set;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_test(set, value, value, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_test(multiset, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::assignable assignable
= test::minimal::assignable::create();
test::minimal::copy_constructible copy_constructible
= test::minimal::copy_constructible::create();
test::minimal::hash<test::minimal::assignable> hash
= test::minimal::hash<test::minimal::assignable>::create();
test::minimal::equal_to<test::minimal::assignable> equal_to
= test::minimal::equal_to<test::minimal::assignable>::create();
std::cout<<"Test unordered_set.\n";
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;
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_test(set, assignable, assignable, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
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;
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_test(multiset, assignable, assignable, hash, equal_to);
}
RUN_TESTS()
File diff suppressed because it is too large Load Diff
+208 -361
View File
@@ -1,15 +1,10 @@
// Copyright 2006-2010 Daniel James.
// 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)
// 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 "../helpers/random_values.hpp"
@@ -18,429 +13,281 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
namespace constructor_tests {
test::seed_t initialize_seed(356730);
test::seed_t seed(356730);
template <class T>
void constructor_tests1(T*, test::random_generator generator)
{
typename T::hasher hf;
typename T::key_equal eq;
typename T::allocator_type al;
template <class T>
void constructor_tests1(T*, test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
UNORDERED_SUB_TEST("Construct 1")
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
T x(0, hf, eq);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(0, hf, eq);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 2")
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(100, hf);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 3")
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
T x(2000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(2000);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 2000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 4")
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
T x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x;
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 5")
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 6")
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 7")
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 8")
std::cerr<<"Construct 8\n";
{
test::check_instances check_;
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 9")
std::cerr<<"Construct 9\n";
{
test::check_instances check_;
T x(0, hf, eq, al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(0, hf, eq, al);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 10")
std::cerr<<"Construct 10\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 11")
std::cerr<<"Construct 11\n";
{
test::check_instances check_;
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
test::random_values<T> v(1000, generator);
T x(al);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
}
}
template <class T>
void constructor_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf;
typename T::hasher hf1(1);
typename T::hasher hf2(2);
typename T::key_equal eq;
typename T::key_equal eq1(1);
typename T::key_equal eq2(2);
typename T::allocator_type al;
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
template <class T>
void constructor_tests2(T*, test::random_generator const& generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::key_equal eq1(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
BOOST_DEDUCED_TYPENAME T::allocator_type al;
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
UNORDERED_SUB_TEST("Construct 1")
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
T x(10000, hf1, eq1);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(10000, hf1, eq1);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 2")
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(100, hf1);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 3")
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 4")
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_CHECK(x.bucket_count() >= 1000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
UNORDERED_SUB_TEST("Construct 5")
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 6")
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 7")
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), 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);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
UNORDERED_SUB_TEST("Construct 8 - from input iterator")
std::cerr<<"Construct 8 - from input iterator\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
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);
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);
test::random_values<T> v(100, generator);
T x(test::input_iterator(v.begin()), test::input_iterator(v.end()), 0, hf1, eq1);
T y(test::input_iterator(x.begin()), test::input_iterator(x.end()), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
}
UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator")
{
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);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <class T>
void map_constructor_test(T* = 0, test::random_generator const& generator = test::default_generator)
{
std::cerr<<"map_constructor_test\n";
UNORDERED_SUB_TEST("Construct 9")
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(50);
BOOST_TEST(x.bucket_count() >= 50);
x.max_load_factor(10);
BOOST_TEST(x.bucket_count() >= 50);
x.insert(v.begin(), v.end());
BOOST_TEST(x.bucket_count() >= 50);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<typename T::value_type> list;
UNORDERED_SUB_TEST("Initializer list construct 1")
{
test::check_instances check_;
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 2")
{
test::check_instances check_;
T x(list, 1000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 3")
{
test::check_instances check_;
T x(list, 10, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 4")
{
test::check_instances check_;
T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
UNORDERED_SUB_TEST("Initializer list construct 5")
{
test::check_instances check_;
T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
}
#endif
}
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
{
typedef test::list<
std::pair<typename T::key_type, 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());
test::check_container(x, v);
test::check_equivalent_keys(x);
}
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::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_default_initializer_list) {
std::initializer_list<int> init;
boost::unordered_set<int> x1 = init;
BOOST_TEST(x1.empty());
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_initializer_list) {
boost::unordered_set<int> x1 = {2, 10, 45, -5};
BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end());
}
#endif
}
RUN_TESTS_QUIET()
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(constructor_tests1,
((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))
)
UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
)
}
RUN_TESTS()
+90 -160
View File
@@ -1,209 +1,139 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
test::seed_t initialize_seed(9063);
test::seed_t seed(9063);
namespace copy_tests {
namespace copy_tests
{
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator)
{
typedef typename T::allocator_type allocator_type;
typename T::hasher hf;
typename T::key_equal eq;
typename T::allocator_type al;
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator = test::default_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 x;
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
T x;
T y(x);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
T y(x);
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));
test::check_equivalent_keys(y);
T x(v.begin(), v.end());
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
// In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate
// enough buckets to decrease the load factor appropriately.
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
x.max_load_factor(x.load_factor() / 4);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
// 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));
test::check_equivalent_keys(y);
// In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate
// enough buckets to decrease the load factor appropriately.
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
x.max_load_factor(x.load_factor() / 4);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
// This isn't guaranteed:
BOOST_CHECK(y.load_factor() < y.max_load_factor());
test::check_equivalent_keys(y);
}
}
}
template <class T>
void copy_construct_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al(1);
typename T::allocator_type al2(2);
template <class T>
void copy_construct_tests2(T* ptr, test::random_generator const& generator = test::default_generator)
{
copy_construct_tests1(ptr);
typedef typename T::allocator_type allocator_type;
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::check_instances check_;
T x(10000, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
T x(10000, hf, eq, al);
T y(x);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
test::check_equivalent_keys(y);
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
test::check_equivalent_keys(y);
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
test::random_values<T> v(500, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
test::check_equivalent_keys(y);
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
}
}
}
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::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
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> >*
test_multiset_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> >*
test_multimap_select_copy;
using test::default_generator;
using test::generate_collisions;
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> >*
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> >*
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> >*
test_multimap_no_select_copy;
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
)
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
((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()
-352
View File
@@ -1,352 +0,0 @@
// Copyright 2017-2018 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 <iostream>
#include <vector>
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
struct hash_equals
{
template <typename T> bool operator()(T const& x) const
{
boost::hash<T> hf;
return hf(x);
}
template <typename T> bool operator()(T const& x, T const& y) const
{
std::equal_to<T> eq;
return eq(x, y);
}
};
template <typename T> struct test_allocator
{
typedef T value_type;
test_allocator() = default;
template <typename T2> test_allocator(test_allocator<T2> const&) {}
T* allocate(std::size_t n) const { return (T*)malloc(sizeof(T) * n); }
void deallocate(T* ptr, std::size_t) const { free(ptr); }
bool operator==(test_allocator const&) { return true; }
bool operator!=(test_allocator const&) { return false; }
};
#endif
int main()
{
std::cout << "BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES: "
<< BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES << std::endl;
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
std::vector<std::pair<int, int> > x;
x.push_back(std::make_pair(1, 3));
x.push_back(std::make_pair(5, 10));
test_allocator<std::pair<const int, int> > pair_allocator;
hash_equals f;
// unordered_map
/*
template<class InputIterator,
class Hash = hash<iter_key_t<InputIterator>>,
class Pred = equal_to<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
unordered_map(InputIterator, InputIterator, typename see below::size_type =
see below,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
Hash, Pred,
Allocator>;
*/
{
boost::unordered_map m(x.begin(), x.end());
static_assert(
std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
}
/* Ambiguous:
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>(), pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator<pair<const
Key, T>>>
unordered_map(initializer_list<pair<const Key, T>>,
typename see below::size_type = see below, Hash = Hash(),
Pred = Pred(), Allocator = Allocator())
-> unordered_map<Key, T, Hash, Pred, Allocator>;
*/
{
boost::unordered_map m({std::pair<int const, int>(1, 2)});
static_assert(
std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
}
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>(), std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_map m(
{std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, hash_equals, hash_equals,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, typename see below::size_type,
Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>,
equal_to<iter_key_t<InputIterator>>,
Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m(x.begin(), x.end(), 0u, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>,
equal_to<iter_key_t<InputIterator>>,
Allocator>;
*/
/* No constructor:
{
boost::unordered_map m(x.begin(), x.end(), pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class InputIterator, class Hash, class Allocator>
unordered_map(InputIterator, InputIterator, typename see below::size_type,
Hash, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
Hash,
equal_to<iter_key_t<InputIterator>>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m(x.begin(), x.end(), 0u, f, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename see
below::size_type,
Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
*/
{
boost::unordered_map m({std::pair<int const, int>(1, 2)}, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class Key, class T, class Hash, class Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename see
below::size_type, Hash,
Allocator)
-> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, f,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
// unordered_multimap
{
boost::unordered_multimap m(x.begin(), x.end());
static_assert(
std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
}
/* Ambiguous:
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>(), pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1, 2)});
static_assert(
std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
}
/* Ambiguous
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>(), std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_multimap m(
{std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, hash_equals, hash_equals,
test_allocator<std::pair<const int, int> > > >::value);
}
/* Ambiguous
{
boost::unordered_multimap m(x.begin(), x.end(), 0u, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/* No constructor:
{
boost::unordered_multimap m(x.begin(), x.end(), pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/* Ambiguous
{
boost::unordered_multimap m(x.begin(), x.end(), 0u, f, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
{
boost::unordered_multimap m(
{std::pair<int const, int>(1, 2)}, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/* Ambiguous
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0, f,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
#endif
}
-101
View File
@@ -1,101 +0,0 @@
// Copyright 2017 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <map>
// Pretty inefficient, but the test is fast enough.
// Might be too slow if we had larger primes?
bool is_prime(std::size_t x)
{
if (x == 2) {
return true;
} else if (x == 1 || x % 2 == 0) {
return false;
} else {
// y*y <= x had rounding errors, so instead use y <= (x/y).
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
break;
}
}
return true;
}
}
void test_next_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::next_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x >= value);
}
void test_prev_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::prev_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x <= value);
if (x > value) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
}
}
UNORDERED_AUTO_TEST (next_prime_test) {
BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100));
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
// test_prev_prime doesn't work for values less than 17.
// Which should be okay, unless an allocator has a really tiny
// max_size?
const std::size_t min_prime = 17;
// test_next_prime doesn't work for values greater than this,
// which might be a problem if you've got terrabytes of memory?
// I seriously doubt the container would work well at such sizes
// regardless.
const std::size_t max_prime = 4294967291ul;
std::size_t i;
BOOST_TEST(is_prime(min_prime));
BOOST_TEST(is_prime(max_prime));
for (i = 0; i < 10000; ++i) {
if (i < min_prime) {
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
} else {
test_prev_prime(i);
}
test_next_prime(i);
}
std::size_t last = i - 1;
for (; i > last; last = i, i += i / 5) {
if (i > max_prime) {
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
} else {
test_next_prime(i);
}
test_prev_prime(i);
}
}
RUN_TESTS()
-514
View File
@@ -1,514 +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()
+118 -131
View File
@@ -1,156 +1,143 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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
{
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
namespace equality_tests
{
struct mod_compare
{
return alt_hash_ ? static_cast<std::size_t>(x % 250)
: static_cast<std::size_t>((x + 5) % 250);
}
};
bool operator()(int x, int y) const
{
return x % 1000 == y % 1000;
}
#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); \
}
int operator()(int x) const
{
return x % 250;
}
};
#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_SET_TEST(seq1, op, seq2) \
do { \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_CHECK(set1 op set2); \
} while(false)
#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_MULTISET_TEST(seq1, op, seq2) \
do { \
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_CHECK(set1 op set2); \
} while(false)
#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_MAP_TEST(seq1, op, seq2) \
do { \
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_CHECK(map1 op map2); \
} while(false)
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
do { \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_CHECK(map1 op map2); \
} while(false)
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
#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_CHECK(x1 == x2);
BOOST_CHECK(!(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_CHECK(x1 != x2);
BOOST_CHECK(!(x1 == x2));
BOOST_CHECK(x2 != x1);
BOOST_CHECK(!(x2 == x1));
x2.insert(1);
BOOST_CHECK(x1 == x2);
BOOST_CHECK(!(x1 != x2));
x2.insert(2);
BOOST_CHECK(x1 != x2);
BOOST_CHECK(!(x1 == x2));
BOOST_CHECK(x2 != x1);
BOOST_CHECK(!(x2 == x1));
}
UNORDERED_AUTO_TEST(equality_key_value_tests)
{
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2));
UNORDERED_EQUALITY_SET_TEST((2), ==, (2));
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)));
}
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)));
}
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_collision_test) {
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST((1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST((1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST((1)(501), ==, (501)(1))
}
UNORDERED_AUTO_TEST (equality_group_size_test) {
UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST (equality_map_value_test) {
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_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);
}
}
RUN_TESTS()
+49 -47
View File
@@ -1,15 +1,10 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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>
#include <map>
@@ -17,61 +12,68 @@
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
template <class Container, class Iterator>
void test_equal_insertion(Iterator begin, Iterator end)
{
typedef test::ordered<Container> tracker;
typedef test::ordered<Container> tracker;
Container x1;
tracker x2 = test::create_ordered(x1);
Container x1;
tracker x2 = test::create_ordered(x1);
for (Iterator it = begin; it != end; ++it) {
x1.insert(*it);
x2.insert(*it);
x2.compare_key(x1, *it);
}
for(Iterator it = begin; it != end; ++it) {
x1.insert(*it);
x2.insert(*it);
x2.compare_key(x1, *it);
}
x2.compare(x1);
test::check_equivalent_keys(x1);
x2.compare(x1);
test::check_equivalent_keys(x1);
}
UNORDERED_AUTO_TEST (set_tests) {
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
UNORDERED_AUTO_TEST(set_tests)
{
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;
test_equal_insertion<boost::unordered_set<int> >(values[0], values[0] + 1);
test_equal_insertion<boost::unordered_set<int> >(values[1], values[1] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[2], values[2] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[3], values[3] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[4], values[4] + 3);
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
test_equal_insertion<boost::unordered_multiset<int> >(values[0], values[0] + 1);
test_equal_insertion<boost::unordered_multiset<int> >(values[1], values[1] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[2], values[2] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[3], values[3] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[4], values[4] + 3);
}
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[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));
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[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));
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
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)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
for(int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
}
RUN_TESTS()
+113 -145
View File
@@ -1,217 +1,185 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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.
#endif
struct write_pair_type
{
template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second << ")";
}
template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const
{
std::cout<<"("<<x.first<<","<<x.second<<")";
}
} write_pair;
template <class Container> void write_container(Container const& x)
template <class Container>
void write_container(Container const& x)
{
std::for_each(x.begin(), x.end(), write_pair);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
std::for_each(x.begin(), x.end(), write_pair);
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); }
};
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::allocator<std::pair<int const, int> > > collide_map;
typedef boost::unordered_multimap<int, int,
collision2_hash, std::equal_to<int>,
test::allocator<std::pair<int const, int> > > collide_map2;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
UNORDERED_AUTO_TEST (empty_range_tests) {
collide_map x;
x.erase(x.begin(), x.end());
x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end());
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST (single_item_tests) {
collide_list init;
init.push_back(collide_value(1, 1));
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.end(), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST (two_equivalent_item_tests) {
collide_list init;
init.push_back(collide_value(1, 1));
init.push_back(collide_value(1, 2));
{
collide_map x(init.begin(), init.end());
UNORDERED_AUTO_TEST(empty_range_tests)
{
collide_map x;
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end());
}
{
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);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(single_item_tests)
{
collide_list init;
init.push_back(collide_value(1,1));
{
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);
test::check_equivalent_keys(x);
}
x.erase(x.begin(), x.begin());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
x.erase(x.end(), x.end());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
x.erase(x.begin(), x.end());
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
}
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_list init;
init.push_back(collide_value(1,1));
init.push_back(collide_value(1,2));
{
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.end());
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
}
{
collide_map x(init.begin(), init.end());
int value = boost::next(x.begin())->second;
x.erase(x.begin(), boost::next(x.begin()));
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
}
{
collide_map x(init.begin(), init.end());
int value = x.begin()->second;
x.erase(boost::next(x.begin()), x.end());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
}
}
// 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());
collide_list b(y.begin(), y.end());
a.sort();
b.sort();
return a == b;
collide_list a(x.begin(), x.end());
collide_list b(y.begin(), y.end());
a.sort();
b.sort();
return a == b;
}
template <class Container>
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
bool general_erase_range_test(Container& x, int start, int end)
{
collide_list l(x.begin(), x.end());
l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
collide_list l(x.begin(), x.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));
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) {
Container y(x);
collide_list init(y.begin(), y.end());
if (!general_erase_range_test(y, position, position + length)) {
BOOST_ERROR("general_erase_range_test failed.");
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
<< position + length << ")\n";
write_container(init);
write_container(y);
}
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)) {
BOOST_ERROR("general_erase_range_test failed.");
std::cout<<"Erase: ["<<position<<","<<position + length<<")\n";
write_container(init);
write_container(y);
}
}
}
}
}
template <class Container>
void x_by_y_erase_range_tests(Container*, int values, int duplicates)
{
Container y;
Container y;
for (int i = 0; i < values; ++i) {
for (int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j));
for(int i = 0; i < values; ++i) {
for(int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j));
}
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
<< ", Duplicates: " << duplicates << "\n";
erase_subrange_tests(y);
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) {
x_by_y_erase_range_tests(x, i, 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) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
collide_map m;
exhaustive_erase_tests((collide_map*)0, 4, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
UNORDERED_AUTO_TEST(exhaustive_collide_tests)
{
std::cout<<"exhaustive_collide_tests:\n";
collide_map m;
exhaustive_erase_tests((collide_map*) 0, 4, 4);
std::cout<<"\n";
}
UNORDERED_AUTO_TEST (exhaustive_collide2_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
UNORDERED_AUTO_TEST (exhaustive_collide3_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
{
std::cout<<"exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*) 0, 8, 4);
std::cout<<"\n";
}
RUN_TESTS()
+106 -233
View File
@@ -1,267 +1,140 @@
// Copyright 2006-2009 Daniel James.
// 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)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include <vector>
#include <cstdlib>
namespace erase_tests {
#include <iostream>
test::seed_t initialize_seed(85638);
namespace erase_tests
{
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator c_iterator;
test::seed_t seed(85638);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
template <class Container>
void erase_tests1(Container*, test::random_generator generator = test::default_generator)
{
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 (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);
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(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()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
iterator pos = x.erase(x.begin());
--size;
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(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()) {
std::size_t index = test::random_value(x.size());
c_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);
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));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
// I'm actually stretching it a little here, as the standard says it
// returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option...
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_TEST(x.size() == size);
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
test::check_equivalent_keys(x);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n";
{
test::check_instances check_;
Container x;
for (int i = 0; i < 100; ++i) {
test::random_values<Container> v(1000, generator);
x.insert(v.begin(), v.end());
// Note that erase only invalidates the erased iterators.
std::vector<c_iterator> iterators;
for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
iterators.push_back(it);
Container x(v.begin(), v.end());
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_CHECK(count == x.erase(test::get_key<Container>(*it)));
BOOST_CHECK(x.size() == old_size - count);
BOOST_CHECK(x.count(test::get_key<Container>(*it)) == 0);
BOOST_CHECK(x.find(test::get_key<Container>(*it)) == x.end());
}
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);
typename std::vector<c_iterator>::const_iterator i2 =
iterators.begin();
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
std::cerr<<"erase(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()) {
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);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(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()) {
std::size_t index = test::random_value(x.size());
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);
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
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);
BOOST_DEDUCED_TYPENAME Container::iterator pos = x.erase(x.begin());
--size;
BOOST_CHECK(pos == x.begin());
BOOST_CHECK(x.count(key) == count - 1);
BOOST_CHECK(x.size() == size);
}
next = test::next(pos);
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));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
BOOST_CHECK(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
std::cerr<<"erase(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
while(size > 0 && !x.empty())
{
using namespace std;
int index = rand() % 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);
BOOST_CHECK(next == x.erase(pos));
--size;
if(size > 0)
BOOST_CHECK(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_CHECK(x.count(key) == count - 1);
BOOST_CHECK(x.size() == size);
}
BOOST_CHECK(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
std::cerr<<"erase(ranges).\n";
{
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
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;
std::size_t size = x.size();
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// I'm actually stretching it a little here, as the standard says it
// returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option...
BOOST_CHECK(x.erase(x.end(), x.end()) == x.end());
BOOST_CHECK(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_CHECK(x.size() == size);
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.end());
BOOST_CHECK(x.empty());
BOOST_CHECK(x.begin() == x.end());
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.begin());
}
std::cerr<<"clear().\n";
{
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
BOOST_CHECK(x.empty());
BOOST_CHECK(x.begin() == x.end());
}
std::cerr<<"\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(erase_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
-133
View File
@@ -1,133 +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"
namespace extract_tests {
test::seed_t initialize_seed(85638);
template <class Container>
void extract_tests1(Container*, test::random_generator generator)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for (typename test::random_values<Container>::iterator it = v.begin();
it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
std::size_t new_count = count ? count - 1 : count;
std::size_t new_size = count ? old_size - 1 : old_size;
typename Container::node_type n =
x.extract(test::get_key<Container>(*it));
BOOST_TEST((n ? true : false) == (count ? true : false));
BOOST_TEST(x.size() == new_size);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
if (!new_count) {
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
} else {
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
}
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(x.begin());
BOOST_TEST(n);
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
using namespace std;
int index = rand() % (int)x.size();
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);
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 == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)))
}
RUN_TESTS()
+66 -124
View File
@@ -1,157 +1,99 @@
// Copyright 2006-2009 Daniel James.
// 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)
// 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 "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/helpers.hpp"
namespace find_tests {
namespace find_tests
{
test::seed_t initialize_seed(78937);
test::seed_t seed(78937);
template <class X> void find_tests1(X*, test::random_generator generator)
{
typedef typename X::iterator iterator;
template <class X>
void find_tests1(X*, test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
X const& x_const = x;
test::ordered<X> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
X const& x_const = x;
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)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
iterator pos = x.find(key);
BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = x_const.find(key);
BOOST_CHECK(pos != x.end() &&
x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_CHECK(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
for (typename test::ordered<X>::const_iterator it1 = tracker.begin();
it1 != tracker.end(); ++it1) {
typename X::key_type key = test::get_key<X>(*it1);
typename X::const_iterator const_pos = x_const.find(key);
iterator pos = x.find(key);
BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(pos != x.end());
BOOST_TEST(pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_CHECK(x.count(key) == tracker.count(key));
BOOST_TEST(x.count(key) == tracker.count(key));
test::compare_pairs(x.equal_range(key),
tracker.equal_range(key),
(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);
}
test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
(typename X::value_type*)0);
test::compare_pairs(x_const.equal_range(key), tracker.equal_range(key),
(typename X::value_type*)0);
}
test::random_values<X> v2(500, generator);
for (typename test::random_values<X>::const_iterator it2 = v2.begin();
it2 != v2.end(); ++it2) {
typename X::key_type key = test::get_key<X>(*it2);
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);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
test::random_values<X> v2(500, generator);
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())
{
BOOST_CHECK(x.find(key) == x.end());
BOOST_CHECK(x_const.find(key) == x_const.end());
BOOST_CHECK(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_CHECK(range.first == range.second);
}
}
}
}
{
test::check_instances check_;
X x;
X x;
test::random_values<X> v2(5, generator);
for (typename test::random_values<X>::const_iterator it3 = v2.begin();
it3 != v2.end(); ++it3) {
typename X::key_type key = test::get_key<X>(*it3);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
}
test::random_values<X> v2(5, generator);
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_CHECK(x.find(key) == x.end());
BOOST_CHECK(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_CHECK(range.first == range.second);
}
}
}
}
struct compatible_key
{
test::object o_;
boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
compatible_key(test::object const& o) : o_(o) {}
};
using test::default_generator;
using test::generate_collisions;
struct compatible_hash
{
test::hash hash_;
UNORDERED_TEST(find_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
std::size_t operator()(compatible_key const& k) const
{
return hash_(k.o_);
}
};
struct compatible_predicate
{
test::equal_to equal_;
bool operator()(compatible_key const& k1, compatible_key const& k2) const
{
return equal_(k1.o_, k2.o_);
}
};
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef 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) {
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) {
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,
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::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(
find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
-81
View File
@@ -1,81 +0,0 @@
// Copyright 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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)
{
swap(x, y);
}
template <typename T>
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)
{
return x != y;
}
template <typename T>
void call_swap(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{
swap(x, y);
}
template <typename T>
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)
{
return x != y;
}
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
int_map x, y;
x[1] = 2;
y[2] = 1;
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
int_multimap x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
-106
View File
@@ -1,106 +0,0 @@
// Copyright 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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;
};
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>*);
template <typename T>
void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{
swap(x, 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)
{
return x != y;
}
template <typename T>
void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{
swap(x, 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)
{
return x != y;
}
#include "../helpers/test.hpp"
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));
}
#include <boost/unordered_set.hpp>
UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
}
UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
int_set x, y;
x.insert(1);
y.insert(2);
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
int_multiset x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
-173
View File
@@ -1,173 +0,0 @@
// Copyright 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)
// 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
{
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
{
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)
{
}
template <typename T2>
allocator(const std::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()
{
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);
}
// 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()
{
// 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.
incomplete_test::use_types();
}

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