Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Clow 68db81064b Release 1.53.0
[SVN r82734]
2013-02-04 18:11:49 +00:00
78 changed files with 1637 additions and 5131 deletions
-1
View File
@@ -1 +0,0 @@
/doc/html/
-60
View File
@@ -1,60 +0,0 @@
# Copyright (C) 2016 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Use Trusty to get a reasonably recent version of Boost.
sudo: required
dist: trusty
language: c++
addons:
apt:
packages:
- libboost-tools-dev
- libxml2-utils
- g++-multilib
matrix:
include:
- compiler: gcc
env: BJAM_TOOLSET=gcc
- compiler: gcc
env: BJAM_TOOLSET=gcc-std11
#- compiler: gcc
# env: BJAM_TOOLSET=gcc-m32
- compiler: gcc
env: BJAM_TOOLSET=gcc-std11m32
#- compiler: clang
# env: BJAM_TOOLSET=clang
- compiler: clang
env: BJAM_TOOLSET=clang-std11
- compiler: clang
env: BJAM_TOOLSET=clang-m32
#- compiler: clang
# env: BJAM_TOOLSET=clang-std11m32
before_script:
- cd ${TRAVIS_BUILD_DIR}
- touch Jamroot.jam
- cd $HOME
- |
echo "using gcc : : g++-4.8 -Werror --std=c++03 -fsanitize=address ;" > ~/user-config.jam
echo "using gcc : std11 : g++-4.8 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
echo "using gcc : m32 : g++-4.8 -m32 -Werror -fsanitize=address ;" >> ~/user-config.jam
echo "using gcc : std11m32 : g++-4.8 -m32 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
echo "using clang : : clang++ -Werror --std=c++03 -fsanitize=address ;" >> ~/user-config.jam
echo "using clang : std11 : clang++ -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
# sanitized=address not available for 32-bit clang on travis.
echo "using clang : m32 : clang++ -m32 -Werror --std=c++03 ;" >> ~/user-config.jam
echo "using clang : std11m32 : clang++ -m32 -Werror --std=c++11 ;" >> ~/user-config.jam
- cat ~/user-config.jam
- wget -O boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/snapshots/master/boost_1_62_0.tar.bz2/download
- tar -xjf boost.tar.bz2
- mv boost_1_62_0 boost
- rm -r boost/boost/unordered
script:
- cd ${TRAVIS_BUILD_DIR}/test
- bjam ${BJAM_TOOLSET} include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
-9
View File
@@ -57,12 +57,3 @@ boostbook standalone : unordered :
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
;
###############################################################################
alias boostdoc
: unordered
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;
+1 -76
View File
@@ -47,7 +47,7 @@ First official release.
[h2 Boost 1.38.0]
* Use [@boost:/libs/core/swap.html `boost::swap`].
* Use [@boost:/libs/utility/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
@@ -228,79 +228,4 @@ C++11 support has resulted in some breaking changes:
* More internal implementation changes, including a much simpler
implementation of `erase`.
[h2 Boost 1.54.0]
* Mark methods specified in standard as `noexpect`. More to come in the next
release.
* If the hash function and equality predicate are known to both have nothrow
move assignment or construction then use them.
[h2 Boost 1.55.0]
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
* Follow the standard by only using the allocators' construct and destroy
methods to construct and destroy stored elements. Don't use them for internal
data like pointers.
[h2 Boost 1.56.0]
* Fix some shadowed variable warnings ([ticket 9377]).
* Fix allocator use in documentation ([ticket 9719]).
* Always use prime number of buckets for integers. Fixes performance
regression when inserting consecutive integers, although makes other
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[h2 Boost 1.62.0]
* Remove use of deprecated `boost::iterator`.
* Remove `BOOST_NO_STD_DISTANCE` workaround.
* Remove `BOOST_UNORDERED_DEPRECATED_EQUALITY` warning.
* Simpler implementation of assignment, fixes an exception safety issue
for `unordered_multiset` and `unordered_multimap`. Might be a little slower.
* Stop using return value SFINAE which some older compilers have issues
with.
[h2 Boost 1.63.0]
* Check hint iterator in `insert`/`emplace_hint`.
* Fix some warnings, mostly in the tests.
* Manually write out `emplace_args` for small numbers of arguments -
should make template error messages a little more bearable.
* Remove superfluous use of `boost::forward` in emplace arguments,
which fixes emplacing string literals in old versions of Visual C++.
* Fix an exception safety issue in assignment. If bucket allocation
throws an exception, it can overwrite the hash and equality functions while
leaving the existing elements in place. This would mean that the function
objects wouldn't match the container elements, so elements might be in the
wrong bucket and equivalent elements would be incorrectly handled.
* Various reference documentation improvements.
* Better allocator support ([ticket 12459]).
* Make the no argument constructors implicit.
* Implement missing allocator aware constructors.
* Fix assigning the hash/key equality functions for empty containers.
* Remove unary/binary_function from the examples in the documentation.
They are removed in C++17.
* Support 10 constructor arguments in emplace. It was meant to support up to 10
arguments, but an off by one error in the preprocessor code meant it only
supports up to 10.
[endsect]
+4 -5
View File
@@ -8,12 +8,11 @@
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
but imperfect emulation. On such compilers you'll need to use Boost.Move
to take advantage of using movable container elements, also note that:
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable.
* Argument forwarding is not perfect.
[endsect]
+2 -2
View File
@@ -54,14 +54,14 @@ order to work with non-C++11 compilers and libraries.
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_map unordered_map]``;
template<
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_multimap unordered_multimap]``;
}
+8 -13
View File
@@ -3,7 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[def __wang__
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
Thomas Wang's article on integer hash functions]]
[section:rationale Implementation Rationale]
@@ -85,8 +85,7 @@ of 2.
Using a prime number of buckets, and choosing a bucket by using the modulus
of the hash function's result will usually give a good result. The downside
is that the required modulus operation is fairly expensive. This is what the
containers do in most cases.
is that the required modulus operation is fairly expensive.
Using a power of 2 allows for much quicker selection of the bucket
to use, but at the expense of loosing the upper bits of the hash value.
@@ -96,16 +95,12 @@ functions this can't be relied on.
To avoid this a transformation could be applied to the hash function, for an
example see __wang__. Unfortunately, a transformation like Wang's requires
knowledge of the number of bits in the hash value, so it isn't portable enough
to use as a default. It can applicable in certain cases so the containers
have a policy based implementation that can use this alternative technique.
knowledge of the number of bits in the hash value, so it isn't portable enough.
This leaves more expensive methods, such as Knuth's Multiplicative Method
(mentioned in Wang's article). These don't tend to work as well as taking the
modulus of a prime, and the extra computation required might negate
efficiency advantage of power of 2 hash tables.
Currently this is only done on 64 bit architecures, where prime number
modulus can be expensive. Although this varies depending on the architecture,
so I probably should revisit it.
I'm also thinking of introducing a mechanism whereby a hash function can
indicate that it's safe to be used directly with power of 2 buckets, in
which case a faster plain power of 2 implementation can be used.
So, this implementation uses a prime number for the hash table size.
[endsect]
+3 -225
View File
@@ -189,22 +189,10 @@ EOL;
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
@@ -258,12 +246,7 @@ EOL;
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@@ -327,168 +310,6 @@ EOL;
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype><?php echo $name; ?> &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>
@@ -537,21 +358,6 @@ EOL;
</para>
</requires>
</method>
<method name="operator=">
<parameter>
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<type><?php echo $name; ?>&amp;</type>
<description>
<para>Assign from values in initializer list. All existing elements are either overwritten by the new elements or destroyed.</para>
</description>
<requires>
<para>
<code>value_type</code> is <code>CopyInsertable</code> into the container and
<code>CopyAssignable</code>.
</para>
</requires>
</method>
<method name="get_allocator" cv="const">
<type>allocator_type</type>
</method>
@@ -834,35 +640,7 @@ EOL;
</parameter>
<type>void</type>
<description>
<para>Inserts a range of elements into the container.
<?php if (!$equivalent_keys): ?>
Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
<?php endif; ?>
</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<type>void</type>
<description>
<para>Inserts a range of elements into the container.
<?php if (!$equivalent_keys): ?>
Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.
<?php endif; ?>
</para>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
+11 -879
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -10,6 +10,7 @@
//[case_insensitive_functions
struct iequal_to
: std::binary_function<std::string, std::string, bool>
{
bool operator()(std::string const& x,
std::string const& y) const
@@ -19,6 +20,7 @@
};
struct ihash
: std::unary_function<std::string, std::size_t>
{
std::size_t operator()(std::string const& x) const
{
+1
View File
@@ -18,6 +18,7 @@
}
struct point_hash
: std::unary_function<point, std::size_t>
{
std::size_t operator()(point const& p) const
{
+2
View File
@@ -19,6 +19,7 @@
namespace hash_examples
{
struct iequal_to
: std::binary_function<std::string, std::string, bool>
{
iequal_to() {}
explicit iequal_to(std::locale const& l) : locale_(l) {}
@@ -33,6 +34,7 @@ namespace hash_examples
};
struct ihash
: std::unary_function<std::string, std::size_t>
{
ihash() {}
explicit ihash(std::locale const& l) : locale_(l) {}
+137 -410
View File
@@ -9,36 +9,27 @@
#ifndef BOOST_UNORDERED_ALLOCATE_HPP
#define BOOST_UNORDERED_ALLOCATE_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// Some of these includes are required for other detail headers.
#include <boost/unordered/detail/fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <iterator>
#include <utility>
#include <cmath>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
@@ -52,8 +43,7 @@
// will be default-initialized.
#endif
// Maximum number of arguments supported by emplace + 1.
#define BOOST_UNORDERED_EMPLACE_LIMIT 11
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
namespace boost { namespace unordered { namespace detail {
@@ -89,16 +79,6 @@ namespace boost { namespace unordered { namespace detail {
convert_from_anything(T const&);
};
namespace func {
// This is a bit nasty, when constructing the individual members
// of a std::pair, need to cast away 'const'. For modern compilers,
// should be able to use std::piecewise_construct instead.
template <typename T> T* const_cast_pointer(T* x) { return x; }
template <typename T> T* const_cast_pointer(T const* x) {
return const_cast<T*>(x);
}
}
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
@@ -107,102 +87,26 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
#else
#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
#else
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
#define BOOST_UNORDERED_EMPLACE_FORWARD args
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#else
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#endif
template <typename A0>
struct emplace_args1
{
BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
emplace_args1(Arg0 b0) : a0(b0) {}
};
template <typename A0>
inline emplace_args1<A0> create_emplace_args(
BOOST_FWD_REF(A0) b0)
{
emplace_args1<A0> e(b0);
return e;
}
template <typename A0, typename A1>
struct emplace_args2
{
BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
};
template <typename A0, typename A1>
inline emplace_args2<A0, A1> create_emplace_args(
BOOST_FWD_REF(A0) b0,
BOOST_FWD_REF(A1) b1)
{
emplace_args2<A0, A1> e(b0, b1);
return e;
}
template <typename A0, typename A1, typename A2>
struct emplace_args3
{
BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
};
template <typename A0, typename A1, typename A2>
inline emplace_args3<A0, A1, A2> create_emplace_args(
BOOST_FWD_REF(A0) b0,
BOOST_FWD_REF(A1) b1,
BOOST_FWD_REF(A2) b2)
{
emplace_args3<A0, A1, A2> e(b0, b1, b2);
return e;
}
#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
#define BOOST_UNORDERED_EARGS(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
struct BOOST_PP_CAT(emplace_args, n) \
@@ -228,7 +132,33 @@ BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
return e; \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)( \
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(b, n)))
#else
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
#endif
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
_)
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
@@ -248,8 +178,9 @@ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
// 2 = boost::container::allocator_traits
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
# if !defined(BOOST_NO_CXX11_ALLOCATOR)
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
# elif defined(BOOST_MSVC)
# if BOOST_MSVC < 1400
// Use container's allocator_traits for older versions of Visual
@@ -303,11 +234,9 @@ namespace boost { namespace unordered { namespace detail {
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace func {
template <class T>
inline void destroy(T* x) {
x->~T();
}
template <class T>
inline void destroy(T* x) {
x->~T();
}
#if defined(BOOST_MSVC)
@@ -326,14 +255,15 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_NO_SFINAE_EXPR)
template <typename T, long unsigned int> struct expr_test;
template <typename T, unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {};
template <typename U> static char for_expr_test(U const&);
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template <typename U> \
static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \
sizeof(for_expr_test(( \
sizeof(boost::unordered::detail::for_expr_test(( \
(expression), \
0)))>::type test( \
BOOST_PP_CAT(choice, count))
@@ -346,7 +276,6 @@ namespace boost { namespace unordered { namespace detail {
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
template <typename U> static char for_expr_test(U const&); \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
@@ -422,69 +351,11 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail {
template <typename Alloc, typename T>
struct rebind_alloc;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <template<typename, typename...> class Alloc,
typename U, typename T, typename... Args>
struct rebind_alloc<Alloc<U, Args...>, T>
{
typedef Alloc<T, Args...> type;
};
#else
template <
template<typename> class Alloc,
typename U, typename T>
struct rebind_alloc<Alloc<U>, T>
{
typedef Alloc<T> type;
};
template <
template<typename, typename> class Alloc,
typename U, typename T,
typename A0>
struct rebind_alloc<Alloc<U, A0>, T>
{
typedef Alloc<T, A0> type;
};
template <
template<typename, typename, typename> class Alloc,
typename U, typename T,
typename A0, typename A1>
struct rebind_alloc<Alloc<U, A0, A1>, T>
{
typedef Alloc<T, A0, A1> type;
};
#endif
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
template <typename Alloc, typename T>
struct rebind_wrap
{
template <typename X>
static choice1::type test(choice1,
typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
template <typename X>
static choice2::type test(choice2, void* = 0);
enum { value = (1 == sizeof(test<Alloc>(choose()))) };
struct fallback {
template <typename U>
struct rebind {
typedef typename rebind_alloc<Alloc, T>::type other;
};
};
typedef typename boost::detail::if_true<value>::
BOOST_NESTED_TEMPLATE then<Alloc, fallback>
::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
};
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
@@ -602,9 +473,6 @@ namespace boost { namespace unordered { namespace detail {
# endif
namespace func
{
template <typename Alloc>
inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
typename boost::enable_if_c<
@@ -642,8 +510,6 @@ namespace boost { namespace unordered { namespace detail {
return (std::numeric_limits<SizeType>::max)();
}
} // namespace func.
template <typename Alloc>
struct allocator_traits
{
@@ -674,14 +540,7 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <typename T>
using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
template <typename T>
using rebind_traits =
boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
#endif
// TODO: rebind_alloc and rebind_traits
static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
@@ -714,7 +573,7 @@ namespace boost { namespace unordered { namespace detail {
::value>::type
construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
{
new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
new ((void*) p) T(boost::forward<Args>(x)...);
}
template <typename T>
@@ -730,7 +589,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# elif !defined(BOOST_NO_SFINAE_EXPR)
@@ -748,7 +607,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc&, T* p, T const& x)
{
new (static_cast<void*>(p)) T(x);
new ((void*) p) T(x);
}
template <typename T>
@@ -764,7 +623,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# else
@@ -790,7 +649,7 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
new (static_cast<void*>(p)) T(x);
new ((void*) p) T(x);
}
template <typename T>
@@ -810,22 +669,21 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# endif
static size_type max_size(const Alloc& a)
{
return boost::unordered::detail::func::
call_max_size<size_type>(a);
return boost::unordered::detail::call_max_size<size_type>(a);
}
// Allocator propagation on construction
static Alloc select_on_container_copy_construction(Alloc const& rhs)
{
return boost::unordered::detail::func::
return boost::unordered::detail::
call_select_on_container_copy_construction(rhs);
}
@@ -900,7 +758,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
namespace boost { namespace unordered { namespace detail { namespace func {
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// call_construct
@@ -918,7 +776,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template <typename Alloc, typename T>
inline void call_destroy(Alloc& alloc, T* x) {
inline void destroy_value_impl(Alloc& alloc, T* x) {
boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
}
@@ -933,30 +791,18 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template <typename Alloc, typename T>
inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::destroy(x);
}
# endif
#else
template <typename Alloc, typename T>
inline void call_construct(Alloc&, T* address)
{
new ((void*) address) T();
}
template <typename Alloc, typename T, typename A0>
inline void call_construct(Alloc&, T* address,
BOOST_FWD_REF(A0) a0)
{
new ((void*) address) T(boost::forward<A0>(a0));
}
template <typename Alloc, typename T>
inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::destroy(x);
}
#endif
@@ -972,7 +818,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template<typename Alloc, typename T> \
void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
{ \
boost::unordered::detail::func::call_construct(alloc, ptr); \
boost::unordered::detail::call_construct(alloc, ptr); \
} \
\
BOOST_PP_REPEAT_FROM_TO(1, n, \
@@ -984,7 +830,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
void construct_from_tuple(Alloc& alloc, T* ptr, \
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
boost::unordered::detail::func::call_construct(alloc, ptr, \
boost::unordered::detail::call_construct(alloc, ptr, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \
}
@@ -1025,7 +871,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
template<typename Alloc, typename T> \
void construct_from_tuple_impl( \
boost::unordered::detail::func::length<0>, Alloc&, T* ptr, \
boost::unordered::detail::length<0>, Alloc&, T* ptr, \
namespace_ tuple<>) \
{ \
new ((void*) ptr) T(); \
@@ -1038,7 +884,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template<typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple_impl( \
boost::unordered::detail::func::length<n>, Alloc&, T* ptr, \
boost::unordered::detail::length<n>, Alloc&, T* ptr, \
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*) ptr) T( \
@@ -1067,7 +913,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
{
construct_from_tuple_impl(
boost::unordered::detail::func::length<
boost::unordered::detail::length<
boost::tuples::length<Tuple>::value>(),
alloc, ptr, x);
}
@@ -1096,10 +942,10 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
// For the standard pair constructor.
template <typename Alloc, typename T, typename... Args>
inline void construct_from_args(Alloc& alloc, T* address,
inline void construct_value_impl(Alloc& alloc, T* address,
BOOST_FWD_REF(Args)... args)
{
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::call_construct(alloc,
address, boost::forward<Args>(args)...);
}
@@ -1111,36 +957,32 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2>
inline typename enable_if<use_piecewise<A0>, void>::type
construct_from_args(Alloc& alloc, std::pair<A, B>* address,
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->first)),
boost::forward<A1>(a1));
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->second)),
boost::forward<A2>(a2));
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->first), boost::forward<A1>(a1));
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->second), boost::forward<A2>(a2));
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
////////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
// Explicitly write out first three overloads for the sake of sane
// error messages.
template <typename Alloc, typename T, typename A0>
inline void construct_from_args(Alloc&, T* address,
inline void construct_value_impl(Alloc&, T* address,
emplace_args1<A0> const& args)
{
new((void*) address) T(boost::forward<A0>(args.a0));
}
template <typename Alloc, typename T, typename A0, typename A1>
inline void construct_from_args(Alloc&, T* address,
inline void construct_value_impl(Alloc&, T* address,
emplace_args2<A0, A1> const& args)
{
new((void*) address) T(
@@ -1150,7 +992,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
}
template <typename Alloc, typename T, typename A0, typename A1, typename A2>
inline void construct_from_args(Alloc&, T* address,
inline void construct_value_impl(Alloc&, T* address,
emplace_args3<A0, A1, A2> const& args)
{
new((void*) address) T(
@@ -1167,7 +1009,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_from_args(Alloc&, T* address, \
inline void construct_value_impl(Alloc&, T* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
@@ -1186,206 +1028,91 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2>
inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
typename enable_if<use_piecewise<A0>, void*>::type = 0)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->first)),
args.a1);
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->second)),
args.a2);
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->first), args.a1);
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->second), args.a2);
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
}}}}
}}}
////////////////////////////////////////////////////////////////////////////////
//
// Some helper functions for allocating & constructing
namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// Node construction
// array_constructor
//
// Allocate and construct an array in an exception safe manner, and
// clean up if an exception is thrown before the container takes charge
// of it.
template <typename NodeAlloc>
struct node_constructor
template <typename Allocator>
struct array_constructor
{
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
typedef typename traits::pointer pointer;
node_allocator& alloc_;
node_pointer node_;
bool node_constructed_;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false)
array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
constructed_ = pointer();
ptr_ = pointer();
}
~node_constructor();
~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
traits::destroy(alloc_, boost::addressof(*p));
void create_node();
traits::deallocate(alloc_, ptr_, length_);
}
}
// no throw
node_pointer release()
template <typename V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(node_ && node_constructed_);
node_pointer p = node_;
node_ = node_pointer();
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
traits::construct(alloc_, boost::addressof(*constructed_), v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
return p;
}
void reclaim(node_pointer p) {
BOOST_ASSERT(!node_);
node_ = p;
node_constructed_ = true;
boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
}
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
};
template <typename Alloc>
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (node_constructed_) {
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
}
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
template <typename Alloc>
void node_constructor<Alloc>::create_node()
{
BOOST_ASSERT(!node_);
node_constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
new ((void*) boost::addressof(*node_)) node();
node_->init(node_);
node_constructed_ = true;
}
template <typename NodeAlloc>
struct node_tmp
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::pointer node_pointer;
NodeAlloc& alloc_;
node_pointer node_;
explicit node_tmp(node_pointer n, NodeAlloc& a):
alloc_(a),
node_(n)
{
}
~node_tmp();
// no throw
node_pointer release()
{
node_pointer p = node_;
node_ = node_pointer();
return p;
}
};
template <typename Alloc>
node_tmp<Alloc>::~node_tmp()
{
if (node_) {
boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
}}}
namespace boost { namespace unordered { namespace detail { namespace func {
// Some nicer construct_node functions, might try to
// improve implementation later.
template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor<Alloc> a(alloc);
a.create_node();
construct_from_args(alloc, a.node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_FORWARD);
return a.release();
}
template <typename Alloc, typename U>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, a.node_->value_ptr(), boost::forward<U>(x));
return a.release();
}
// TODO: When possible, it might be better to use std::pair's
// constructor for std::piece_construct with std::tuple.
template <typename Alloc, typename Key>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)));
return a.release();
}
template <typename Alloc, typename Key, typename Mapped>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)),
boost::forward<Mapped>(m));
return a.release();
}
}}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
+228 -197
View File
@@ -7,13 +7,18 @@
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -25,10 +30,6 @@ namespace boost { namespace unordered { namespace detail {
}}}
// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
// in the detail namespace. It didn't work because the template parameters
// were in detail. I'm not changing it at the moment to be safe. I might
// do in the future if I change the iterator types.
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
@@ -37,9 +38,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
// all no throw
template <typename Node> struct iterator;
template <typename Node> struct c_iterator;
template <typename Node, typename ConstNodePointer> struct c_iterator;
template <typename Node, typename Policy> struct l_iterator;
template <typename Node, typename Policy>
template <typename Node, typename ConstNodePointer, typename Policy>
struct cl_iterator;
// Local Iterators
@@ -48,19 +49,20 @@ namespace boost { namespace unordered { namespace iterator_detail {
template <typename Node, typename Policy>
struct l_iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type*,
typename Node::node_pointer,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename Node2, typename Policy2>
template <typename Node2, typename ConstNodePointer, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -69,10 +71,10 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator() : ptr_() {}
l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(n), bucket_(b), bucket_count_(c) {}
l_iterator(iterator x, std::size_t b, std::size_t c)
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
return ptr_->value();
@@ -96,22 +98,22 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
bool operator==(l_iterator x) const BOOST_NOEXCEPT {
bool operator==(l_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
bool operator!=(l_iterator x) const {
return ptr_ != x.ptr_;
}
};
template <typename Node, typename Policy>
template <typename Node, typename ConstNodePointer, typename Policy>
struct cl_iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type const*,
ConstNodePointer,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
@@ -119,6 +121,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -127,13 +130,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator() : ptr_() {}
cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(n), bucket_(b), bucket_count_(c) {}
cl_iterator(iterator x, std::size_t b, std::size_t c) :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
Node, Policy> const& x) BOOST_NOEXCEPT :
Node, Policy> const& x) :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
@@ -159,31 +162,31 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
friend bool operator==(cl_iterator const& x, cl_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ == y.ptr_;
}
friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ != y.ptr_;
}
};
template <typename Node>
struct iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type*,
typename Node::node_pointer,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
template <typename, typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
template <typename>
@@ -199,9 +202,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
iterator() BOOST_NOEXCEPT : node_() {}
iterator() : node_() {}
explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
explicit iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
value_type& operator*() const {
@@ -209,7 +212,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
value_type* operator->() const {
return node_->value_ptr();
return &node_->value();
}
iterator& operator++() {
@@ -223,22 +226,22 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
bool operator==(iterator const& x) const BOOST_NOEXCEPT {
bool operator==(iterator const& x) const {
return node_ == x.node_;
}
bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
bool operator!=(iterator const& x) const {
return node_ != x.node_;
}
};
template <typename Node>
template <typename Node, typename ConstNodePointer>
struct c_iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type const*,
ConstNodePointer,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::iterator<Node>;
@@ -254,26 +257,26 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer node_;
public:
typedef typename Node::value_type value_type;
c_iterator() BOOST_NOEXCEPT : node_() {}
c_iterator() : node_() {}
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
explicit c_iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
c_iterator(iterator const& x) : node_(x.node_) {}
value_type const& operator*() const {
return node_->value();
}
value_type const* operator->() const {
return node_->value_ptr();
return &node_->value();
}
c_iterator& operator++() {
@@ -287,15 +290,11 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
friend bool operator==(c_iterator const& x, c_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator==(c_iterator const& x, c_iterator const& y) {
return x.node_ == y.node_;
}
friend bool operator!=(c_iterator const& x, c_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
return x.node_ != y.node_;
}
};
@@ -303,6 +302,125 @@ namespace boost { namespace unordered { namespace iterator_detail {
namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
//
// Node construction
template <typename NodeAlloc>
struct node_constructor
{
private:
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
protected:
node_allocator& alloc_;
node_pointer node_;
bool node_constructed_;
bool value_constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false),
value_constructed_(false)
{
}
~node_constructor();
void construct();
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
construct();
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
}
template <typename A0>
void construct_with_value2(BOOST_FWD_REF(A0) a0)
{
construct();
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
value_constructed_ = true;
}
value_type const& value() const {
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
return node_->value();
}
// no throw
node_pointer release()
{
BOOST_ASSERT(node_ && node_constructed_);
node_pointer p = node_;
node_ = node_pointer();
return p;
}
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
template <typename Alloc>
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (value_constructed_) {
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
}
if (node_constructed_) {
node_allocator_traits::destroy(alloc_,
boost::addressof(*node_));
}
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
template <typename Alloc>
void node_constructor<Alloc>::construct()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
node_allocator_traits::construct(alloc_,
boost::addressof(*node_), node());
node_->init(node_);
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_);
if (value_constructed_)
{
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
value_constructed_ = false;
}
}
}
///////////////////////////////////////////////////////////////////
//
// Node Holder
@@ -310,9 +428,11 @@ namespace boost { namespace unordered { namespace detail {
// Temporary store for nodes. Deletes any that aren't used.
template <typename NodeAlloc>
struct node_holder
struct node_holder : private node_constructor<NodeAlloc>
{
private:
typedef node_constructor<NodeAlloc> base;
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
@@ -322,14 +442,13 @@ namespace boost { namespace unordered { namespace detail {
typedef typename node::link_pointer link_pointer;
typedef boost::unordered::iterator_detail::iterator<node> iterator;
node_constructor<NodeAlloc> constructor_;
node_pointer nodes_;
public:
template <typename Table>
explicit node_holder(Table& b) :
constructor_(b.node_alloc()),
base(b.node_alloc()),
nodes_()
{
if (b.size_) {
@@ -342,40 +461,61 @@ namespace boost { namespace unordered { namespace detail {
~node_holder();
node_pointer pop_node()
void node_for_assignment()
{
node_pointer n = nodes_;
nodes_ = static_cast<node_pointer>(nodes_->next_);
n->init(n);
n->next_ = link_pointer();
return n;
if (!this->node_ && nodes_) {
this->node_ = nodes_;
nodes_ = static_cast<node_pointer>(nodes_->next_);
this->node_->init(this->node_);
this->node_->next_ = link_pointer();
this->node_constructed_ = true;
this->value_constructed_ = true;
}
}
template <typename T>
inline node_pointer copy_of(T const& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
inline void assign_impl(T const& v) {
if (this->node_ && this->value_constructed_) {
this->node_->value() = v;
}
else {
constructor_.create_node();
this->construct_with_value2(v);
}
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(), v);
return constructor_.release();
}
template <typename T1, typename T2>
inline void assign_impl(std::pair<T1 const, T2> const& v) {
this->construct_with_value2(v);
}
template <typename T>
inline node_pointer move_copy_of(T& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
inline void move_assign_impl(T& v) {
if (this->node_ && this->value_constructed_) {
this->node_->value() = boost::move(v);
}
else {
constructor_.create_node();
this->construct_with_value2(boost::move(v));
}
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(),
boost::move(v));
return constructor_.release();
}
template <typename T1, typename T2>
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
this->construct_with_value2(boost::move(v));
}
node_pointer copy_of(value_type const& v)
{
node_for_assignment();
assign_impl(v);
return base::release();
}
node_pointer move_copy_of(value_type& v)
{
node_for_assignment();
move_assign_impl(v);
return base::release();
}
iterator begin() const
@@ -391,10 +531,10 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::func::call_destroy(constructor_.alloc_,
boost::unordered::detail::destroy_value_impl(this->alloc_,
p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1);
}
}
@@ -511,51 +651,11 @@ namespace boost { namespace unordered { namespace detail {
typedef mix64_policy<std::size_t> type;
};
template <typename T>
struct pick_policy :
pick_policy_impl<
std::numeric_limits<std::size_t>::digits,
std::numeric_limits<std::size_t>::radix> {};
// While the mix policy is generally faster, the prime policy is a lot
// faster when a large number consecutive integers are used, because
// there are no collisions. Since that is probably quite common, use
// prime policy for integeral types. But not the smaller ones, as they
// don't have enough unique values for this to be an issue.
template <>
struct pick_policy<int> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<unsigned int> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<long> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<unsigned long> {
typedef prime_policy<std::size_t> type;
};
// TODO: Maybe not if std::size_t is smaller than long long.
#if !defined(BOOST_NO_LONG_LONG)
template <>
struct pick_policy<boost::long_long_type> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<boost::ulong_long_type> {
typedef prime_policy<std::size_t> type;
};
#endif
////////////////////////////////////////////////////////////////////////////
// Functions
@@ -570,23 +670,12 @@ namespace boost { namespace unordered { namespace detail {
// atomically assigns the new function objects in a strongly
// exception safe manner.
template <class H, class P, bool NoThrowMoveAssign>
class set_hash_functions;
template <class H, class P> class set_hash_functions;
template <class H, class P>
class functions
{
public:
static const bool nothrow_move_assignable =
boost::is_nothrow_move_assignable<H>::value &&
boost::is_nothrow_move_assignable<P>::value;
static const bool nothrow_move_constructible =
boost::is_nothrow_move_constructible<H>::value &&
boost::is_nothrow_move_constructible<P>::value;
private:
friend class boost::unordered::detail::set_hash_functions<H, P,
nothrow_move_assignable>;
friend class boost::unordered::detail::set_hash_functions<H, P>;
functions& operator=(functions const&);
typedef compressed<H, P> function_pair;
@@ -603,40 +692,23 @@ namespace boost { namespace unordered { namespace detail {
static_cast<void const*>(&funcs_[current_]));
}
function_pair& current() {
return *static_cast<function_pair*>(
static_cast<void*>(&funcs_[current_]));
}
void construct(bool which, H const& hf, P const& eq)
{
new((void*) &funcs_[which]) function_pair(hf, eq);
}
void construct(bool which, function_pair const& f,
boost::unordered::detail::false_type =
boost::unordered::detail::false_type())
void construct(bool which, function_pair const& f)
{
new((void*) &funcs_[which]) function_pair(f);
}
void construct(bool which, function_pair& f,
boost::unordered::detail::true_type)
{
new((void*) &funcs_[which]) function_pair(f,
boost::unordered::detail::move_tag());
}
void destroy(bool which)
{
boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
}
public:
typedef boost::unordered::detail::set_hash_functions<H, P,
nothrow_move_assignable> set_hash_functions;
functions(H const& hf, P const& eq)
: current_(false)
{
@@ -649,14 +721,6 @@ namespace boost { namespace unordered { namespace detail {
construct(current_, bf.current());
}
functions(functions& bf, boost::unordered::detail::move_tag)
: current_(false)
{
construct(current_, bf.current(),
boost::unordered::detail::integral_constant<bool,
nothrow_move_constructible>());
}
~functions() {
this->destroy(current_);
}
@@ -669,28 +733,26 @@ namespace boost { namespace unordered { namespace detail {
return current().second();
}
};
template <class H, class P>
class set_hash_functions<H, P, false>
class set_hash_functions
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
typedef functions<H, P> functions_type;
functions_type& functions_;
functions<H,P>& functions_;
bool tmp_functions_;
public:
set_hash_functions(functions_type& f, H const& h, P const& p)
set_hash_functions(functions<H,P>& f, H const& h, P const& p)
: functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, h, p);
}
set_hash_functions(functions_type& f, functions_type const& other)
set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
: functions_(f),
tmp_functions_(!f.current_)
{
@@ -709,37 +771,6 @@ namespace boost { namespace unordered { namespace detail {
}
};
template <class H, class P>
class set_hash_functions<H, P, true>
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
typedef functions<H, P> functions_type;
functions_type& functions_;
H hash_;
P pred_;
public:
set_hash_functions(functions_type& f, H const& h, P const& p) :
functions_(f),
hash_(h),
pred_(p) {}
set_hash_functions(functions_type& f, functions_type const& other) :
functions_(f),
hash_(other.hash_function()),
pred_(other.key_eq()) {}
void commit()
{
functions_.current().first() = boost::move(hash_);
functions_.current().second() = boost::move(pred_);
}
};
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
+194 -249
View File
@@ -7,11 +7,11 @@
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -51,16 +51,15 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct grouped_ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef grouped_ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
node_pointer group_prev_;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
grouped_ptr_node() :
bucket_base(),
@@ -73,10 +72,6 @@ namespace boost { namespace unordered { namespace detail {
group_prev_ = self;
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
@@ -110,11 +105,9 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct pick_grouped_node
{
typedef typename boost::remove_const<T>::type nonconst;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::grouped_ptr_node<nonconst> >::type
boost::unordered::detail::grouped_ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@@ -122,7 +115,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_grouped_node2<A, nonconst,
typedef pick_grouped_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
@@ -131,6 +124,55 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
struct multimap
{
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
struct grouped_table_impl : boost::unordered::detail::table<Types>
{
@@ -147,7 +189,6 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::node_tmp node_tmp;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
@@ -188,58 +229,48 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
// Node functions.
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
static inline node_pointer next_group(node_pointer n) {
return static_cast<node_pointer>(n->group_prev_->next_);
}
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
node_pointer n = this->begin(bucket_index);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return node_pointer();
return iterator();
}
n = next_group(n);
n = iterator(n.node_->group_prev_->next_);
}
}
std::size_t count(key_type const& k) const
{
node_pointer n = this->find_node(k);
if (!n) return 0;
iterator n = this->find_node(k);
if (!n.node_) return 0;
std::size_t x = 0;
node_pointer it = n;
node_pointer it = n.node_;
do {
it = it->group_prev_;
++x;
} while(it != n);
} while(it != n.node_);
return x;
}
@@ -247,8 +278,9 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n), iterator(n ? next_group(n) : n));
iterator n = this->find_node(k);
return std::make_pair(
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
}
// Equality
@@ -257,12 +289,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
for(node_pointer n1 = this->begin(); n1;)
for(iterator n1 = this->begin(); n1.node_;)
{
node_pointer n2 = other.find_node(other.get_key(n1->value()));
if (!n2) return false;
node_pointer end1 = next_group(n1);
node_pointer end2 = next_group(n2);
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(n1.node_->group_prev_->next_);
iterator end2(n2.node_->group_prev_->next_);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -270,24 +302,24 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if (n1->value() != n2->value()) break;
if (*n1 != *n2) break;
n1 = next_node(n1);
n2 = next_node(n2);
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(node_pointer n1a = n1, n2a = n2;;)
for(iterator n1a = n1, n2a = n2;;)
{
n1a = next_node(n1a);
n2a = next_node(n2a);
++n1a;
++n2a;
if (n1a == end1)
{
@@ -298,43 +330,41 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
node_pointer start = n1;
for(;n1 != end1; n1 = next_node(n1))
iterator start = n1;
for(;n1 != end1; ++n1)
{
value_type const& v = n1->value();
if (!find(start, n1, v)) {
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
if (matches != 1 + count_equal(next_node(n1), end1, v)) return false;
}
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
}
return true;
}
static bool find(node_pointer n, node_pointer end, value_type const& v)
static bool find(iterator n, iterator end, value_type const& v)
{
for(;n != end; n = next_node(n))
if (n->value() == v)
for(;n != end; ++n)
if (*n == v)
return true;
return false;
}
static std::size_t count_equal(node_pointer n, node_pointer end,
static std::size_t count_equal(iterator n, iterator end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; n = next_node(n))
if (n->value() == v) ++count;
for(;n != end; ++n)
if (*n == v) ++count;
return count;
}
// Emplace/Insert
// Add node 'n' to the group containing 'pos'.
// If 'pos' is the first node in group, add to the end of the group,
// otherwise add before 'pos'.
static inline void add_to_node_group(
static inline void add_after_node(
node_pointer n,
node_pointer pos)
{
@@ -344,17 +374,18 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = n;
}
inline node_pointer add_node(
node_pointer n,
inline iterator add_node(
node_constructor& a,
std::size_t key_hash,
node_pointer pos)
iterator pos)
{
node_pointer n = a.release();
n->hash_ = key_hash;
if (pos) {
this->add_to_node_group(n, pos);
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
next_node(n)->hash_);
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
@@ -370,7 +401,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
next_node(start_node)->hash_
static_cast<node_pointer>(start_node->next_)->hash_
))->next_ = n;
}
@@ -385,26 +416,27 @@ namespace boost { namespace unordered { namespace detail {
}
}
++this->size_;
return n;
return iterator(n);
}
inline node_pointer add_using_hint(
node_pointer n,
node_pointer hint)
iterator emplace_impl(node_constructor& a)
{
n->hash_ = hint->hash_;
this->add_to_node_group(n, hint);
if (n->next_ != hint && n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
next_node(n)->hash_);
if (next_bucket != this->hash_to_bucket(n->hash_)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
++this->size_;
return n;
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a, key_hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -414,13 +446,6 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(c_iterator, boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
@@ -428,65 +453,16 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_impl(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_hint_impl(hint,
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
iterator emplace_impl(node_pointer n)
{
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
return iterator(this->add_node(a.release(), key_hash, position));
}
iterator emplace_hint_impl(c_iterator hint, node_pointer n)
{
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
return iterator(this->add_using_hint(a.release(), hint.node_));
}
else {
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
return iterator(this->add_node(a.release(), key_hash, position));
}
}
void emplace_impl_no_rehash(node_pointer n)
{
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
this->add_node(a.release(), key_hash, position);
return iterator(emplace_impl(a));
}
////////////////////////////////////////////////////////////////////////
@@ -495,37 +471,37 @@ namespace boost { namespace unordered { namespace detail {
// if hash function throws, or inserting > 1 element, basic exception
// safety. Strong otherwise
template <class I>
void insert_range(I i, I j, typename
boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
typename boost::unordered::detail::enable_if_forward<I, void>::type
insert_range(I i, I j)
{
if(i == j) return;
std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
std::size_t distance = boost::unordered::detail::distance(i, j);
if(distance == 1) {
emplace_impl(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
node_constructor a(this->node_alloc());
a.construct_with_value2(*i);
emplace_impl(a);
}
else {
// Only require basic exception safety here
this->reserve_for_insert(this->size_ + distance);
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
emplace_impl_no_rehash(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
}
}
}
template <class I>
void insert_range(I i, I j, typename
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
typename boost::unordered::detail::disable_if_forward<I, void>::type
insert_range(I i, I j)
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
emplace_impl(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
a.construct_with_value2(*i);
emplace_impl(a);
}
}
@@ -543,34 +519,35 @@ namespace boost { namespace unordered { namespace detail {
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
node_pointer first_node;
for (;;)
{
if (!prev->next_) return 0;
first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(first_node->value())))
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = first_node->group_prev_;
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
node_pointer first_node = static_cast<node_pointer>(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
std::size_t count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return count;
}
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
node_pointer next = next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
@@ -580,47 +557,48 @@ namespace boost { namespace unordered { namespace detail {
return iterator(r2.node_);
}
link_pointer erase_nodes(node_pointer i, node_pointer j)
link_pointer erase_nodes(node_pointer begin, node_pointer end)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// Split the groups containing 'begin' and 'end'.
// And get the pointer to the node before begin while
// we're at it.
link_pointer prev = split_groups(i, j);
link_pointer prev = split_groups(begin, end);
// If we don't have a 'prev' it means that i is at the
// If we don't have a 'prev' it means that begin is at the
// beginning of a block, so search through the blocks in the
// same bucket.
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i)
prev = next_node(prev)->group_prev_;
while (prev->next_ != begin)
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
// Delete the nodes.
do {
link_pointer group_end = next_group(next_node(prev));
link_pointer group_end =
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
} while(prev->next_ != end);
return prev;
}
static link_pointer split_groups(node_pointer i, node_pointer j)
static link_pointer split_groups(node_pointer begin, node_pointer end)
{
node_pointer prev = i->group_prev_;
if (prev->next_ != i) prev = node_pointer();
node_pointer prev = begin->group_prev_;
if (prev->next_ != begin) prev = node_pointer();
if (j) {
node_pointer first = j;
while (first != i && first->group_prev_->next_ == first) {
if (end) {
node_pointer first = end;
while (first != begin && first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, j->group_prev_);
if (first == i) return prev;
boost::swap(first->group_prev_, end->group_prev_);
if (first == begin) return prev;
}
if (prev) {
@@ -628,7 +606,7 @@ namespace boost { namespace unordered { namespace detail {
while (first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, i->group_prev_);
boost::swap(first->group_prev_, begin->group_prev_);
}
return prev;
@@ -637,65 +615,31 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////
// fill_buckets
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
link_pointer prev = dst.get_previous_start();
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = key_hash;
prev->next_ = first_node;
++dst.size_;
for (++n; n != group_end; ++n)
{
this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), key_hash, pos);
end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
}
}
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), key_hash, pos);
}
}
}
void assign_buckets(table const& src) {
node_holder<node_allocator> holder(*this);
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(holder.copy_of(n->value()), key_hash, pos);
}
}
}
void move_assign_buckets(table& src) {
node_holder<node_allocator> holder(*this);
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(holder.move_copy_of(n->value()), key_hash, pos);
}
prev = place_in_bucket(dst, prev, end);
}
}
@@ -707,7 +651,8 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_);
prev = place_in_bucket(*this, prev,
static_cast<node_pointer>(prev->next_)->group_prev_);
}
// Iterate through the nodes placing them in the correct buckets.
+18 -23
View File
@@ -6,11 +6,6 @@
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
namespace boost {
@@ -51,7 +46,7 @@ namespace detail {
typedef ValueType value_type;
typedef ValueType key_type;
static key_type const& extract(value_type const& v)
static key_type const& extract(key_type const& v)
{
return v;
}
@@ -61,19 +56,19 @@ namespace detail {
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
{
return no_key();
}
#else
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
@@ -112,6 +107,14 @@ namespace detail {
return k;
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
static no_key extract()
{
return no_key();
@@ -123,16 +126,8 @@ namespace detail {
return no_key();
}
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class Arg3, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
Args const&...)
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
{
return no_key();
}
+3 -37
View File
@@ -1,56 +1,22 @@
// Copyright (C) 2008-2016 Daniel James.
// Copyright (C) 2008-2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
// Already defined.
#elif defined(BOOST_LIBSTDCXX11)
// https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70
# if BOOST_LIBSTDCXX_VERSION > 40600
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
# endif
#elif defined(_LIBCPP_VERSION)
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
# if LIBCPP_VERSION >= 3000
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
# endif
#elif defined(BOOST_MSVC)
// Apparently C++11 standard supported in Visual Studio 2012
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
# if BOOST_MSVC >= 1700
# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
# endif
#endif
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
#endif
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#include <utility>
#endif
namespace boost
{
namespace unordered
{
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
using std::piecewise_construct_t;
using std::piecewise_construct;
#else
struct piecewise_construct_t {};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
}
}
-79
View File
@@ -1,79 +0,0 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator>
traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
template <typename A, typename K, typename M, typename H, typename P>
struct multimap
{
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
}}}
-75
View File
@@ -1,75 +0,0 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::
c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::
c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
}}}
+195 -123
View File
@@ -7,18 +7,29 @@
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/buckets.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cmath>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant
#endif
#if defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
#if defined(__EDG__)
#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
#pragma message("Warning: BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported.")
#elif defined(__GNUC__) || defined(__HP_aCC) || \
defined(__SUNPRO_CC) || defined(__IBMCPP__)
#warning "BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported."
#endif
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
@@ -43,10 +54,6 @@ namespace boost { namespace unordered { namespace detail {
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
value_base() :
data_()
{}
void* address() {
return this;
}
@@ -64,6 +71,70 @@ namespace boost { namespace unordered { namespace detail {
value_base& operator=(value_base const&);
};
template <typename NodeAlloc>
struct copy_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type const& v)
{
constructor.construct_with_value2(v);
return constructor.release();
}
};
template <typename NodeAlloc>
struct move_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit move_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type& v)
{
constructor.construct_with_value2(boost::move(v));
return constructor.release();
}
};
template <typename Buckets>
struct assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type const& v)
{
return holder.copy_of(v);
}
};
template <typename Buckets>
struct move_assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit move_assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type& v)
{
return holder.move_copy_of(v);
}
};
template <typename Types>
struct table :
boost::unordered::detail::functions<
@@ -84,15 +155,10 @@ namespace boost { namespace unordered { namespace detail {
typedef typename Types::table table_impl;
typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy;
typedef typename Types::iterator iterator;
typedef typename Types::c_iterator c_iterator;
typedef typename Types::l_iterator l_iterator;
typedef typename Types::cl_iterator cl_iterator;
typedef boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal> functions;
typedef typename functions::set_hash_functions set_hash_functions;
typedef typename Types::allocator allocator;
typedef typename boost::unordered::detail::
@@ -111,8 +177,15 @@ namespace boost { namespace unordered { namespace detail {
bucket_pointer;
typedef boost::unordered::detail::node_constructor<node_allocator>
node_constructor;
typedef boost::unordered::detail::node_tmp<node_allocator>
node_tmp;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node, const_node_pointer> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, const_node_pointer, policy> cl_iterator;
////////////////////////////////////////////////////////////////////////
// Members
@@ -125,13 +198,6 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_load_;
bucket_pointer buckets_;
////////////////////////////////////////////////////////////////////////
// Node functions
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
////////////////////////////////////////////////////////////////////////
// Data access
@@ -178,21 +244,21 @@ namespace boost { namespace unordered { namespace detail {
return get_bucket(bucket_index)->next_;
}
node_pointer begin() const
iterator begin() const
{
return size_ ? next_node(get_previous_start()) : node_pointer();
return size_ ? iterator(get_previous_start()->next_) : iterator();
}
node_pointer begin(std::size_t bucket_index) const
iterator begin(std::size_t bucket_index) const
{
if (!size_) return node_pointer();
if (!size_) return iterator();
link_pointer prev = get_previous_start(bucket_index);
return prev ? next_node(prev) : node_pointer();
return prev ? iterator(prev->next_) : iterator();
}
std::size_t hash_to_bucket(std::size_t hash_value) const
std::size_t hash_to_bucket(std::size_t hash) const
{
return policy::to_bucket(bucket_count_, hash_value);
return policy::to_bucket(bucket_count_, hash);
}
float load_factor() const
@@ -204,14 +270,14 @@ namespace boost { namespace unordered { namespace detail {
std::size_t bucket_size(std::size_t index) const
{
node_pointer n = begin(index);
if (!n) return 0;
iterator it = begin(index);
if (!it.node_) return 0;
std::size_t count = 0;
while(n && hash_to_bucket(n->hash_) == index)
while(it.node_ && hash_to_bucket(it.node_->hash_) == index)
{
++count;
n = next_node(n);
++it;
}
return count;
@@ -267,7 +333,7 @@ namespace boost { namespace unordered { namespace detail {
return policy::new_bucket_count(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_)) + 1));
static_cast<double>(mlf_))) + 1);
}
////////////////////////////////////////////////////////////////////////
@@ -297,7 +363,7 @@ namespace boost { namespace unordered { namespace detail {
{}
table(table& x, boost::unordered::detail::move_tag m) :
functions(x, m),
functions(x),
allocators_(x.allocators_, m),
bucket_count_(x.bucket_count_),
size_(x.size_),
@@ -311,8 +377,8 @@ namespace boost { namespace unordered { namespace detail {
}
table(table& x, node_allocator const& a,
boost::unordered::detail::move_tag m) :
functions(x, m),
boost::unordered::detail::move_tag) :
functions(x),
allocators_(a, a),
bucket_count_(x.bucket_count_),
size_(0),
@@ -327,7 +393,9 @@ namespace boost { namespace unordered { namespace detail {
void init(table const& x)
{
if (x.size_) {
static_cast<table_impl*>(this)->copy_buckets(x);
create_buckets(bucket_count_);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
@@ -338,7 +406,11 @@ namespace boost { namespace unordered { namespace detail {
}
else if(x.size_) {
// TODO: Could pick new bucket size?
static_cast<table_impl*>(this)->move_buckets(x);
create_buckets(bucket_count_);
move_nodes<node_allocator> move(node_alloc());
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, move);
}
}
@@ -347,53 +419,34 @@ namespace boost { namespace unordered { namespace detail {
void create_buckets(std::size_t new_count)
{
std::size_t length = new_count + 1;
bucket_pointer new_buckets = bucket_allocator_traits::allocate(
bucket_alloc(), length);
bucket_pointer constructed = new_buckets;
boost::unordered::detail::array_constructor<bucket_allocator>
constructor(bucket_alloc());
// Creates an extra bucket to act as the start node.
constructor.construct(bucket(), new_count + 1);
BOOST_TRY {
bucket_pointer end = new_buckets
+ static_cast<std::ptrdiff_t>(length);
for(; constructed != end; ++constructed) {
new ((void*) boost::addressof(*constructed)) bucket();
}
if (buckets_)
{
// Copy the nodes to the new buckets, including the dummy
// node if there is one.
(new_buckets +
static_cast<std::ptrdiff_t>(new_count))->next_ =
(buckets_ + static_cast<std::ptrdiff_t>(
bucket_count_))->next_;
destroy_buckets();
}
else if (bucket::extra_node)
{
node_constructor a(node_alloc());
a.create_node();
(new_buckets +
static_cast<std::ptrdiff_t>(new_count))->next_ =
a.release();
}
if (buckets_)
{
// Copy the nodes to the new buckets, including the dummy
// node if there is one.
(constructor.get() +
static_cast<std::ptrdiff_t>(new_count))->next_ =
(buckets_ + static_cast<std::ptrdiff_t>(
bucket_count_))->next_;
destroy_buckets();
}
BOOST_CATCH(...) {
for(bucket_pointer p = new_buckets; p != constructed; ++p) {
boost::unordered::detail::func::destroy(
boost::addressof(*p));
}
else if (bucket::extra_node)
{
node_constructor a(node_alloc());
a.construct();
bucket_allocator_traits::deallocate(bucket_alloc(),
new_buckets, length);
BOOST_RETHROW;
(constructor.get() +
static_cast<std::ptrdiff_t>(new_count))->next_ =
a.release();
}
BOOST_CATCH_END
bucket_count_ = new_count;
buckets_ = new_buckets;
buckets_ = constructor.release();
recalculate_max_load();
}
@@ -402,8 +455,6 @@ namespace boost { namespace unordered { namespace detail {
void swap_allocators(table& other, false_type)
{
boost::unordered::detail::func::ignore_unused_variable_warning(other);
// According to 23.2.1.8, if propagate_on_container_swap is
// false the behaviour is undefined unless the allocators
// are equal.
@@ -418,8 +469,10 @@ namespace boost { namespace unordered { namespace detail {
// Only swaps the allocators if propagate_on_container_swap
void swap(table& x)
{
set_hash_functions op1(*this, x);
set_hash_functions op2(x, *this);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
op1(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
op2(x, *this);
// I think swap can throw if Propagate::value,
// since the allocators' swap can throw. Not sure though.
@@ -437,11 +490,9 @@ namespace boost { namespace unordered { namespace detail {
op2.commit();
}
// Only call with nodes allocated with the currect allocator, or
// one that is equal to it. (Can't assert because other's
// allocators might have already been moved).
void move_buckets_from(table& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
BOOST_ASSERT(!buckets_);
buckets_ = other.buckets_;
bucket_count_ = other.bucket_count_;
@@ -464,9 +515,10 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
boost::unordered::detail::func::call_destroy(node_alloc(),
boost::unordered::detail::destroy_value_impl(node_alloc(),
n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
--size_;
}
@@ -493,7 +545,7 @@ namespace boost { namespace unordered { namespace detail {
if (bucket::extra_node) {
node_pointer n = static_cast<node_pointer>(
get_bucket(bucket_count_)->next_);
boost::unordered::detail::func::destroy(
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
}
@@ -530,7 +582,7 @@ namespace boost { namespace unordered { namespace detail {
bucket_pointer end = get_bucket(bucket_count_ + 1);
for(bucket_pointer it = buckets_; it != end; ++it)
{
boost::unordered::detail::func::destroy(
bucket_allocator_traits::destroy(bucket_alloc(),
boost::addressof(*it));
}
@@ -585,14 +637,13 @@ namespace boost { namespace unordered { namespace detail {
void assign(table const& x, false_type)
{
// Strong exception safety.
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
if (!size_ && !x.size_) {
new_func_this.commit();
return;
}
if (!size_ && !x.size_) return;
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
@@ -601,8 +652,11 @@ namespace boost { namespace unordered { namespace detail {
clear_buckets();
}
new_func_this.commit();
static_cast<table_impl*>(this)->assign_buckets(x);
// assign_nodes takes ownership of the container's elements,
// assigning to them if possible, and deleting any that are
// left over.
assign_nodes<table> assign(*this);
table_impl::fill_buckets(x.begin(), *this, assign);
}
void assign(table const& x, true_type)
@@ -612,7 +666,8 @@ namespace boost { namespace unordered { namespace detail {
assign(x, false_type());
}
else {
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
// Delete everything with current allocators before assigning
// the new ones.
@@ -627,7 +682,9 @@ namespace boost { namespace unordered { namespace detail {
// Finally copy the elements.
if (x.size_) {
static_cast<table_impl*>(this)->copy_buckets(x);
create_buckets(bucket_count_);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
}
@@ -646,35 +703,24 @@ namespace boost { namespace unordered { namespace detail {
void move_assign(table& x, true_type)
{
delete_buckets();
set_hash_functions new_func_this(*this, x);
allocators_.move_assign(x.allocators_);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
move_assign_no_alloc(x);
}
void move_assign(table& x, false_type)
{
if (node_alloc() == x.node_alloc()) {
delete_buckets();
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
move_assign_no_alloc(x);
}
else {
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
if (!size_ && !x.size_) {
new_func_this.commit();
return;
}
if (!size_ && !x.size_) return;
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
@@ -683,10 +729,25 @@ namespace boost { namespace unordered { namespace detail {
clear_buckets();
}
new_func_this.commit();
static_cast<table_impl*>(this)->move_assign_buckets(x);
// move_assign_nodes takes ownership of the container's
// elements, assigning to them if possible, and deleting
// any that are left over.
move_assign_nodes<table> assign(*this);
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, assign);
}
}
void move_assign_no_alloc(table& x)
{
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
// Accessors
@@ -703,7 +764,7 @@ namespace boost { namespace unordered { namespace detail {
// Find Node
template <typename Key, typename Hash, typename Pred>
node_pointer generic_find_node(
iterator generic_find_node(
Key const& k,
Hash const& hf,
Pred const& eq) const
@@ -712,7 +773,7 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
node_pointer find_node(
iterator find_node(
std::size_t key_hash,
key_type const& k) const
{
@@ -720,12 +781,23 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(key_hash, k, this->key_eq());
}
node_pointer find_node(key_type const& k) const
iterator find_node(key_type const& k) const
{
return static_cast<table_impl const*>(this)->
find_node_impl(hash(k), k, this->key_eq());
}
iterator find_matching_node(iterator n) const
{
// TODO: Does this apply to C++11?
//
// For some stupid reason, I decided to support equality comparison
// when different hash functions are used. So I can't use the hash
// value from the node here.
return find_node(get_key(*n));
}
// Reserve and rehash
void reserve_for_insert(std::size_t);
+165 -226
View File
@@ -7,11 +7,11 @@
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
@@ -27,9 +27,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
A, unique_node<A, T> >::type::pointer node_pointer;
typedef node_pointer link_pointer;
link_pointer next_;
@@ -50,15 +48,14 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
ptr_node() :
bucket_base(),
@@ -69,10 +66,6 @@ namespace boost { namespace unordered { namespace detail {
{
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
ptr_node& operator=(ptr_node const&);
};
@@ -106,11 +99,9 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct pick_node
{
typedef typename boost::remove_const<T>::type nonconst;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_node<nonconst> >::type
boost::unordered::detail::ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@@ -118,7 +109,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_node2<A, nonconst,
typedef pick_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
@@ -127,6 +118,54 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator>
traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
struct table_impl : boost::unordered::detail::table<Types>
{
@@ -143,7 +182,6 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::node_tmp node_tmp;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
@@ -186,53 +224,47 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
// Node functions.
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
node_pointer n = this->begin(bucket_index);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return node_pointer();
return iterator();
}
n = next_node(n);
++n;
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k) ? 1 : 0;
return this->find_node(k).node_ ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
node_pointer n = this->find_node(k);
if (n) return n->value();
iterator it = this->find_node(k);
if (it.node_) return *it;
}
boost::throw_exception(
@@ -242,8 +274,10 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n), iterator(n ? next_node(n) : n));
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
}
// equals
@@ -252,11 +286,11 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
for(node_pointer n1 = this->begin(); n1; n1 = next_node(n1))
for(iterator n1 = this->begin(); n1.node_; ++n1)
{
node_pointer n2 = other.find_node(other.get_key(n1->value()));
iterator n2 = other.find_matching_node(n1);
if (!n2 || n1->value() != n2->value())
if (!n2.node_ || *n1 != *n2)
return false;
}
@@ -265,10 +299,11 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline node_pointer add_node(
node_pointer n,
inline iterator add_node(
node_constructor& a,
std::size_t key_hash)
{
node_pointer n = a.release();
n->hash_ = key_hash;
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
@@ -279,7 +314,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
next_node(start_node)->hash_)
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
}
@@ -294,28 +329,28 @@ namespace boost { namespace unordered { namespace detail {
}
++this->size_;
return n;
}
inline node_pointer resize_and_add_node(node_pointer n, std::size_t key_hash)
{
node_tmp b(n, this->node_alloc());
this->reserve_for_insert(this->size_ + 1);
return this->add_node(b.release(), key_hash);
return iterator(n);
}
value_type& operator[](key_type const& k)
{
typedef typename value_type::second_type mapped_type;
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return pos->value();
}
else {
return this->resize_and_add_node(
boost::unordered::detail::func::construct_node_pair(this->node_alloc(), k),
key_hash)->value();
}
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return *pos;
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
this->reserve_for_insert(this->size_ + 1);
return *add_node(a, key_hash);
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -324,29 +359,14 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
return emplace_return(this->begin(), false);
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
return emplace_return(this->begin(), false);
}
# endif
#endif
@@ -365,21 +385,6 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint,
BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_hint_impl(hint,
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_hint_impl(hint,
extractor::extract(args.a0, args.a1),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
@@ -387,86 +392,50 @@ namespace boost { namespace unordered { namespace detail {
{
return emplace_impl(extractor::extract(args.a0), args);
}
template <typename A0>
iterator emplace_hint(c_iterator hint,
boost::unordered::detail::emplace_args1<A0> const& args)
{
return emplace_hint_impl(hint, extractor::extract(args.a0), args);
}
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint_impl(c_iterator hint, key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
else {
return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
iterator(this->resize_and_add_node(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
key_hash)),
true);
}
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint_impl(c_iterator hint, no_key,
BOOST_UNORDERED_EMPLACE_ARGS)
emplace_return emplace_impl_with_node(node_constructor& a)
{
node_tmp b(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return iterator(pos);
}
else {
return iterator(this->resize_and_add_node(b.release(), key_hash));
}
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
iterator(this->resize_and_add_node(b.release(), key_hash)),
true);
}
// Don't have a key, so construct the node first in order
// to be able to lookup the position.
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
}
////////////////////////////////////////////////////////////////////////
@@ -485,7 +454,9 @@ namespace boost { namespace unordered { namespace detail {
template <class InputIt>
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
{
insert_range_impl2(k, i, j);
node_constructor a(this->node_alloc());
insert_range_impl2(a, k, i, j);
while(++i != j) {
// Note: can't use get_key as '*i' might not be value_type - it
@@ -496,25 +467,26 @@ namespace boost { namespace unordered { namespace detail {
// key here. Could be more efficient if '*i' is expensive. Could
// be less efficient if copying the full value_type is
// expensive.
insert_range_impl2(extractor::extract(*i), i, j);
insert_range_impl2(a, extractor::extract(*i), i, j);
}
}
template <class InputIt>
void insert_range_impl2(key_type const& k, InputIt i, InputIt j)
void insert_range_impl2(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
iterator pos = this->find_node(key_hash, k);
if (!pos) {
node_tmp b(
boost::unordered::detail::func::construct_node(this->node_alloc(), *i),
this->node_alloc());
if (!pos.node_) {
a.construct_with_value2(*i);
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
this->add_node(b.release(), key_hash);
// Nothing after this point can throw.
this->add_node(a, key_hash);
}
}
@@ -524,24 +496,8 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
do {
if (!a.node_) { a.create_node(); }
boost::unordered::detail::func::call_construct(
a.alloc_, a.node_->value_ptr(), *i);
node_tmp b(a.release(), a.alloc_);
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
a.reclaim(b.release());
}
else {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
this->add_node(b.release(), key_hash);
}
a.construct_with_value2(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
@@ -562,29 +518,31 @@ namespace boost { namespace unordered { namespace detail {
for (;;)
{
if (!prev->next_) return 0;
std::size_t node_hash = next_node(prev)->hash_;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
next_node(prev)->value())))
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = prev->next_;
}
link_pointer end = next_node(prev)->next_;
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
std::size_t count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return count;
}
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
node_pointer next = next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
@@ -594,57 +552,38 @@ namespace boost { namespace unordered { namespace detail {
return iterator(r2.node_);
}
void erase_nodes(node_pointer i, node_pointer j)
void erase_nodes(node_pointer begin, node_pointer end)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
// Find the node before i.
// Find the node before begin.
link_pointer prev = this->get_previous_start(bucket_index);
while(prev->next_ != i) prev = prev->next_;
while(prev->next_ != begin) prev = prev->next_;
// Delete the nodes.
do {
this->delete_node(prev);
bucket_index = this->fix_bucket(bucket_index, prev);
} while (prev->next_ != j);
} while (prev->next_ != end);
}
////////////////////////////////////////////////////////////////////////
// fill_buckets
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), n->hash_);
}
}
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), n->hash_);
}
}
void assign_buckets(table const& src)
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
node_holder<node_allocator> holder(*this);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(holder.copy_of(n->value()), n->hash_);
}
}
link_pointer prev = dst.get_previous_start();
void move_assign_buckets(table& src)
{
node_holder<node_allocator> holder(*this);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(holder.move_copy_of(n->value()), n->hash_);
while (n.node_) {
node_pointer node = creator.create(*n);
node->hash_ = n.node_->hash_;
prev->next_ = node;
++dst.size_;
++n;
prev = place_in_bucket(dst, prev);
}
}
@@ -663,7 +602,7 @@ namespace boost { namespace unordered { namespace detail {
// pre: prev->next_ is not null.
static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
node_pointer n = next_node(prev);
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {
+24 -13
View File
@@ -7,9 +7,8 @@
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
@@ -29,11 +28,6 @@ namespace boost { namespace unordered { namespace detail {
struct move_tag {};
struct empty_emplace {};
namespace func {
template <class T>
inline void ignore_unused_variable_warning(T const&) {}
}
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
@@ -124,16 +118,33 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// insert_size/initial_size
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
template <class I>
inline std::size_t insert_size(I i, I j, typename
boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
inline typename
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
insert_size(I i, I j)
{
return static_cast<std::size_t>(std::distance(i, j));
return std::distance(i, j);
}
template <class I>
inline std::size_t insert_size(I, I, typename
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
inline typename
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
insert_size(I, I)
{
return 1;
}
+103 -298
View File
@@ -9,13 +9,14 @@
#ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/map.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
@@ -82,23 +83,12 @@ namespace unordered
// constructors
unordered_map();
explicit unordered_map(
size_type,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_map(
size_type,
const allocator_type&);
explicit unordered_map(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_map(allocator_type const&);
template <class InputIt>
@@ -119,40 +109,28 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_map(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_map(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_map(unordered_map const&);
unordered_map(unordered_map const&, allocator_type const&);
unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list<value_type>,
@@ -160,20 +138,11 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_map(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_map(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
~unordered_map() BOOST_NOEXCEPT;
~unordered_map();
// Assign
@@ -209,53 +178,53 @@ namespace unordered
unordered_map& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -270,9 +239,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...).first;
}
#else
@@ -311,12 +280,12 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
).first;
}
template <typename A0, typename A1>
@@ -332,15 +301,15 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
).first;
}
template <typename A0, typename A1, typename A2>
@@ -358,17 +327,17 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
).first;
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
@@ -390,15 +359,15 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator hint, \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace_hint(hint, \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)); \
)).first; \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -480,12 +449,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -532,13 +501,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -595,23 +564,12 @@ namespace unordered
// constructors
unordered_multimap();
explicit unordered_multimap(
size_type,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_multimap(
size_type,
const allocator_type&);
explicit unordered_multimap(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_multimap(allocator_type const&);
template <class InputIt>
@@ -632,40 +590,28 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_multimap(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_multimap(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_multimap(unordered_multimap const&);
unordered_multimap(unordered_multimap const&, allocator_type const&);
unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list<value_type>,
@@ -673,20 +619,11 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_multimap(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_multimap(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
~unordered_multimap() BOOST_NOEXCEPT;
~unordered_multimap();
// Assign
@@ -723,53 +660,53 @@ namespace unordered
unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -784,9 +721,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...);
}
#else
@@ -825,9 +762,9 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
@@ -846,11 +783,11 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
@@ -872,12 +809,12 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
@@ -904,11 +841,11 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator hint, \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace_hint(hint, \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
@@ -990,12 +927,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -1042,13 +979,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -1062,13 +999,6 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1077,20 +1007,6 @@ namespace unordered
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1141,32 +1057,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_map<K,T,H,P,A>::unordered_map(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_map<K,T,H,P,A>::unordered_map(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
unordered_map<K,T,H,P,A>::~unordered_map() {}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1175,13 +1066,17 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
BOOST_RV_REF(unordered_map) other, allocator_type const& a)
unordered_map&& other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
@@ -1196,30 +1091,6 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>& unordered_map<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@@ -1234,7 +1105,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_map<K,T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1334,14 +1205,14 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1353,7 +1224,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1365,7 +1236,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1403,13 +1274,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_map<K,T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_map<K,T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -1461,13 +1332,6 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1476,20 +1340,6 @@ namespace unordered
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1540,32 +1390,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1574,13 +1399,17 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
unordered_multimap&& other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
@@ -1595,30 +1424,6 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>& unordered_multimap<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@@ -1633,7 +1438,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1712,14 +1517,14 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1731,7 +1536,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1743,7 +1548,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1781,13 +1586,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_multimap<K,T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
+101 -295
View File
@@ -9,12 +9,14 @@
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/set.hpp>
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
@@ -67,9 +69,9 @@ namespace unordered
typedef std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator;
typedef typename table::l_iterator local_iterator;
typedef typename table::cl_iterator local_iterator;
typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
typedef typename table::c_iterator iterator;
private:
@@ -79,23 +81,12 @@ namespace unordered
// constructors
unordered_set();
explicit unordered_set(
size_type,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_set(
size_type,
const allocator_type&);
explicit unordered_set(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_set(allocator_type const&);
template <class InputIt>
@@ -116,40 +107,28 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_set(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_set(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_set(unordered_set const&);
unordered_set(unordered_set const&, allocator_type const&);
unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>,
@@ -157,20 +136,11 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_set(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_set(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
~unordered_set() BOOST_NOEXCEPT;
~unordered_set();
// Assign
@@ -206,53 +176,53 @@ namespace unordered
unordered_set& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -267,9 +237,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...).first;
}
#else
@@ -308,12 +278,12 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
).first;
}
template <typename A0, typename A1>
@@ -329,15 +299,15 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
).first;
}
template <typename A0, typename A1, typename A2>
@@ -355,17 +325,17 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
).first;
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
@@ -387,15 +357,15 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator hint, \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace_hint(hint, \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)); \
)).first; \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -464,12 +434,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -516,13 +486,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -566,9 +536,9 @@ namespace unordered
typedef std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator;
typedef typename table::l_iterator local_iterator;
typedef typename table::cl_iterator local_iterator;
typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
typedef typename table::c_iterator iterator;
private:
@@ -578,23 +548,12 @@ namespace unordered
// constructors
unordered_multiset();
explicit unordered_multiset(
size_type,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_multiset(
size_type,
const allocator_type&);
explicit unordered_multiset(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_multiset(allocator_type const&);
template <class InputIt>
@@ -615,40 +574,28 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_multiset(unordered_multiset const&);
unordered_multiset(unordered_multiset const&, allocator_type const&);
unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>,
@@ -656,20 +603,11 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_multiset(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_multiset(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
~unordered_multiset() BOOST_NOEXCEPT;
~unordered_multiset();
// Assign
@@ -706,53 +644,53 @@ namespace unordered
unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -767,9 +705,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...);
}
#else
@@ -808,9 +746,9 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
@@ -829,11 +767,11 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
@@ -855,12 +793,12 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace_hint(hint,
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
@@ -887,11 +825,11 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator hint, \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace_hint(hint, \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
@@ -964,12 +902,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -1016,13 +954,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -1036,13 +974,6 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1051,20 +982,6 @@ namespace unordered
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1115,32 +1032,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_set<T,H,P,A>::unordered_set(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_set<T,H,P,A>::unordered_set(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
unordered_set<T,H,P,A>::~unordered_set() {}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1149,13 +1041,17 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
BOOST_RV_REF(unordered_set) other, allocator_type const& a)
unordered_set&& other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
@@ -1170,30 +1066,6 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@@ -1208,7 +1080,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_set<T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1287,7 +1159,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -1299,7 +1171,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1328,13 +1200,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_set<T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_set<T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -1386,13 +1258,6 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1401,20 +1266,6 @@ namespace unordered
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1465,32 +1316,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_multiset<T,H,P,A>::unordered_multiset(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_multiset<T,H,P,A>::unordered_multiset(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1499,13 +1325,17 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
unordered_multiset&& other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
@@ -1520,30 +1350,6 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@@ -1558,7 +1364,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_multiset<T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1637,7 +1443,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -1649,7 +1455,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1678,13 +1484,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_multiset<T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_map.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_set.hpp>
-17
View File
@@ -1,17 +0,0 @@
{
"key": "unordered",
"name": "Unordered",
"authors": [
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
]
}
+2 -79
View File
@@ -5,82 +5,5 @@
import testing ;
project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
<toolset>msvc:<cxxflags>"/wd4494"
;
#alias framework : /boost/test//boost_unit_test_framework ;
alias framework : ;
test-suite unordered
:
[ run unordered/fwd_set_test.cpp ]
[ run unordered/fwd_map_test.cpp ]
[ run unordered/allocator_traits.cpp ]
[ run unordered/minimal_allocator.cpp ]
[ run unordered/compile_set.cpp ]
[ run unordered/compile_map.cpp ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
: compile_map_unordered_allocator ]
[ run unordered/noexcept_tests.cpp ]
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
[ run unordered/incomplete_test.cpp ]
[ run unordered/simple_tests.cpp ]
[ run unordered/equivalent_keys_tests.cpp ]
[ run unordered/constructor_tests.cpp ]
[ run unordered/copy_tests.cpp ]
[ run unordered/move_tests.cpp ]
[ run unordered/assign_tests.cpp ]
[ run unordered/insert_tests.cpp ]
[ run unordered/insert_stable_tests.cpp ]
[ run unordered/insert_hint_tests.cpp ]
[ run unordered/emplace_tests.cpp ]
[ run unordered/unnecessary_copy_tests.cpp ]
[ run unordered/erase_tests.cpp ]
[ run unordered/erase_equiv_tests.cpp ]
[ run unordered/find_tests.cpp ]
[ run unordered/at_tests.cpp ]
[ run unordered/bucket_tests.cpp ]
[ run unordered/load_factor_tests.cpp ]
[ run unordered/rehash_tests.cpp ]
[ run unordered/equality_tests.cpp ]
[ run unordered/swap_tests.cpp ]
[ run unordered/compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run unordered/copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run unordered/move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run unordered/assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
test-suite unordered-exception
:
[ run exception/constructor_exception_tests.cpp framework ]
[ run exception/copy_exception_tests.cpp framework ]
[ run exception/assign_exception_tests.cpp framework ]
[ run exception/move_assign_exception_tests.cpp framework ]
[ run exception/insert_exception_tests.cpp framework ]
[ run exception/erase_exception_tests.cpp framework ]
[ run exception/rehash_exception_tests.cpp framework ]
[ run exception/swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
build-project unordered ;
build-project exception ;
+34
View File
@@ -0,0 +1,34 @@
# Copyright 2006-2008 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
#alias framework : /boost/test//boost_unit_test_framework ;
alias framework : ;
project unordered-test/exception-tests
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
#<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
;
test-suite unordered-exception
:
[ run constructor_exception_tests.cpp framework ]
[ run copy_exception_tests.cpp framework ]
[ run assign_exception_tests.cpp framework ]
[ run insert_exception_tests.cpp framework ]
[ run erase_exception_tests.cpp framework ]
[ run rehash_exception_tests.cpp framework ]
[ run swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
+25 -61
View File
@@ -17,7 +17,7 @@ template <class T>
struct self_assign_base : public test::exception_base
{
test::random_values<T> values;
self_assign_base(std::size_t count = 0) : values(count) {}
self_assign_base(int count = 0) : values(count) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
@@ -38,18 +38,21 @@ struct self_assign_test2 : self_assign_base<T>
template <class T>
struct assign_base : public test::exception_base
{
test::random_values<T> x_values, y_values;
const test::random_values<T> x_values, y_values;
T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(),
y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(count1),
y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
@@ -63,86 +66,47 @@ struct assign_base : public test::exception_base
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
// internal structure is hidden, this exposes it.
T& y = const_cast<T&>(x1);
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
y.emplace(*x_values.begin());
test::check_equivalent_keys(y);
}
}
};
template <class T>
struct assign_values : assign_base<T>
struct assign_test1 : assign_base<T>
{
assign_values(unsigned int count1, unsigned int count2,
int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1);
this->y_values.fill(count2);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
assign_test1() : assign_base<T>(0, 0, 0, 0) {}
};
template <class T>
struct assign_test1 : assign_values<T>
struct assign_test2 : assign_base<T>
{
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
assign_test2() : assign_base<T>(60, 0, 0, 0) {}
};
template <class T>
struct assign_test2 : assign_values<T>
struct assign_test3 : assign_base<T>
{
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
assign_test3() : assign_base<T>(0, 60, 0, 0) {}
};
template <class T>
struct assign_test3 : assign_values<T>
struct assign_test4 : assign_base<T>
{
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
};
template <class T>
struct assign_test4 : assign_values<T>
struct assign_test5 : assign_base<T>
{
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
};
template <class T>
struct assign_test4a : assign_values<T>
{
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
};
template <class T>
struct assign_test5 : assign_values<T>
{
assign_test5() : assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
};
template <class T>
struct equivalent_test1 : assign_base<T>
{
equivalent_test1() :
assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
};
EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test4a)(assign_test5)
(equivalent_test1),
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
CONTAINER_SEQ)
RUN_TESTS()
+11 -12
View File
@@ -8,7 +8,7 @@
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/helpers.hpp"
#include <boost/utility.hpp>
#include <cmath>
test::seed_t initialize_seed(747373);
@@ -17,7 +17,7 @@ template <class T>
struct insert_test_base : public test::exception_base
{
test::random_values<T> values;
insert_test_base(unsigned int count = 5) : values(count, test::limited_range) {}
insert_test_base(unsigned int count = 5) : values(count) {}
typedef T data_type;
typedef test::strong<T> strong_type;
@@ -112,7 +112,7 @@ struct insert_test4 : public insert_test_base<T>
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, test::next(it));
x.insert(it, boost::next(it));
}
}
};
@@ -130,13 +130,12 @@ struct insert_test_rehash1 : public insert_test_base<T>
T x;
x.max_load_factor(0.25);
// TODO: This doesn't really work is bucket_count is 0
size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>(
ceil((double) bucket_count * (double) x.max_load_factor()) - 1);
ceil(bucket_count * (double) x.max_load_factor()) - 1);
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
test::next(this->values.begin(), initial_elements));
boost::next(this->values.begin(), initial_elements));
BOOST_TEST(bucket_count == x.bucket_count());
return x;
}
@@ -147,7 +146,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = test::next(this->values.begin(), x.size()),
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
@@ -171,7 +170,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
int count = 0;
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = test::next(this->values.begin(), x.size()),
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
@@ -202,14 +201,14 @@ struct insert_test_rehash3 : public insert_test_base<T>
original_bucket_count = x.bucket_count();
rehash_bucket_count = static_cast<size_type>(
ceil((double) original_bucket_count * (double) x.max_load_factor())) - 1;
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
size_type initial_elements =
rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
test::next(this->values.begin(), initial_elements));
boost::next(this->values.begin(), initial_elements));
BOOST_TEST(original_bucket_count == x.bucket_count());
return x;
}
@@ -217,8 +216,8 @@ struct insert_test_rehash3 : public insert_test_base<T>
void run(T& x) const {
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
x.insert(test::next(this->values.begin(), x.size()),
test::next(this->values.begin(), x.size() + 20));
x.insert(boost::next(this->values.begin(), x.size()),
boost::next(this->values.begin(), x.size() + 20));
// This isn't actually a failure, but it means the test isn't doing its
// job.
@@ -1,131 +0,0 @@
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable:4512) // move_assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
template <class T>
struct move_assign_base : public test::exception_base
{
test::random_values<T> x_values, y_values;
T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(),
y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const {
test::exceptions_enable disable_exceptions(false);
T y1 = y;
disable_exceptions.release();
x1 = boost::move(y1);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
}
};
template <class T>
struct move_assign_values : move_assign_base<T>
{
move_assign_values(unsigned int count1, unsigned int count2,
int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
move_assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1);
this->y_values.fill(count2);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
template <class T>
struct move_assign_test1 : move_assign_values<T>
{
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
};
template <class T>
struct move_assign_test2 : move_assign_values<T>
{
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
};
template <class T>
struct move_assign_test3 : move_assign_values<T>
{
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
};
template <class T>
struct move_assign_test4 : move_assign_values<T>
{
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
};
template <class T>
struct move_assign_test4a : move_assign_values<T>
{
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
};
template <class T>
struct move_assign_test5 : move_assign_values<T>
{
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
};
template <class T>
struct equivalent_test1 : move_assign_base<T>
{
equivalent_test1() :
move_assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
EXCEPTION_TESTS(
(move_assign_test1)(move_assign_test2)(move_assign_test3)(move_assign_test4)(move_assign_test4a)(move_assign_test5)
(equivalent_test1),
CONTAINER_SEQ)
RUN_TESTS()
+2 -2
View File
@@ -18,8 +18,8 @@ struct rehash_test_base : public test::exception_base
{
test::random_values<T> values;
unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count), n(n_)
rehash_test_base(unsigned int count = 100, unsigned int n = 0)
: values(count), n(n)
{}
typedef T data_type;
+3 -3
View File
@@ -17,7 +17,7 @@ template <class T>
struct self_swap_base : public test::exception_base
{
test::random_values<T> values;
self_swap_base(std::size_t count = 0) : values(count) {}
self_swap_base(int count = 0) : values(count) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
@@ -66,8 +66,8 @@ struct swap_base : public test::exception_base
{}
struct data_type {
data_type(T const& x_, T const& y_)
: x(x_), y(y_) {}
data_type(T const& x, T const& y)
: x(x), y(y) {}
T x, y;
};
+3 -9
View File
@@ -69,16 +69,10 @@ namespace test {
};
struct check_instances {
int instances_;
int constructions_;
int instances;
check_instances() :
instances_(global_object_count.instances),
constructions_(global_object_count.constructions) {}
~check_instances() { BOOST_TEST(global_object_count.instances == instances_); }
int instances() const { return global_object_count.instances - instances_; }
int constructions() const { return global_object_count.constructions - constructions_; }
check_instances() : instances(global_object_count.instances) {}
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
};
}
+9 -4
View File
@@ -42,15 +42,20 @@ namespace test
}
struct equivalent_type {
equivalent_type() {}
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const {
bool operator()(T1 const& x, T2 const& y) {
return equivalent_impl(x, y, derived);
}
};
const equivalent_type equivalent;
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
equivalent_type equivalent;
}
template <class Container>
class unordered_equivalence_tester
+12 -39
View File
@@ -111,28 +111,16 @@ namespace test {
exceptions_enable(exceptions_enable const&);
bool old_value_;
bool released_;
public:
exceptions_enable(bool enable)
: old_value_(exceptions_enabled), released_(false)
: old_value_(exceptions_enabled)
{
exceptions_enabled = enable;
}
~exceptions_enable()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
}
void release()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
exceptions_enabled = old_value_;
}
};
@@ -179,13 +167,12 @@ namespace test {
class test_runner
{
Test const& test_;
bool exception_in_check_;
test_runner(test_runner const&);
test_runner& operator=(test_runner const&);
public:
test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
void run() {
test_runner(Test const& t) : test_(t) {}
void operator()() const {
DISABLE_EXCEPTIONS;
test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
@@ -200,24 +187,14 @@ namespace test {
>(&Test::run, test_, x, strong);
}
catch(...) {
try {
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
} catch(...) {
exception_in_check_ = true;
}
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
throw;
}
}
void end() {
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
}
};
// Quick exception testing based on lightweight test
@@ -247,30 +224,26 @@ namespace test {
iteration = 0;
bool success = false;
char const* error_msg = 0;
do {
++iteration;
count = 0;
try {
runner.run();
runner();
success = true;
}
catch(test_failure) {
error_msg = "test_failure caught.";
BOOST_ERROR("test_failure caught.");
break;
}
catch(test_exception) {
continue;
}
catch(...) {
error_msg = "Unexpected exception.";
BOOST_ERROR("Unexpected exception.");
break;
}
} while(!success);
if (error_msg) { BOOST_ERROR(error_msg); }
runner.end();
}
}
}
+5 -11
View File
@@ -10,17 +10,11 @@
namespace test
{
typedef enum {
default_generator,
generate_collisions,
limited_range
} random_generator;
int generate(int const*, random_generator);
char generate(char const*, random_generator);
signed char generate(signed char const*, random_generator);
std::string generate(std::string const*, random_generator);
float generate(float const*, random_generator);
int generate(int const*);
char generate(char const*);
signed char generate(signed char const*);
std::string generate(std::string*);
float generate(float const*);
struct base_type {} base;
struct derived_type : base_type {} derived;
+10 -30
View File
@@ -27,32 +27,25 @@ namespace test
}
};
std::size_t random_value(std::size_t max) {
using namespace std;
return static_cast<std::size_t>(rand()) % max;
}
inline int generate(int const*, random_generator g)
inline int generate(int const*)
{
using namespace std;
int value = rand();
if (g == limited_range) { value = value % 100; }
return value;
return rand();
}
inline char generate(char const*, random_generator)
inline char generate(char const*)
{
using namespace std;
return static_cast<char>((rand() >> 1) % (128-32) + 32);
}
inline signed char generate(signed char const*, random_generator)
inline signed char generate(signed char const*)
{
using namespace std;
return static_cast<signed char>(rand());
}
inline std::string generate(std::string const*, random_generator g)
inline std::string generate(std::string const*)
{
using namespace std;
@@ -60,30 +53,17 @@ namespace test
std::string result;
if (g == limited_range) {
std::size_t length = test::random_value(2) + 2;
char const* strings[] = { "'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J" };
for (std::size_t i = 0; i < length; ++i) {
result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
}
}
else {
std::size_t length = test::random_value(10) + 1;
for (std::size_t i = 0; i < length; ++i) {
result += generate(char_ptr, g);
}
}
int length = rand() % 10;
for(int i = 0; i < length; ++i)
result += generate(char_ptr);
return result;
}
float generate(float const*, random_generator g)
float generate(float const*)
{
using namespace std;
int x = 0;
int value = generate(&x, g);
return (float) value / (float) RAND_MAX;
return (float) rand() / (float) RAND_MAX;
}
}
-20
View File
@@ -38,26 +38,6 @@ namespace test
{
return get_key_impl<Container>::get_key(x);
}
// test::next
//
// Increments an iterator by 1 or a given value.
// Like boost::next, but simpler and slower.
template <typename Iterator>
Iterator next(Iterator it)
{
return ++it;
}
template <typename Iterator, typename IntType>
Iterator next(Iterator it, IntType x)
{
for(; x > 0; --x) {
++it;
}
return it;
}
}
#endif
+3 -3
View File
@@ -7,8 +7,8 @@
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <iterator>
namespace test
{
@@ -28,7 +28,7 @@ namespace test
template <class Iterator>
struct input_iterator_adaptor
: public std::iterator<
: public boost::iterator<
std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
@@ -72,7 +72,7 @@ namespace test
template <class Iterator>
struct copy_iterator_adaptor
: public std::iterator<
: public boost::iterator<
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
+2 -3
View File
@@ -91,7 +91,7 @@ namespace test
// Check the load factor.
float load_factor = size == 0 ? 0 :
float load_factor =
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
using namespace std;
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
@@ -105,8 +105,7 @@ namespace test
i = 0; i < x1.bucket_count(); ++i)
{
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
begin2 = x1.begin(i), end2 = x1.end(i);
begin2 != end2; ++begin2)
begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
{
++bucket_size;
}
+3 -3
View File
@@ -11,8 +11,8 @@
#if !defined(UNORDERED_TEST_LIST_HEADER)
#define UNORDERED_TEST_LIST_HEADER
#include <boost/iterator.hpp>
#include <boost/limits.hpp>
#include <iterator>
#include <functional>
namespace test
@@ -83,7 +83,7 @@ namespace test
template <typename T>
class list_iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag, T,
int, T*, T&>
{
@@ -109,7 +109,7 @@ namespace test
template <typename T>
class list_const_iterator
: public std::iterator<
: public boost::iterator<
std::forward_iterator_tag, T,
int, T const*, T const&>
{
+15 -5
View File
@@ -8,6 +8,8 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test
{
@@ -20,11 +22,19 @@ namespace test
template <class Container>
struct has_unique_keys
{
static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&);
static long flip(std::pair<BOOST_DEDUCED_TYPENAME Container::iterator, bool> const&);
BOOST_STATIC_CONSTANT(bool, value = sizeof(long) == sizeof(
flip(((Container*) 0)->insert(*(BOOST_DEDUCED_TYPENAME Container::value_type*) 0))
));
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class V, class H, class P, class A>
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class K, class M, class H, class P, class A>
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
+17 -18
View File
@@ -14,6 +14,11 @@
namespace test
{
typedef enum {
default_generator,
generate_collisions
} random_generator;
template <class X>
struct unordered_generator_set
{
@@ -27,15 +32,16 @@ namespace test
template <class T>
void fill(T& x, std::size_t len) {
value_type* value_ptr = 0;
int* int_ptr = 0;
len += x.size();
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr, type_);
value_type value = generate(value_ptr);
std::size_t count = type_ == generate_collisions ?
random_value(5) + 1 : 1;
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(std::size_t j = 0; j < count; ++j) {
for(int i = 0; i < count; ++i) {
x.push_back(value);
}
}
@@ -57,16 +63,17 @@ namespace test
void fill(T& x, std::size_t len) {
key_type* key_ptr = 0;
mapped_type* mapped_ptr = 0;
int* int_ptr = 0;
for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr, type_);
key_type key = generate(key_ptr);
std::size_t count = type_ == generate_collisions ?
random_value(5) + 1 : 1;
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(std::size_t j = 0; j < count; ++j) {
for(int i = 0; i < count; ++i) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr, type_)));
key, generate(mapped_ptr)));
}
}
}
@@ -96,16 +103,8 @@ namespace test
struct random_values
: public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
{
random_values() {}
explicit random_values(std::size_t count, test::random_generator const& generator =
random_values(int count, test::random_generator const& generator =
test::default_generator)
{
fill(count, generator);
}
void fill(std::size_t count, test::random_generator const& generator =
test::default_generator)
{
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
+1 -20
View File
@@ -24,11 +24,7 @@
void BOOST_PP_CAT(x, _type)::run() \
#define RUN_TESTS() int main(int, char**) \
{ \
::test::write_compiler_info(); \
::test::test_list::run_tests(); \
return boost::report_errors(); \
}
{ ::test::test_list::run_tests(); return boost::report_errors(); } \
namespace test {
struct registered_test_base {
@@ -70,21 +66,6 @@ namespace test {
}
}
}
inline void write_compiler_info() {
#if defined(BOOST_GCC_CXX11)
char const* cpp11 = "true";
#else
char const* cpp11 = "false";
#endif
std::cout
<< "Compiler: " << BOOST_COMPILER << "\n"
<< "Library: " << BOOST_STDLIB << "\n"
<< "C++11: " << cpp11 << "\n"
<< "\n"
<< std::flush;
}
}
#include <boost/preprocessor/seq/for_each_product.hpp>
+18 -25
View File
@@ -13,6 +13,7 @@
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/type_traits/is_same.hpp>
#include "../objects/fwd.hpp"
#include "./metafunctions.hpp"
#include "./helpers.hpp"
@@ -59,46 +60,38 @@ namespace test
values2.begin(), test::equivalent));
}
template <typename X,
bool is_set = test::is_set<X>::value,
bool has_unique_keys = test::has_unique_keys<X>::value>
template <typename X>
struct ordered_base;
template <typename X>
struct ordered_base<X, true, true>
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_set<V, H, P, A> >
{
typedef std::set<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
typedef std::set<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <typename X>
struct ordered_base<X, true, false>
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <typename X>
struct ordered_base<X, false, true>
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
{
typedef std::map<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
typedef std::map<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <typename X>
struct ordered_base<X, false, false>
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
{
typedef std::multimap<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
typedef std::multimap<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
+1 -5
View File
@@ -148,7 +148,7 @@ namespace test
return ptr;
}
pointer allocate(size_type n, void const*)
pointer allocate(size_type n, void const* u)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
@@ -201,11 +201,9 @@ namespace test
public move_allocator_base<Flags>,
Flags
{
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
#endif
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
@@ -253,11 +251,9 @@ namespace test
return tmp;
}
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
#endif
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
+10 -15
View File
@@ -23,7 +23,7 @@ namespace exception
class hash;
class equal_to;
template <class T> class allocator;
object generate(object const*, random_generator);
object generate(object const*);
struct true_type
{
@@ -101,9 +101,9 @@ namespace exception
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend object generate(object const*, random_generator g) {
friend object generate(object const*) {
int* x = 0;
return object(::test::generate(x, g), ::test::generate(x, g));
return object(::test::generate(x), ::test::generate(x));
}
friend std::ostream& operator<<(std::ostream& out, object const& o)
@@ -146,18 +146,14 @@ namespace exception
UNORDERED_EPOINT("Mock hash function.");
}
int result;
switch(tag_) {
case 1:
result = x.tag1_;
break;
return x.tag1_;
case 2:
result = x.tag2_;
break;
return x.tag2_;
default:
result = x.tag1_ + x.tag2_;
return x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
friend bool operator==(hash const& x1, hash const& x2) {
@@ -318,7 +314,7 @@ namespace exception
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const*)
pointer allocate(size_type n, void const* u)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator::allocate(size_type, const_pointer)) {
@@ -498,7 +494,7 @@ namespace exception
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const*)
pointer allocate(size_type n, void const* u)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
@@ -592,9 +588,8 @@ namespace exception
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace test
{
test::exception::object generate(test::exception::object const* x,
random_generator g) {
return test::exception::generate(x, g);
test::exception::object generate(test::exception::object const* x) {
return test::exception::generate(x);
}
}
#endif
+21 -50
View File
@@ -19,12 +19,6 @@
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test
{
namespace minimal
@@ -35,9 +29,7 @@ namespace minimal
class default_assignable;
class assignable;
struct ampersand_operator_used {
ampersand_operator_used() { BOOST_TEST(false); }
};
struct ampersand_operator_used {};
template <class T> class hash;
template <class T> class equal_to;
@@ -56,7 +48,6 @@ namespace minimal
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
@@ -68,7 +59,6 @@ namespace minimal
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
@@ -88,15 +78,11 @@ namespace minimal
{
}
void dummy_member() const {}
private:
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
bool operator==(
@@ -135,12 +121,9 @@ namespace minimal
{
}
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
private:
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
class assignable
@@ -150,13 +133,11 @@ namespace minimal
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
void dummy_member() const {}
private:
assignable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
// TODO: This messes up a concept check in the tests.
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
struct movable_init {};
@@ -172,7 +153,6 @@ namespace minimal
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)
@@ -184,7 +164,6 @@ namespace minimal
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
private:
movable2() {}
movable2(movable2 const&);
@@ -205,10 +184,8 @@ namespace minimal
~hash() {}
std::size_t operator()(T const&) const { return 0; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -222,10 +199,8 @@ namespace minimal
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T> class ptr;
@@ -313,10 +288,9 @@ namespace minimal
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -351,10 +325,9 @@ namespace minimal
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -386,7 +359,7 @@ namespace minimal
}
template <class Y>
pointer allocate(size_type n, const_ptr<Y>)
pointer allocate(size_type n, const_ptr<Y> u)
{
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
@@ -414,10 +387,8 @@ namespace minimal
#else
private: allocator& operator=(allocator const&);
#endif
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -447,7 +418,7 @@ namespace minimal
{
public:
typedef T value_type;
//template <class U> struct rebind { typedef cxx11_allocator<U> other; };
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
@@ -462,7 +433,7 @@ namespace minimal
}
template <class Y>
T* allocate(std::size_t n, const_ptr<Y>) {
T* allocate(std::size_t n, const_ptr<Y> u) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
+18 -37
View File
@@ -25,9 +25,9 @@ namespace test
class equal_to;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*, random_generator);
movable generate(movable const*, random_generator);
implicitly_convertible generate(implicitly_convertible const*, random_generator);
object generate(object const*);
movable generate(movable const*);
implicitly_convertible generate(implicitly_convertible const*);
inline void ignore_variable(void const*) {}
@@ -58,9 +58,9 @@ namespace test
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend object generate(object const*, random_generator g) {
friend object generate(object const*) {
int* x = 0;
return object(generate(x, g), generate(x, g));
return object(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, object const& o)
@@ -133,9 +133,9 @@ namespace test
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend movable generate(movable const*, random_generator g) {
friend movable generate(movable const*) {
int* x = 0;
return movable(generate(x, g), generate(x, g));
return movable(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, movable const& o)
@@ -163,9 +163,9 @@ namespace test
return movable(tag1_, tag2_);
}
friend implicitly_convertible generate(implicitly_convertible const*, random_generator g) {
friend implicitly_convertible generate(implicitly_convertible const*) {
int* x = 0;
return implicitly_convertible(generate(x, g), generate(x, g));
return implicitly_convertible(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, implicitly_convertible const& o)
@@ -182,48 +182,29 @@ namespace test
explicit hash(int t = 0) : type_(t) {}
std::size_t operator()(object const& x) const {
int result;
switch(type_) {
case 1:
result = x.tag1_;
break;
return x.tag1_;
case 2:
result = x.tag2_;
break;
return x.tag2_;
default:
result = x.tag1_ + x.tag2_;
return x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(movable const& x) const {
int result;
switch(type_) {
case 1:
result = x.tag1_;
break;
return x.tag1_;
case 2:
result = x.tag2_;
break;
return x.tag2_;
default:
result = x.tag1_ + x.tag2_;
return x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(int x) const {
int result;
switch(type_) {
case 1:
result = x;
break;
case 2:
result = x * 7;
break;
default:
result = x * 256;
}
return static_cast<std::size_t>(result);
return x;
}
friend bool operator==(hash const& x1, hash const& x2) {
@@ -366,7 +347,7 @@ namespace test
return ptr;
}
T* allocate(std::size_t n, void const*)
T* allocate(std::size_t n, void const* u)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
@@ -592,7 +573,7 @@ namespace test
return p;
}
pointer allocate(size_type n, void const*)
pointer allocate(size_type n, void const* u)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
+64
View File
@@ -0,0 +1,64 @@
# Copyright 2006-2008 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
;
test-suite unordered
:
[ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ]
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
[ run copy_tests.cpp ]
[ run move_tests.cpp ]
[ run assign_tests.cpp ]
[ run insert_tests.cpp ]
[ run insert_stable_tests.cpp ]
[ run unnecessary_copy_tests.cpp ]
[ run erase_tests.cpp ]
[ run erase_equiv_tests.cpp ]
[ run find_tests.cpp ]
[ run at_tests.cpp ]
[ run bucket_tests.cpp ]
[ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ]
[ run equality_tests.cpp ]
[ run swap_tests.cpp ]
[ run compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
+4 -4
View File
@@ -22,9 +22,9 @@
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
T* allocate(std::size_t n, void const*) \
T* allocate(std::size_t n, void const* u) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
void deallocate(T* p, std::size_t) { ::operator delete((void*) p); } \
void deallocate(T* p, std::size_t n) { ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
@@ -44,9 +44,9 @@
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ return pointer(::operator new(n * sizeof(T))); } \
pointer allocate(std::size_t n, void const*) \
pointer allocate(std::size_t n, void const* u) \
{ return pointer(::operator new(n * sizeof(T))); } \
void deallocate(pointer p, std::size_t) \
void deallocate(pointer p, std::size_t n) \
{ ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
+3 -18
View File
@@ -77,21 +77,7 @@ void assign_tests2(T*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
std::cerr<<"assign_tests2.0 - empty container\n";
{
test::check_instances check_;
T x1(0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, x2);
}
std::cerr<<"assign_tests2.1\n";
{
test::check_instances check_;
@@ -250,7 +236,6 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T>
bool is_propagate(T*)
@@ -271,7 +256,7 @@ UNORDERED_TEST(assign_tests1, (
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(assign_tests2, (
@@ -279,7 +264,7 @@ UNORDERED_TEST(assign_tests2, (
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+1
View File
@@ -16,6 +16,7 @@ UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
+4 -7
View File
@@ -34,10 +34,8 @@ void tests(X*, test::random_generator generator)
X x(v.begin(), v.end());
BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
if (!(x.bucket_count() <= x.max_bucket_count())) {
std::cerr<<x.bucket_count()<<"<="<<x.max_bucket_count()<<"\n";
}
BOOST_TEST(x.bucket_count() < x.max_bucket_count());
std::cerr<<x.bucket_count()<<"<"<<x.max_bucket_count()<<"\n";
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = v.begin(), end = v.end(); it != end; ++it)
@@ -45,7 +43,7 @@ void tests(X*, test::random_generator generator)
size_type bucket = x.bucket(test::get_key<X>(*it));
BOOST_TEST(bucket < x.bucket_count());
if(bucket < x.bucket_count()) {
if(bucket < x.max_bucket_count()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while(lit != lend
@@ -89,11 +87,10 @@ boost::unordered_multimap<test::object, test::object,
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))
((default_generator)(generate_collisions))
)
}
+4 -6
View File
@@ -24,15 +24,15 @@ template class boost::unordered_map<
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_multimap<
int const,
int const,
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_map<
test::minimal::assignable const,
test::minimal::default_assignable const,
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
@@ -202,7 +202,6 @@ UNORDERED_AUTO_TEST(test2)
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,
@@ -227,7 +226,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
RUN_TESTS()
+2 -4
View File
@@ -23,13 +23,13 @@ template class boost::unordered_set<
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_multiset<
int const,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_set<
test::minimal::assignable const,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
@@ -183,7 +183,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
@@ -196,7 +195,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(movable1_tests)
+5 -186
View File
@@ -89,9 +89,8 @@ void container_test(X& r, T const&)
// size_type can represent any non-negative value type of difference_type
// I'm not sure about either of these tests...
size_type max_diff = static_cast<size_type>(
(std::numeric_limits<difference_type>::max)());
difference_type converted_diff(static_cast<difference_type>(max_diff));
size_type max_diff((std::numeric_limits<difference_type>::max)());
difference_type converted_diff(max_diff);
BOOST_TEST((std::numeric_limits<difference_type>::max)()
== converted_diff);
@@ -101,18 +100,7 @@ void container_test(X& r, T const&)
static_cast<comparison_type>(
(std::numeric_limits<difference_type>::max)()));
// Constructors
// I don't test the runtime post-conditions here.
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
// It isn't specified in the container requirements that the no argument
// constructor is implicit, but it is defined that way in the concrete
// container specification.
X u_implicit = {};
sink(u_implicit);
#endif
X u;
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
@@ -123,8 +111,6 @@ void container_test(X& r, T const&)
sink(X(a));
X u2(a);
X u3 = a;
X u4(rvalue(a_const));
X u5 = rvalue(a_const);
a.swap(b);
boost::swap(a, b);
@@ -134,25 +120,12 @@ void container_test(X& r, T const&)
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
allocator_type m = a.get_allocator();
sink(X(m));
X c(m);
sink(X(a_const, m));
X c2(a_const, m);
sink(X(rvalue(a_const), m));
X c3(rvalue(a_const), m);
// Avoid unused variable warnings:
sink(u);
sink(u2);
sink(u3);
sink(u4);
sink(u5);
sink(c);
sink(c2);
sink(c3);
}
template <class X>
@@ -175,7 +148,6 @@ void unordered_destructible_test(X&)
X* ptr = new X();
X& a1 = *ptr;
(&a1)->~X();
::operator delete((void*)(&a1));
X a,b;
X const a_const;
@@ -208,28 +180,6 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
}
template <class X, class Key, class T>
@@ -241,30 +191,6 @@ void unordered_map_test(X& r, Key const& k, T const& v)
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
// Calling functions
r.insert(std::pair<Key const, T>(k, v));
Key k_lvalue(k);
@@ -273,9 +199,6 @@ void unordered_map_test(X& r, Key const& k, T const& v)
r.emplace(k, v);
r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v));
r.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
}
template <class X>
@@ -384,7 +307,6 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
@@ -417,13 +339,8 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
X a;
allocator_type m = a.get_allocator();
// Constructors
X(10, hf, eq);
X a1(10, hf, eq);
X a(10, hf, eq);
X(10, hf);
X a2(10, hf);
X(10);
@@ -431,15 +348,6 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
X();
X a4;
X(10, hf, eq, m);
X a1a(10, hf, eq, m);
X(10, hf, m);
X a2a(10, hf, m);
X(10, m);
X a3a(10, m);
(X(m));
X a4a(m);
test::check_return_type<size_type>::equals(a.erase(k));
const_iterator q1 = a.cbegin(), q2 = a.cend();
@@ -482,14 +390,9 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
// Avoid unused variable warnings:
sink(a);
sink(a1);
sink(a2);
sink(a3);
sink(a4);
sink(a1a);
sink(a2a);
sink(a3a);
sink(a4a);
}
template <class X, class Key, class T, class Hash, class Pred>
@@ -499,17 +402,14 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
X a;
allocator_type m = a.get_allocator();
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
// Constructors
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
X a6(i, j, 10, hf);
@@ -518,55 +418,17 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
X(i, j);
X a8(i, j);
X(i, j, 10, hf, eq, m);
X a5a(i, j, 10, hf, eq, m);
X(i, j, 10, hf, m);
X a6a(i, j, 10, hf, m);
X(i, j, 10, m);
X a7a(i, j, 10, m);
// Not specified for some reason (maybe ambiguity with another constructor?)
//X(i, j, m);
//X a8a(i, j, m);
//sink(a8a);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::size_t min_buckets = 10;
X({t});
X({t}, min_buckets);
X({t}, min_buckets, hf);
X({t}, min_buckets, hf, eq);
//X({t}, m);
X({t}, min_buckets, m);
X({t}, min_buckets, hf, m);
X({t}, min_buckets, hf, eq, m);
#endif
X const b;
sink(X(b));
X a9(b);
a = b;
sink(X(b, m));
X a9a(b, m);
const_iterator q = a.cbegin();
test::check_return_type<iterator>::equals(a.insert(q, t));
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
a.insert(i, j);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<T> list = {t};
a.insert(list);
a.insert({t,t,t});
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
a.insert({});
a.insert({t});
a.insert({t,t});
#endif
#endif
X a10;
a10.insert(t);
@@ -581,10 +443,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
sink(a7);
sink(a8);
sink(a9);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a9a);
}
template <class X, class Key, class T, class Hash, class Pred>
@@ -594,7 +452,6 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>());
@@ -603,14 +460,9 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
x2 = boost::move(x1);
#endif
X a;
allocator_type m = a.get_allocator();
test::minimal::constructor_param* i = 0;
test::minimal::constructor_param* j = 0;
// Constructors
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
@@ -620,17 +472,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
X(i, j);
X a8(i, j);
X(i, j, 10, hf, eq, m);
X a5a(i, j, 10, hf, eq, m);
X(i, j, 10, hf, m);
X a6a(i, j, 10, hf, m);
X(i, j, 10, m);
X a7a(i, j, 10, m);
// Not specified for some reason (maybe ambiguity with another constructor?)
//X(i, j, m);
//X a8a(i, j, m);
//sink(a8a);
X a;
const_iterator q = a.cbegin();
@@ -664,28 +506,5 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
sink(a6);
sink(a7);
sink(a8);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a10);
}
template <class X, class T>
void unordered_set_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->dummy_member();
x1.cbegin()->dummy_member();
}
template <class X, class T>
void unordered_map_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->first.dummy_member();
x1.cbegin()->first.dummy_member();
x1.begin()->second.dummy_member();
x1.cbegin()->second.dummy_member();
}
+3 -4
View File
@@ -418,21 +418,20 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(constructor_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+2 -3
View File
@@ -198,14 +198,13 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(copy_construct_tests1, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(copy_construct_tests2, (
@@ -213,7 +212,7 @@ UNORDERED_TEST(copy_construct_tests2, (
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
-436
View File
@@ -1,436 +0,0 @@
//
// Copyright 2016 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/functional/hash/hash.hpp>
#include "../helpers/test.hpp"
#include "../helpers/count.hpp"
#include <string>
// Test that various emplace methods work with different numbers of
// arguments.
namespace emplace_tests {
// Constructible with 2 to 10 arguments
struct emplace_value : private test::counted_object {
typedef int A0;
typedef std::string A1;
typedef char A2;
typedef int A3;
typedef int A4;
typedef int A5;
typedef int A6;
typedef int A7;
typedef int A8;
typedef int A9;
int arg_count;
A0 a0;
A1 a1;
A2 a2;
A3 a3;
A4 a4;
A5 a5;
A6 a6;
A7 a7;
A8 a8;
A9 a9;
emplace_value(
A0 const& b0, A1 const& b1) :
arg_count(2),
a0(b0), a1(b1) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2) :
arg_count(3),
a0(b0), a1(b1), a2(b2) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3) :
arg_count(4),
a0(b0), a1(b1), a2(b2), a3(b3) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4) :
arg_count(5),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5) :
arg_count(6),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
a5(b5) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6) :
arg_count(7),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
a5(b5), a6(b6) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7) :
arg_count(8),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
a5(b5), a6(b6), a7(b7) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7,
A8 const& b8) :
arg_count(9),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
a5(b5), a6(b6), a7(b7), a8(b8) {}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7,
A8 const& b8, A9 const& b9) :
arg_count(10),
a0(b0), a1(b1), a2(b2), a3(b3), a4(b4),
a5(b5), a6(b6), a7(b7), a8(b8), a9(b9) {}
friend std::size_t hash_value(emplace_value const& x) {
std::size_t r1 = 23894278u;
if (x.arg_count >= 1) boost::hash_combine(r1, x.a0);
if (x.arg_count >= 2) boost::hash_combine(r1, x.a1);
if (x.arg_count >= 3) boost::hash_combine(r1, x.a2);
if (x.arg_count >= 4) boost::hash_combine(r1, x.a3);
if (x.arg_count >= 5) boost::hash_combine(r1, x.a4);
if (x.arg_count >= 6) boost::hash_combine(r1, x.a5);
if (x.arg_count >= 7) boost::hash_combine(r1, x.a6);
if (x.arg_count >= 8) boost::hash_combine(r1, x.a7);
if (x.arg_count >= 9) boost::hash_combine(r1, x.a8);
if (x.arg_count >= 10) boost::hash_combine(r1, x.a9);
return r1;
}
friend bool operator==(emplace_value const& x, emplace_value const& y) {
if (x.arg_count != y.arg_count) { return false; }
if (x.arg_count >= 1 && x.a0 != y.a0) { return false; }
if (x.arg_count >= 2 && x.a1 != y.a1) { return false; }
if (x.arg_count >= 3 && x.a2 != y.a2) { return false; }
if (x.arg_count >= 4 && x.a3 != y.a3) { return false; }
if (x.arg_count >= 5 && x.a4 != y.a4) { return false; }
if (x.arg_count >= 6 && x.a5 != y.a5) { return false; }
if (x.arg_count >= 7 && x.a6 != y.a6) { return false; }
if (x.arg_count >= 8 && x.a7 != y.a7) { return false; }
if (x.arg_count >= 9 && x.a8 != y.a8) { return false; }
if (x.arg_count >= 10 && x.a9 != y.a9) { return false; }
return true;
}
private:
emplace_value();
emplace_value(emplace_value const&);
};
UNORDERED_AUTO_TEST(emplace_set) {
test::check_instances check_;
typedef boost::unordered_set<emplace_value,
boost::hash<emplace_value> > container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
iterator i1;
return_type r1,r2;
// 2 args
emplace_value v1(10, "x");
r1 = x.emplace(10, std::string("x"));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(*r1.first == v1);
BOOST_TEST(r1.first == x.find(v1));
BOOST_TEST_EQ(check_.instances(), 2);
BOOST_TEST_EQ(check_.constructions(), 2);
// 3 args
emplace_value v2(3, "foo", 'a');
r1 = x.emplace(3, "foo", 'a');
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second);
BOOST_TEST(*r1.first == v2);
BOOST_TEST(r1.first == x.find(v2));
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
// 7 args with hint + duplicate
emplace_value v3(25, "something", 'z', 4, 5, 6, 7);
i1 = x.emplace_hint(r1.first, 25, "something", 'z', 4, 5, 6, 7);
BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(*i1 == v3);
BOOST_TEST(i1 == x.find(v3));
BOOST_TEST_EQ(check_.instances(), 6);
BOOST_TEST_EQ(check_.constructions(), 6);
r2 = x.emplace(25, "something", 'z', 4, 5, 6, 7);
BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(!r2.second);
BOOST_TEST(i1 == r2.first);
// The container has to construct an object in order to check
// whether it can emplace, so there's an extra cosntruction
// here.
BOOST_TEST_EQ(check_.instances(), 6);
BOOST_TEST_EQ(check_.constructions(), 7);
// 10 args + hint duplicate
std::string s1;
emplace_value v4(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10);
r1 = x.emplace(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10);
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST(r1.second);
BOOST_TEST(*r1.first == v4);
BOOST_TEST(r1.first == x.find(v4));
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 9);
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r1.first ==
x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 12);
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST(x.count(v1) == 1);
BOOST_TEST(x.count(v2) == 1);
BOOST_TEST(x.count(v3) == 1);
BOOST_TEST(x.count(v4) == 1);
}
UNORDERED_AUTO_TEST(emplace_multiset) {
test::check_instances check_;
typedef boost::unordered_multiset<emplace_value,
boost::hash<emplace_value> > container;
typedef container::iterator iterator;
container x(10);
iterator i1, i2;
// 2 args.
emplace_value v1(10, "x");
i1 = x.emplace(10, std::string("x"));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(i1 == x.find(v1));
BOOST_TEST_EQ(check_.instances(), 2);
BOOST_TEST_EQ(check_.constructions(), 2);
// 4 args + duplicate
emplace_value v2(4, "foo", 'a', 15);
i1 = x.emplace(4, "foo", 'a', 15);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(i1 == x.find(v2));
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
i2 = x.emplace(4, "foo", 'a', 15);
BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(i1 != i2);
BOOST_TEST(*i1 == *i2);
BOOST_TEST(x.count(*i1) == 2);
BOOST_TEST_EQ(check_.instances(), 5);
BOOST_TEST_EQ(check_.constructions(), 5);
// 7 args + duplicate using hint.
emplace_value v3(7, "", 'z', 4, 5, 6, 7);
i1 = x.emplace(7, "", 'z', 4, 5, 6, 7);
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST_EQ(i1->a2, 'z');
BOOST_TEST(x.count(*i1) == 1);
BOOST_TEST(i1 == x.find(v3));
BOOST_TEST_EQ(check_.instances(), 7);
BOOST_TEST_EQ(check_.constructions(), 7);
i2 = x.emplace_hint(i1, 7, "", 'z', 4, 5, 6, 7);
BOOST_TEST_EQ(x.size(), 5u);
BOOST_TEST(*i1 == *i2);
BOOST_TEST(i1 != i2);
BOOST_TEST(x.count(*i1) == 2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 8);
// 10 args with bad hint + duplicate
emplace_value v4(10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
i1 = x.emplace_hint(i2, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
BOOST_TEST_EQ(x.size(), 6u);
BOOST_TEST_EQ(i1->arg_count, 10);
BOOST_TEST(i1 == x.find(v4));
BOOST_TEST_EQ(check_.instances(), 10);
BOOST_TEST_EQ(check_.constructions(), 10);
i2 = x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10);
BOOST_TEST_EQ(x.size(), 7u);
BOOST_TEST(*i1 == *i2);
BOOST_TEST(i1 != i2);
BOOST_TEST(x.count(*i1) == 2);
BOOST_TEST_EQ(check_.instances(), 11);
BOOST_TEST_EQ(check_.constructions(), 11);
BOOST_TEST_EQ(x.count(v1), 1u);
BOOST_TEST_EQ(x.count(v2), 2u);
BOOST_TEST_EQ(x.count(v3), 2u);
}
UNORDERED_AUTO_TEST(emplace_map) {
test::check_instances check_;
typedef boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> > container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2;
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
r2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(!r2.second);
BOOST_TEST(r1.first == r2.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
// constructions could possibly be 5 if the implementation only
// constructed the key.
BOOST_TEST_EQ(check_.constructions(), 6);
// 9/3 args + duplicates with hints, different mapped value.
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first.arg_count == 9);
BOOST_TEST(r1.first->second.arg_count == 3);
BOOST_TEST(x.find(k2) == r1.first);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST(r1.first == x.emplace_hint(r1.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first == x.emplace_hint(x.end(),
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16);
}
UNORDERED_AUTO_TEST(emplace_multimap) {
test::check_instances check_;
typedef boost::unordered_multimap<emplace_value, emplace_value,
boost::hash<emplace_value> > container;
typedef container::iterator iterator;
container x(10);
iterator i1, i2, i3, i4;
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(x.find(k1) == i1);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8);
i2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(i1 != i2);
BOOST_TEST(i1->second == m1);
BOOST_TEST(i2->second == m1a);
BOOST_TEST_EQ(check_.instances(), 7);
BOOST_TEST_EQ(check_.constructions(), 7);
// 9/3 args + duplicates with hints, different mapped value.
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(i1->first.arg_count == 9);
BOOST_TEST(i1->second.arg_count == 3);
BOOST_TEST_EQ(check_.instances(), 11);
BOOST_TEST_EQ(check_.constructions(), 11);
emplace_value m2a(15, "jkjk");
i2 = x.emplace_hint(i2,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk"));
emplace_value m2b(275, "xxx", 'm', 6);
i3 = x.emplace_hint(i1,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6));
emplace_value m2c(-10, "blah blah", '\0');
i4 = x.emplace_hint(x.end(),
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0'));
BOOST_TEST_EQ(x.size(), 6u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 20);
BOOST_TEST_EQ(check_.constructions(), 20);
}
}
RUN_TESTS()
+2 -4
View File
@@ -25,11 +25,9 @@ namespace equality_tests
return x % 1000 == y % 1000;
}
std::size_t operator()(int x) const
int operator()(int x) const
{
return alt_hash_ ?
static_cast<std::size_t>(x % 250) :
static_cast<std::size_t>((x + 5) % 250);
return alt_hash_ ? x % 250 : (x + 5) % 250;
}
};
+9 -10
View File
@@ -13,10 +13,10 @@
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
#include <set>
#include <iostream>
#include <iterator>
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
@@ -43,19 +43,19 @@ void write_container(Container const& x)
// Make everything collide - for testing erase in a single bucket.
struct collision_hash
{
std::size_t operator()(int) const { return 0; }
int operator()(int) const { return 0; }
};
// For testing erase in 2 buckets.
struct collision2_hash
{
std::size_t operator()(int x) const { return static_cast<std::size_t>(x & 1); }
int operator()(int x) const { return x & 1; }
};
// For testing erase in lots of buckets.
struct collision3_hash
{
std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
int operator()(int x) const { return x; }
};
typedef boost::unordered_multimap<int, int,
@@ -111,8 +111,8 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_map x(init.begin(), init.end());
int value = test::next(x.begin())->second;
x.erase(x.begin(), test::next(x.begin()));
int value = boost::next(x.begin())->second;
x.erase(x.begin(), boost::next(x.begin()));
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
test::check_equivalent_keys(x);
@@ -121,7 +121,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_map x(init.begin(), init.end());
int value = x.begin()->second;
x.erase(test::next(x.begin()), x.end());
x.erase(boost::next(x.begin()), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
test::check_equivalent_keys(x);
@@ -144,9 +144,8 @@ template <class Container>
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
{
collide_list l(x.begin(), x.end());
l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
x.erase(boost::next(x.begin(), start), boost::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
+18 -66
View File
@@ -9,15 +9,15 @@
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include <vector>
#include <iostream>
#include <cstdlib>
namespace erase_tests
{
@@ -27,9 +27,6 @@ test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
std::cerr<<"Erase by key.\n";
{
test::check_instances check_;
@@ -63,7 +60,8 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
iterator pos = x.erase(x.begin());
BOOST_DEDUCED_TYPENAME Container::iterator
pos = x.erase(x.begin());
--size;
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
@@ -83,29 +81,26 @@ void erase_tests1(Container*, test::random_generator generator)
int iterations = 0;
while(size > 0 && !x.empty())
{
std::size_t index = test::random_value(x.size());
c_iterator prev, pos, next;
using namespace std;
int index = rand() % (int) x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if(index == 0) {
prev = pos = x.begin();
}
else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
next = test::next(pos);
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
BOOST_TEST(next == x.erase(pos));
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == test::next(prev));
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
std::cerr << count << " => " << x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
@@ -139,45 +134,6 @@ void erase_tests1(Container*, test::random_generator generator)
test::check_equivalent_keys(x);
}
std::cerr<<"erase(random ranges).\n";
{
test::check_instances check_;
Container x;
for (int i = 0; i < 100; ++i) {
test::random_values<Container> v(1000, generator);
x.insert(v.begin(), v.end());
// Note that erase only invalidates the erased iterators.
std::vector<c_iterator> iterators;
for(c_iterator it = x.cbegin(); it != x.cend(); ++it) {
iterators.push_back(it);
}
iterators.push_back(x.cend());
while(iterators.size() > 1) {
std::size_t start = test::random_value(iterators.size());
std::size_t length = test::random_value(iterators.size() - start);
x.erase(iterators[start], iterators[start + length]);
iterators.erase(
test::next(iterators.begin(), start),
test::next(iterators.begin(), start + length));
BOOST_TEST(x.size() == iterators.size() - 1);
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator
i2 = iterators.begin();
for(c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
}
std::cerr<<"quick_erase(begin()).\n";
{
test::check_instances check_;
@@ -210,29 +166,26 @@ void erase_tests1(Container*, test::random_generator generator)
int iterations = 0;
while(size > 0 && !x.empty())
{
std::size_t index = test::random_value(x.size());
using namespace std;
int index = rand() % (int) x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if(index == 0) {
prev = pos = x.begin();
}
else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
next = test::next(pos);
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
x.quick_erase(pos);
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == test::next(prev));
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
std::cerr << count << " => " << x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
@@ -269,11 +222,10 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(erase_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
+6 -8
View File
@@ -37,15 +37,13 @@ void find_tests1(X*, test::random_generator generator)
tracker.begin(); it1 != tracker.end(); ++it1)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
iterator pos = x.find(key);
BOOST_DEDUCED_TYPENAME X::const_iterator
const_pos = x_const.find(key);
iterator pos = x.find(key);
BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(pos != x.end());
BOOST_TEST(pos != x.end() &&
x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(x.count(key) == tracker.count(key));
@@ -119,6 +117,7 @@ struct compatible_predicate
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator;
test::random_values<X> v(500, generator);
@@ -155,15 +154,14 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(find_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
-118
View File
@@ -1,118 +0,0 @@
// Copyright 2016 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../helpers/invariants.hpp"
#include <map>
#include <set>
#include <iostream>
namespace insert_hint
{
UNORDERED_AUTO_TEST(insert_hint_empty) {
typedef boost::unordered_multiset<int> container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(insert_hint_empty2) {
typedef boost::unordered_multimap<std::string, int> container;
container x;
x.emplace_hint(x.cbegin(), "hello", 50);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count("hello"), 1u);
BOOST_TEST_EQ(x.find("hello")->second, 50);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(insert_hint_single) {
typedef boost::unordered_multiset<std::string> container;
container x;
x.insert("equal");
x.insert(x.cbegin(), "equal");
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(x.count("equal"), 2u);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(insert_hint_single2) {
typedef boost::unordered_multimap<int, std::string> container;
container x;
x.emplace(10, "one");
x.emplace_hint(x.cbegin(), 10, "two");
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(x.count(10), 2u);
container::iterator it = x.find(10);
std::string v0 = (it++)->second;
std::string v1 = (it++)->second;
BOOST_TEST(v0 == "one" || v0 == "two");
BOOST_TEST(v1 == "one" || v1 == "two");
BOOST_TEST(v0 != v1);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(insert_hint_multiple) {
for (unsigned int size = 0; size < 10; ++size) {
for (unsigned int offset = 0; offset <= size; ++offset) {
typedef boost::unordered_multiset<std::string> container;
container x;
for (unsigned int i = 0; i < size; ++i) { x.insert("multiple"); }
BOOST_TEST_EQ(x.size(), size);
container::const_iterator position = x.cbegin();
for (unsigned int i = 0; i < offset; ++i) { ++position; }
x.insert(position, "multiple");
BOOST_TEST_EQ(x.size(), size + 1u);
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
test::check_equivalent_keys(x);
}
}
}
UNORDERED_AUTO_TEST(insert_hint_unique) {
typedef boost::unordered_set<int> container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(insert_hint_unique_single) {
typedef boost::unordered_set<int> container;
container x;
x.insert(10);
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x);
x.insert(x.cbegin(), 20);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(x.count(10), 1u);
BOOST_TEST_EQ(x.count(20), 1u);
test::check_equivalent_keys(x);
}
}
RUN_TESTS()
+4 -7
View File
@@ -49,8 +49,6 @@ UNORDERED_AUTO_TEST(stable_insert_test1) {
x.insert(insert_stable::member(1,2));
x.insert(insert_stable::member(1,3));
BOOST_TEST(x.count(insert_stable::member(1,4)) == 3);
boost::unordered_multiset<insert_stable::member>::const_iterator
it = x.begin(), end = x.end();
BOOST_TEST(it != end);
@@ -68,11 +66,10 @@ UNORDERED_AUTO_TEST(stable_insert_test2) {
boost::unordered_multimap<insert_stable::member, int>::const_iterator
iterator;
iterator it = x.emplace(insert_stable::member(1,1), 1);
it = x.emplace(insert_stable::member(1,2), 2);
it = x.emplace(insert_stable::member(1,3), 3);
BOOST_TEST(x.count(insert_stable::member(1,4)) == 3);
iterator it
= x.insert(x.end(), std::make_pair(insert_stable::member(1,1), 1));
it = x.insert(it, std::make_pair(insert_stable::member(1,2), 2));
it = x.insert(it, std::make_pair(insert_stable::member(1,3), 3));
it = x.begin();
iterator end = x.end();
+35 -124
View File
@@ -9,6 +9,7 @@
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
@@ -54,7 +55,7 @@ void unique_insert_tests1(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -87,7 +88,7 @@ void equivalent_insert_tests1(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -123,11 +124,10 @@ void insert_tests2(X*, test::random_generator generator)
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -153,11 +153,10 @@ void insert_tests2(X*, test::random_generator generator)
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -183,11 +182,10 @@ void insert_tests2(X*, test::random_generator generator)
BOOST_TEST(*pos == *r2);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -207,15 +205,14 @@ void insert_tests2(X*, test::random_generator generator)
old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
x.insert(it, test::next(it));
x.insert(it, boost::next(it));
tracker.insert(*it);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -295,42 +292,6 @@ void insert_tests2(X*, test::random_generator generator)
test::check_equivalent_keys(x);
}
std::cerr<<"insert various ranges.\n";
{
for (int i = 0; i < 100; ++i) {
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
it = v.begin(); it != v.end();)
{
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
next = it;
for (std::size_t j = test::random_value(20); j > 0; ++j) {
++next;
if (next == v.end()) { break; }
}
x.insert(it, next);
tracker.insert(it, next);
it = next;
tracker.compare(x); // Slow, but I can't see any other way.
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
}
}
template <class X>
@@ -362,11 +323,10 @@ void unique_emplace_tests1(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -393,17 +353,19 @@ void equivalent_emplace_tests1(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
template <class X>
void move_emplace_tests(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
X x;
@@ -423,18 +385,17 @@ void move_emplace_tests(X*, test::random_generator generator)
tracker.insert(*it);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
tracker.compare(x);
}
template <class X>
void default_emplace_tests(X*, test::random_generator)
{
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
std::cerr<<"emplace() tests.\n";
bool is_unique = test::has_unique_keys<X>::value;
@@ -443,17 +404,17 @@ void default_emplace_tests(X*, test::random_generator)
x.emplace();
BOOST_TEST(x.size() == 1);
x.emplace();
BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
BOOST_TEST(x.size() == is_unique ? 1: 2);
x.emplace();
BOOST_TEST(x.size() == (is_unique ? 1u : 3u));
BOOST_TEST(x.size() == is_unique ? 1: 3);
typename X::value_type y;
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 3u));
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 3);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
x.emplace(y);
BOOST_TEST(x.size() == (is_unique ? 1u : 4u));
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 4u));
BOOST_TEST(x.size() == is_unique ? 1: 4);
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 4);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
x.clear();
@@ -461,11 +422,10 @@ void default_emplace_tests(X*, test::random_generator)
x.emplace(y);
BOOST_TEST(x.size() == 1);
x.emplace(y);
BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
BOOST_TEST(x.size() == is_unique ? 1: 2);
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 2);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
#endif
}
template <class X>
@@ -488,11 +448,10 @@ void map_tests(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
@@ -562,77 +521,61 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_insert_tests1,
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(insert_tests2,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_emplace_tests1,
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
(test_multiset)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
(test_multiset)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_tests,
((test_map))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test1,
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
struct initialize_from_two_ints
{
int a, b;
friend std::size_t hash_value(initialize_from_two_ints const& x)
{
return static_cast<std::size_t>(x.a + x.b);
}
bool operator==(initialize_from_two_ints const& x) const
{
return a == x.a && b == x.b;
}
};
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
boost::unordered_set<int> set;
@@ -640,38 +583,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
boost::unordered_set<initialize_from_two_ints> set2;
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
set2.insert({{1, 2}});
#else
set2.insert({1, 2});
#endif
BOOST_TEST(set2.size() == 1);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) == set2.end());
set2.insert({{3,4},{5,6},{7,8}});
BOOST_TEST(set2.size() == 4);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
set2.insert({{2, 1}, {3,4}});
BOOST_TEST(set2.size() == 5);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
}
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
{
boost::unordered_multiset<std::string> multiset;
@@ -688,8 +601,6 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
BOOST_TEST_EQ(multiset.count("c"), 0u);
}
#endif
UNORDERED_AUTO_TEST(insert_initializer_list_map)
{
boost::unordered_map<std::string, std::string> map;
@@ -713,8 +624,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
struct overloaded_constructor
{
overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
: x1(x1_), x2(x2_), x3(x3_), x4(x4_) {}
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
: x1(x1), x2(x2), x3(x3), x4(x4) {}
int x1, x2, x3, x4;
+2 -3
View File
@@ -51,7 +51,7 @@ void insert_test(X*, float mlf, test::random_generator generator)
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
x.insert(*it);
if(static_cast<double>(old_size + 1) <= b * static_cast<double>(old_bucket_count))
if(static_cast<double>(old_size + 1) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
}
@@ -78,7 +78,6 @@ boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
@@ -86,7 +85,7 @@ UNORDERED_TEST(set_load_factor_tests,
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
+1 -1
View File
@@ -18,7 +18,7 @@ struct SimpleAllocator
{
}
template <class T> SimpleAllocator(const SimpleAllocator<T>&)
template <class T> SimpleAllocator(const SimpleAllocator<T>& other)
{
}
+4 -5
View File
@@ -369,7 +369,6 @@ boost::unordered_multimap<test::object, test::object,
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(move_construct_tests1, (
(test_map_std_alloc)
@@ -377,7 +376,7 @@ boost::unordered_multimap<test::object, test::object,
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_assign_tests1, (
(test_map_std_alloc)
@@ -385,21 +384,21 @@ boost::unordered_multimap<test::object, test::object,
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_construct_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_assign_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
-148
View File
@@ -1,148 +0,0 @@
// Copyright 2013 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
namespace noexcept_tests
{
// Test the noexcept is set correctly for the move constructor.
struct hash_possible_exception : boost::hash<int>
{
hash_possible_exception(hash_possible_exception const&) {}
};
struct equal_to_possible_exception : std::equal_to<int>
{
equal_to_possible_exception(equal_to_possible_exception const&) {}
};
// Test that the move constructor does actually move without throwing
// an exception when it claims to.
struct test_exception {};
bool throwing_test_exception = false;
void test_throw(char const* name) {
if (throwing_test_exception) {
std::cerr << "Throw exception in: " << name << std::endl;
throw test_exception();
}
}
class hash_nothrow_move : boost::hash<int>
{
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
typedef boost::hash<int> base;
public:
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
BOOST_NOEXCEPT {}
hash_nothrow_move() { test_throw("Constructor"); }
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
{ test_throw("Assign"); return *this; }
hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
{ test_throw("Move Assign"); return *this; }
std::size_t operator()(int x) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
};
class equal_to_nothrow_move : std::equal_to<int>
{
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
typedef std::equal_to<int> base;
public:
equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
BOOST_NOEXCEPT {}
equal_to_nothrow_move() { test_throw("Constructor"); }
equal_to_nothrow_move(equal_to_nothrow_move const&)
{ test_throw("Copy"); }
equal_to_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move))
{ test_throw("Assign"); return *this; }
equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move))
{ test_throw("Move Assign"); return *this; }
std::size_t operator()(int x, int y) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
};
bool have_is_nothrow_move = false;
UNORDERED_AUTO_TEST(check_is_nothrow_move)
{
BOOST_TEST(!boost::is_nothrow_move_constructible<hash_possible_exception>::value);
have_is_nothrow_move = boost::is_nothrow_move_constructible<hash_nothrow_move>::value;
// Copied from boost::is_nothrow_move_constructible implementation
// to make sure this does actually detect it when expected.
//
// The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT
// is defined (for some versions of Visual C++?) but detects 'throw()',
// not noexcept.
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
BOOST_TEST(have_is_nothrow_move);
#endif
}
UNORDERED_AUTO_TEST(test_noexcept)
{
if (have_is_nothrow_move) {
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
}
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception>
>::value));
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_multiset<int, boost::hash<int>,
equal_to_possible_exception>
>::value));
}
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{
typedef boost::unordered_set<int,
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
if (have_is_nothrow_move)
{
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
throwing_test_exception = false;
throwing_set x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
} catch(test_exception) {
BOOST_TEST(false);
}
throwing_test_exception = false;
}
}
}
RUN_TESTS()
+11 -9
View File
@@ -22,7 +22,7 @@ test::seed_t initialize_seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{
return static_cast<double>(x.bucket_count()) >=
return static_cast<double>(x.bucket_count()) >
static_cast<double>(x.size()) / x.max_load_factor() &&
x.bucket_count() >= n;
}
@@ -139,7 +139,7 @@ void reserve_test1(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13)
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
@@ -149,6 +149,9 @@ void reserve_test1(X*, test::random_generator generator)
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
// For the current standard this should reserve i+1, I've
// submitted a defect report and will assume it's a defect
// for now.
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
// Insert an element before the range insert, otherwise there are
@@ -171,7 +174,7 @@ void reserve_test2(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13)
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
@@ -208,22 +211,21 @@ boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
@@ -233,11 +235,11 @@ UNORDERED_TEST(reserve_empty_test2,
)
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
+2 -3
View File
@@ -206,7 +206,6 @@ bool is_propagate(T*)
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_AUTO_TEST(check_traits)
{
@@ -221,7 +220,7 @@ UNORDERED_TEST(swap_tests1, (
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(swap_tests2, (
@@ -229,7 +228,7 @@ UNORDERED_TEST(swap_tests2, (
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
)
((default_generator)(generate_collisions)(limited_range))
((default_generator)(generate_collisions))
)
}
+14 -48
View File
@@ -115,24 +115,10 @@ namespace unnecessary_copy_tests
#endif
{
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x) {
return static_cast<std::size_t>(x.tag_);
return x.tag_;
}
}
// Boost.Move doesn't seem to work very well on this compiler.
// For example for:
//
// T x;
//
// It will default construct T, and then move it in.
// For 'T const' it seems to copy.
#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
#define EXTRA_CONSTRUCT_COST 1
#else
#define EXTRA_CONSTRUCT_COST 0
#endif
#define COPY_COUNT(n) \
if(::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
@@ -164,13 +150,9 @@ namespace unnecessary_copy_tests
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define COPY_COUNT_EXTRA(a, b) \
COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
#define MOVE_COUNT_EXTRA(a, b) \
MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
namespace unnecessary_copy_tests
{
@@ -225,29 +207,13 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T>
void unnecessary_copy_emplace_std_move_test(T*)
void unnecessary_copy_emplace_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT(0);
x.emplace(std::move(a));
COPY_COUNT(1); MOVE_COUNT(1);
}
UNORDERED_TEST(unnecessary_copy_emplace_std_move_test,
((set)(multiset)(map)(multimap)))
#endif
template <class T>
void unnecessary_copy_emplace_boost_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1); MOVE_COUNT(1);
@@ -257,7 +223,7 @@ namespace unnecessary_copy_tests
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_test,
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
((set)(multiset)(map)(multimap)))
template <class T>
@@ -281,10 +247,10 @@ namespace unnecessary_copy_tests
T x;
COPY_COUNT(0); MOVE_COUNT(0);
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(1); MOVE_COUNT(0);
x.emplace(boost::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(2); MOVE_COUNT(0);
#else
COPY_COUNT(1); MOVE_COUNT(1);
#endif
@@ -398,7 +364,7 @@ namespace unnecessary_copy_tests
// TODO: Run tests for pairs without const etc.
std::pair<count_copies const, count_copies> a;
x.emplace(a);
COPY_COUNT_EXTRA(4, 1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(4); MOVE_COUNT(0);
//
// 0 arguments
@@ -408,7 +374,7 @@ namespace unnecessary_copy_tests
// COPY_COUNT(1) would be okay here.
reset();
x.emplace();
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
# if BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
// This is a little odd, Visual C++ 11 seems to move the pair, which
// results in one copy (for the const key) and one move (for the
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
@@ -416,7 +382,7 @@ namespace unnecessary_copy_tests
// Visual C++ 11 handles calling move for default arguments.
COPY_COUNT(3); MOVE_COUNT(1);
# else
COPY_COUNT_EXTRA(2, 1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(2); MOVE_COUNT(0);
# endif
#endif
@@ -441,8 +407,9 @@ namespace unnecessary_copy_tests
x.emplace(source<std::pair<count_copies, count_copies> >());
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
!(defined(_MSC_VER) && _MSC_VER < 1600)
#if (defined(__GNUC__) && __GNUC__ > 4) || \
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
@@ -509,9 +476,8 @@ namespace unnecessary_copy_tests
COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
#if defined(__GNUC__) && __GNUC__ > 4 || \
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
reset();
x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first),