Compare commits

..

1 Commits

Author SHA1 Message Date
Beman Dawes f409496e68 Boost 1.42.0
[SVN r59432]
2010-02-02 20:03:43 +00:00
87 changed files with 5997 additions and 13646 deletions
-1
View File
@@ -1 +0,0 @@
/doc/html/
+5 -11
View File
@@ -3,14 +3,16 @@
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
using boostbook ;
using quickbook ;
path-constant images_location : ../ ;
path-constant admonishment_location : ../../../../doc/src/images ;
xml unordered : unordered.qbk ;
boostbook standalone : unordered :
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
<xsl:param>boost.root=../../../..
<xsl:param>boost.libraries=../../../libraries.htm
<xsl:param>navig.graphics=1
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
<xsl:param>generate.section.toc.level=2
@@ -21,15 +23,7 @@ boostbook standalone : unordered :
<xsl:param>boost.compact.function=0
<xsl:param>boost.compact.enum=0
# HTML Options:
<format>html:<xsl:param>boost.root=../../../..
<format>html:<xsl:param>img.src.path=../../../../doc/html/
<format>xhtml:<xsl:param>boost.root=../../../..
<format>xhtml:<xsl:param>img.src.path=../../../../doc/html/
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
<xsl:param>fop1.extensions=0
<format>pdf:<xsl:param>xep.extensions=1
+1 -1
View File
@@ -112,7 +112,7 @@ load factor is /required/ to be less than the maximum is following a call to
below the max load factor, and set the maximum load factor to be the same as
or close to the hint - unless your hint is unreasonably small or large.
[table:bucket_size Methods for Controlling Bucket Size
[table Methods for Controlling Bucket Size
[[Method] [Description]]
[
+1 -153
View File
@@ -3,9 +3,6 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[template ticket[number]'''<ulink
url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
[section:changes Change Log]
[h2 Review Version]
@@ -47,7 +44,7 @@ First official release.
[h2 Boost 1.38.0]
* Use [@boost:/libs/core/swap.html `boost::swap`].
* Use [@boost:/libs/utility/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
@@ -120,153 +117,4 @@ First official release.
Add missing `std` qualifier to `ptrdiff_t`.
* Some code formatting changes to fit almost all lines into 80 characters.
[h2 Boost 1.43.0]
* [@http://svn.boost.org/trac/boost/ticket/3966 Ticket 3966]:
`erase_return_void` is now `quick_erase`, which is the
[@http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579
current forerunner for resolving the slow erase by iterator], although
there's a strong possibility that this may change in the future. The old
method name remains for backwards compatibility but is considered deprecated
and will be removed in a future release.
* Use Boost.Exception.
* Stop using deprecated `BOOST_HAS_*` macros.
[h2 Boost 1.45.0]
* Fix a bug when inserting into an `unordered_map` or `unordered_set` using
iterators which returns `value_type` by copy.
[h2 Boost 1.48.0 - Major update]
This is major change which has been converted to use Boost.Move's move
emulation, and be more compliant with the C++11 standard. See the
[link unordered.compliance compliance section] for details.
The container now meets C++11's complexity requirements, but to do so
uses a little more memory. This means that `quick_erase` and
`erase_return_void` are no longer required, they'll be removed in a
future version.
C++11 support has resulted in some breaking changes:
* Equality comparison has been changed to the C++11 specification.
In a container with equivalent keys, elements in a group with equal
keys used to have to be in the same order to be considered equal,
now they can be a permutation of each other. To use the old
behavior define the macro `BOOST_UNORDERED_DEPRECATED_EQUALITY`.
* The behaviour of swap is different when the two containers to be
swapped has unequal allocators. It used to allocate new nodes using
the appropriate allocators, it now swaps the allocators if
the allocator has a member structure `propagate_on_container_swap`,
such that `propagate_on_container_swap::value` is true.
* Allocator's `construct` and `destroy` functions are called with raw
pointers, rather than the allocator's `pointer` type.
* `emplace` used to emulate the variadic pair constructors that
appeared in early C++0x drafts. Since they were removed it no
longer does so. It does emulate the new `piecewise_construct`
pair constructors - only you need to use
`boost::piecewise_construct`. To use the old emulation of
the variadic consturctors define
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
[h2 Boost 1.49.0]
* Fix warning due to accidental odd assignment.
* Slightly better error messages.
[h2 Boost 1.50.0]
* Fix equality for `unordered_multiset` and `unordered_multimap`.
* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
Implement `reserve`.
* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
Fix some Sun specific code.
* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
Avoid gcc's `-Wshadow` warning.
* [@https://svn.boost.org/trac/boost/ticket/6905 Ticket 6905]:
Make namespaces in macros compatible with `bcp` custom namespaces.
Fixed by Luke Elliott.
* Remove some of the smaller prime number of buckets, as they may make
collisions quite probable (e.g. multiples of 5 are very common because
we used base 10).
* On old versions of Visual C++, use the container library's implementation
of `allocator_traits`, as it's more likely to work.
* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas
Wang's hash function to pick which one to use. As modulus is very slow
for 64 bit values.
* Some internal changes.
[h2 Boost 1.51.0]
* Fix construction/destruction issue when using a C++11 compiler with a
C++03 allocator ([ticket 7100]).
* Remove a `try..catch` to support compiling without exceptions.
* Adjust SFINAE use to try to supprt g++ 3.4 ([ticket 7175]).
* Updated to use the new config macros.
[h2 Boost 1.52.0]
* Faster assign, which assigns to existing nodes where possible, rather than
creating entirely new nodes and copy constructing.
* Fixed bug in `erase_range` ([ticket 7471]).
* Reverted some of the internal changes to how nodes are created, especially
for C++11 compilers. 'construct' and 'destroy' should work a little better
for C++11 allocators.
* Simplified the implementation a bit. Hopefully more robust.
[h2 Boost 1.53.0]
* Remove support for the old pre-standard variadic pair constructors, and
equality implementation. Both have been deprecated since Boost 1.48.
* Remove use of deprecated config macros.
* More internal implementation changes, including a much simpler
implementation of `erase`.
[h2 Boost 1.54.0]
* Mark methods specified in standard as `noexpect`. More to come in the next
release.
* If the hash function and equality predicate are known to both have nothrow
move assignment or construction then use them.
[h2 Boost 1.55.0]
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
* Follow the standard by only using the allocators' construct and destroy
methods to construct and destroy stored elements. Don't use them for internal
data like pointers.
[h2 Boost 1.56.0]
* Fix some shadowed variable warnings ([ticket 9377]).
* Fix allocator use in documentation ([ticket 9719]).
* Always use prime number of buckets for integers. Fixes performance
regression when inserting consecutive integers, although makes other
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[endsect]
+8 -5
View File
@@ -1,10 +1,10 @@
[/ Copyright 2006-2011 Daniel James.
[/ Copyright 2006-2008 Daniel James.
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[section:comparison Comparison with Associative Containers]
[table:interface_differences Interface differences.
[table Interface differences.
[[Associative Containers] [Unordered Associative Containers]]
[
@@ -66,12 +66,15 @@
[
[No equivalent]
[Local iterators can be used to iterate through individual buckets.
(The order of local iterators and iterators aren't
(I don't think that the order of local iterators and iterators are
required to have any correspondence.)]
]
[
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
[Can be compared using the `==` and `!=` operators.]
[No comparison operators are defined in the standard, although
[link unordered.rationale.equality_operators
implementations might extend the containers to support `==` and
`!=`].]
]
[
[]
@@ -85,7 +88,7 @@
]
]
[table:complexity_guarantees Complexity Guarantees
[table Complexity Guarantees
[[Operation] [Associative Containers] [Unordered Associative Containers]]
[
[Construction of empty container]
-112
View File
@@ -1,112 +0,0 @@
[/ Copyright 2011 Daniel James.
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[section:compliance C++11 Compliance]
[section:move Move emulation]
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Argument forwarding is not perfect.
[endsect]
[section:allocator_compliance Use of allocators]
C++11 introduced a new allocator system. It's backwards compatible due to
the lax requirements for allocators in the old standard, but might need
some changes for allocators which worked with the old versions of the
unordered containers.
It uses a traits class, `allocator_traits` to handle the allocator
adding extra functionality, and making some methods and types optional.
During development a stable release of
`allocator_traits` wasn't available so an internal partial implementation
is always used in this version. Hopefully a future version will use the
standard implementation where available.
The member functions `construct`, `destroy` and `max_size` are now
optional, if they're not available a fallback is used.
A full implementation of `allocator_traits` requires sophisticated
member function detection so that the fallback is used whenever the
member function call is not well formed.
This requires support for SFINAE expressions, which are available on
GCC from version 4.4 and Clang.
On other compilers, there's just a test to see if the allocator has
a member, but no check that it can be called. So rather than using a
fallback there will just be a compile error.
`propagate_on_container_copy_assignment`,
`propagate_on_container_move_assignment`,
`propagate_on_container_swap` and
`select_on_container_copy_construction` are also supported.
Due to imperfect move emulation, some assignments might check
`propagate_on_container_copy_assignment` on some compilers and
`propagate_on_container_move_assignment` on others.
The use of the allocator's construct and destruct methods might be a bit
surprising.
Nodes are constructed and destructed using the allocator, but the elements
are stored in aligned space within the node and constructed and destructed
by calling the constructor and destructor directly.
In C++11 the allocator's construct function has the signature:
template <class U, class... Args>
void construct(U* p, Args&&... args);
which supports calling `construct` for the contained object, but
most existing allocators don't support this. If member function detection
was good enough then with old allocators it would fall back to calling
the element's constructor directly but in general, detection isn't good
enough to do this which is why Boost.Unordered just calls the constructor
directly every time. In most cases this will work okay.
`pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators, this can cause problems if the allocator can't be
used with incomplete types. If `const_pointer` is not defined in the
allocator, `boost::pointer_to_other<pointer, const value_type>::type`
is used to obtain a const pointer.
[endsect]
[section:pairs Pairs]
Since the containers use `std::pair` they're limited to the version
from the current standard library. But since C++11 `std::pair`'s
`piecewise_construct` based constructor is very useful, `emplace`
emulates it with a `piecewise_construct` in the `boost::unordered`
namespace. So for example, the following will work:
boost::unordered_multimap<std::string, std::complex> x;
x.emplace(
boost::unordered::piecewise_construct,
boost::make_tuple("key"), boost::make_tuple(1, 2));
Older drafts of the standard also supported variadic constructors
for `std::pair`, where the first argument would be used for the
first part of the pair, and the remaining for the second part.
[endsect]
[section:misc Miscellaneous]
When swapping, `Pred` and `Hash` are not currently swapped by calling
`swap`, their copy constructors are used. As a consequence when swapping
an exception may be throw from their copy constructor.
Variadic constructor arguments for `emplace` are only used when both
rvalue references and variadic template parameters are available.
Otherwise `emplace` can only take up to 10 constructors arguments.
[endsect]
[endsect]
+2 -3
View File
@@ -67,10 +67,9 @@ so that the hash function doesn't need to be explicitly given:
See the [link hash.custom Boost.Hash documentation] for more detail on how to
do this. Remember that it relies on extensions to the draft standard - so it
won't work for other implementations of the unordered associative containers,
you'll need to explicitly use Boost.Hash.
won't work on other implementations of the unordered associative containers.
[table:access_methods Methods for accessing the hash and equality functions.
[table Methods for accessing the hash and equality functions.
[[Method] [Description]]
[
+17 -6
View File
@@ -2,6 +2,15 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[def __tr1__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
C++ Standard Library Technical Report]]
[def __boost-tr1__
[@http://www.boost.org/doc/html/boost_tr1.html
Boost.TR1]]
[def __draft__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
Working Draft of the C++ Standard]]
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
hash table]]
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function
@@ -22,10 +31,12 @@ to order their elements. For some data types this is impossible to implement
or isn't practical. In contrast, a hash table only needs an equality function
and a hash function for the key.
With this in mind, unordered associative containers were added to the C++
standard. This is an implementation of the containers described in C++11,
with some [link unordered.compliance deviations from the standard] in
order to work with non-C++11 compilers and libraries.
With this in mind, the __tr1__ introduced the unordered associative containers,
which are implemented using hash tables, and they have now been added to the
__draft__.
This library supplies an almost complete implementation of the specification in
the __draft__.
`unordered_set` and `unordered_multiset` are defined in the header
<[headerref boost/unordered_set.hpp]>
@@ -54,14 +65,14 @@ order to work with non-C++11 compilers and libraries.
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_map unordered_map]``;
template<
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_multimap unordered_multimap]``;
}
+55 -25
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]
@@ -44,8 +44,6 @@ bucket but there are a some serious problems with this:
So chained addressing is used.
[/ (Removing for now as this is out of date)
For containers with unique keys I store the buckets in a single-linked list.
There are other possible data structures (such as a double-linked list)
that allow for some operations to be faster (such as erasing and iteration)
@@ -65,17 +63,6 @@ nodes in reverse order. This allows quick navigation to the end of a group (sinc
the first element points to the last) and can be quickly updated when elements
are inserted or erased. The main disadvantage of this approach is some hairy code
for erasing elements.
]
[/ (Starting to write up new structure, might not be ready in time)
The node used to be stored in a linked list for each bucket but that
didn't meet the complexity requirements for C++11, so now the nodes
are stored in one long single linked list. But there needs a way to get
the bucket from the node, to do that a copy of the key's hash value is
stored in the node. Another possibility would be to store a pointer to
the bucket, or the bucket's index, but storing the hash value allows
some operations to be faster.
]
[h2 Number of Buckets]
@@ -85,8 +72,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 +82,60 @@ 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.
So, this implementation uses a prime number for the hash table size.
I'm also thinking of introducing a mechanism whereby a hash function can
indicate that it's safe to be used directly with power of 2 buckets, in
which case a faster plain power of 2 implementation can be used.
[h2 Equality operators]
`operator==` and `operator!=` are not included in the standard, but I've
added them as I think they could be useful and can be implemented
fairly efficiently. They are specified differently to the other standard
containers, comparing keys using the equality predicate rather than
`operator==`.
It's also different to the proposal
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2944.pdf n2944].
which uses the equality operators for the whole of `value_type`. This
implementation just uses the key equality function for the key,
and `mapped_type`'s equality operator in `unordered_map` and
`unordered_multimap` for the mapped part of the element.
Also, in `unordered_multimap`, the mapped values for a group of elements with
equivalent keys are only considered equal if they are in the same order,
in n2944 they just need to be a permutation of each other. Since the
order of elements with equal keys is now defined to be stable, it seems to me
that their order can be considered part of the container's value.
[h2 Active Issues and Proposals]
[h3 C++0x allocators]
Recent drafts have included an overhaul of the allocators, but this was
dependent on concepts which are no longer in the standard.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946]
attempts to respecify them without concepts. I'll try to implement this (or
an appropriate later version) in a future version of boost, possibly changed
a little to accomodate non-C++0x compilers.
[h3 Swapping containers with unequal allocators]
It isn't clear how to swap containers when their allocators aren't equal.
This is
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431
Issue 431: Swapping containers with unequal allocators]. This has been resolved
with the new allocator specification, so this should be fixed when
support is added.
[h3 Are insert and erase stable for unordered_multiset and unordered_multimap?]
It wan't specified if `unordered_multiset` and `unordered_multimap` preserve the order
of elements with equivalent keys (i.e. if they're stable under `insert` and `erase`).
Since [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
n2691] it's been specified that they do and this implementation follows that.
[endsect]
-1219
View File
File diff suppressed because it is too large Load Diff
+222 -900
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -3,7 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[library Boost.Unordered
[quickbook 1.5]
[quickbook 1.4]
[authors [James, Daniel]]
[copyright 2003 2004 Jeremy B. Maitin-Shepard]
[copyright 2005 2006 2007 2008 Daniel James]
@@ -13,7 +13,7 @@
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
[@http://www.boost.org/LICENSE_1_0.txt]
]
]
@@ -31,7 +31,6 @@
[include:unordered buckets.qbk]
[include:unordered hash_equality.qbk]
[include:unordered comparison.qbk]
[include:unordered compliance.qbk]
[include:unordered rationale.qbk]
[include:unordered changes.qbk]
[xinclude ref.xml]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,111 @@
// Copyright 2005-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)
// A couple of templates to make using allocators easier.
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__)
# define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# include <boost/detail/allocator_utilities.hpp>
#endif
namespace boost { namespace unordered_detail {
// rebind_wrap
//
// Rebind allocators. For some problematic libraries, use rebind_to
// from <boost/detail/allocator_utilities.hpp>.
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <class Alloc, class T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
#else
template <class Alloc, class T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
#endif
// allocator_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 <class Allocator>
struct allocator_array_constructor
{
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
allocator_array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
constructed_ = pointer();
ptr_ = pointer();
}
~allocator_array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
alloc_.destroy(p);
alloc_.deallocate(ptr_, length_);
}
}
template <class V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = alloc_.allocate(length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
alloc_.construct(constructed_, v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
return p;
}
private:
allocator_array_constructor(allocator_array_constructor const&);
allocator_array_constructor& operator=(
allocator_array_constructor const&);
};
}}
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#endif
File diff suppressed because it is too large Load Diff
+163 -640
View File
@@ -1,686 +1,209 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2011 Daniel James
// Copyright (C) 2005-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)
#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
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered_detail {
template <typename A, typename T> struct grouped_node;
template <typename T> struct grouped_ptr_node;
template <typename Types> struct grouped_table_impl;
////////////////////////////////////////////////////////////////////////////
// Equality
template <typename A, typename T>
struct grouped_node :
boost::unordered::detail::value_base<T>
template <class T>
bool hash_equivalent_table<T>
::equals(hash_equivalent_table<T> const& other) const
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, grouped_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
typedef node_pointer link_pointer;
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
link_pointer next_;
node_pointer group_prev_;
std::size_t hash_;
grouped_node() :
next_(),
group_prev_(),
hash_(0)
{}
void init(node_pointer self)
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
{
group_prev_ = self;
}
private:
grouped_node& operator=(grouped_node const&);
};
template <typename T>
struct grouped_ptr_node :
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(),
group_prev_(0),
hash_(0)
{}
void init(node_pointer self)
{
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&);
};
// If the allocator uses raw pointers use grouped_ptr_node
// Otherwise use grouped_node.
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_grouped_node2
{
typedef boost::unordered::detail::grouped_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
>::pointer node_pointer;
typedef boost::unordered::detail::bucket<node_pointer> bucket;
typedef node_pointer link_pointer;
};
template <typename A, typename T>
struct pick_grouped_node2<A, T,
boost::unordered::detail::grouped_ptr_node<T>*,
boost::unordered::detail::ptr_bucket*>
{
typedef boost::unordered::detail::grouped_ptr_node<T> node;
typedef boost::unordered::detail::ptr_bucket bucket;
typedef bucket* link_pointer;
};
template <typename A, typename T>
struct pick_grouped_node
{
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::grouped_ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_grouped_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::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 typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
struct grouped_table_impl : boost::unordered::detail::table<Types>
{
typedef boost::unordered::detail::table<Types> table;
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
typedef typename table::bucket_pointer bucket_pointer;
typedef typename table::link_pointer link_pointer;
typedef typename table::hasher hasher;
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
// Constructors
grouped_table_impl(std::size_t n,
hasher const& hf,
key_equal const& eq,
node_allocator const& a)
: table(n, hf, eq, a)
{}
grouped_table_impl(grouped_table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
grouped_table_impl(grouped_table_impl const& x,
node_allocator const& a)
: table(x, a)
{
this->init(x);
}
grouped_table_impl(grouped_table_impl& x,
boost::unordered::detail::move_tag m)
: table(x, m)
{}
grouped_table_impl(grouped_table_impl& x,
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
for (;;)
node_ptr it1 = i->next_;
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
{
if (!n.node_) return n;
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
node_ptr end1 = node::next_group(it1);
node_ptr end2 = node::next_group(it2);
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
n = iterator(n.node_->group_prev_->next_);
do {
if(!extractor::compare_mapped(
node::get_value(it1), node::get_value(it2)))
return false;
it1 = it1->next_;
it2 = it2->next_;
} while(it1 != end1 && it2 != end2);
if(it1 != end1 || it2 != end2) return false;
}
}
std::size_t count(key_type const& k) const
{
iterator n = this->find_node(k);
if (!n.node_) return 0;
return true;
}
std::size_t x = 0;
node_pointer it = n.node_;
do {
it = it->group_prev_;
++x;
} while(it != n.node_);
////////////////////////////////////////////////////////////////////////////
// A convenience method for adding nodes.
return x;
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::node_ptr
hash_equivalent_table<T>
::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
{
node_ptr n = a.release();
if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
node::add_after_node(n, pos);
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
return std::make_pair(
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
else {
node::add_to_bucket(n, *bucket);
if(bucket < this->cached_begin_bucket_)
this->cached_begin_bucket_ = bucket;
}
++this->size_;
return n;
}
// Equality
////////////////////////////////////////////////////////////////////////////
// Insert methods
bool equals(grouped_table_impl const& other) const
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_;)
{
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(n1.node_->group_prev_->next_);
iterator end2(n2.node_->group_prev_->next_);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
return true;
template <class T>
inline BOOST_DEDUCED_TYPENAME
hash_equivalent_table<T>::iterator_base
hash_equivalent_table<T>::emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash_value = this->hash_function()(k);
if(!this->size_) {
return this->emplace_empty_impl_with_node(a, 1);
}
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if (*n1 != *n2) break;
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(iterator n1a = n1, n2a = n2;;)
{
++n1a;
++n2a;
if (n1a == end1)
{
if (n2a == end2) break;
else return false;
}
if (n2a == end2) return false;
}
iterator start = n1;
for(;n1 != end1; ++n1)
{
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
}
return true;
}
static bool find(iterator n, iterator end, value_type const& v)
{
for(;n != end; ++n)
if (*n == v)
return true;
return false;
}
static std::size_t count_equal(iterator n, iterator end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; ++n)
if (*n == v) ++count;
return count;
}
// Emplace/Insert
static inline void add_after_node(
node_pointer n,
node_pointer pos)
{
n->next_ = pos->group_prev_->next_;
n->group_prev_ = pos->group_prev_;
pos->group_prev_->next_ = n;
pos->group_prev_ = n;
}
inline iterator add_node(
node_constructor& a,
std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(
this->hash_to_bucket(key_hash));
if (!b->next_)
{
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_
))->next_ = n;
}
b->next_ = start_node;
n->next_ = start_node->next_;
start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = n;
}
}
++this->size_;
return iterator(n);
}
iterator emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
else {
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr position = this->find_iterator(bucket, 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);
}
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
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));
return iterator_base(bucket, add_node(a, bucket, position));
}
}
template <class T>
inline void hash_equivalent_table<T>
::emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
add_node(a, bucket, this->find_iterator(bucket, k));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#if defined(BOOST_UNORDERED_STD_FORWARD)
// Emplace (equivalent key containers)
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
template <class... Args>
BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base
hash_equivalent_table<T>
::emplace(Args&&... args)
{
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_impl(a);
}
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base \
hash_equivalent_table<T> \
::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_impl(a); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
////////////////////////////////////////////////////////////////////////////
// Insert range methods
return iterator(emplace_impl(a));
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
inline void hash_equivalent_table<T>
::insert_for_range(I i, I j, forward_traversal_tag)
{
if(i == j) return;
std::size_t distance = unordered_detail::distance(i, j);
if(distance == 1) {
emplace(*i);
}
else {
node_constructor a(*this);
////////////////////////////////////////////////////////////////////////
// Insert range methods
// if hash function throws, or inserting > 1 element, basic exception
// safety. Strong otherwise
template <class I>
typename boost::unordered::detail::enable_if_forward<I, void>::type
insert_range(I i, I j)
{
if(i == j) return;
std::size_t distance = boost::unordered::detail::distance(i, j);
if(distance == 1) {
node_constructor a(this->node_alloc());
a.construct_with_value2(*i);
emplace_impl(a);
}
else {
// Only require basic exception safety here
// Only require basic exception safety here
if(this->size_) {
this->reserve_for_insert(this->size_ + distance);
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
}
}
}
template <class I>
typename boost::unordered::detail::disable_if_forward<I, void>::type
insert_range(I i, I j)
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl(a);
}
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
std::size_t erase_key(key_type const& k)
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
{
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
node_pointer first_node = static_cast<node_pointer>(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
}
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
link_pointer erase_nodes(node_pointer i, node_pointer j)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// we're at it.
link_pointer prev = split_groups(i, j);
// If we don't have a 'prev' it means that i 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 = static_cast<node_pointer>(prev->next_)->group_prev_;
}
// Delete the nodes.
do {
link_pointer group_end =
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
return prev;
}
static link_pointer split_groups(node_pointer i, node_pointer j)
{
node_pointer prev = i->group_prev_;
if (prev->next_ != i) prev = node_pointer();
if (j) {
node_pointer first = j;
while (first != i && first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, j->group_prev_);
if (first == i) return prev;
}
if (prev) {
node_pointer first = prev;
while (first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, i->group_prev_);
}
return prev;
}
////////////////////////////////////////////////////////////////////////
// fill_buckets
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
link_pointer prev = dst.get_previous_start();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = key_hash;
prev->next_ = first_node;
++dst.size_;
for (++n; n != group_end; ++n)
{
end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
prev = place_in_bucket(dst, prev, end);
}
}
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
BOOST_ASSERT(this->buckets_);
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev,
static_cast<node_pointer>(prev->next_)->group_prev_);
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static link_pointer place_in_bucket(table& dst,
link_pointer prev, node_pointer end)
{
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
if (!b->next_) {
b->next_ = prev;
return end;
}
else {
link_pointer next = end->next_;
end->next_ = b->next_->next_;
b->next_->next_ = prev->next_;
prev->next_ = next;
return prev;
a.construct(*i++);
this->emplace_empty_impl_with_node(a, distance);
}
for (; i != j; ++i) {
a.construct(*i);
emplace_impl_no_rehash(a);
}
}
};
}}}
}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
inline void hash_equivalent_table<T>
::insert_for_range(I i, I j, boost::incrementable_traversal_tag)
{
node_constructor a(*this);
for (; i != j; ++i) {
a.construct(*i);
emplace_impl(a);
}
}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
void hash_equivalent_table<T>::insert_range(I i, I j)
{
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
iterator_traversal_tag;
insert_for_range(i, j, iterator_traversal_tag);
}
}}
#endif
+45 -85
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2005-2011 Daniel James
// Copyright (C) 2005-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)
@@ -7,15 +7,11 @@
#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>
#include <boost/type_traits/remove_const.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost {
namespace unordered {
namespace detail {
namespace unordered_detail {
// key extractors
//
@@ -32,19 +28,6 @@ namespace detail {
template <class T> no_key(T const&) {}
};
template <typename Key, typename T>
struct is_key {
template <typename T2>
static choice1::type test(T2 const&);
static choice2::type test(Key const&);
enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
sizeof(choice2::type) };
typedef typename boost::detail::if_true<value>::
BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
};
template <class ValueType>
struct set_extractor
{
@@ -61,38 +44,49 @@ namespace detail {
return no_key();
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
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&)
template <class Arg>
static no_key extract(Arg const&, Arg const&)
{
return no_key();
}
#endif
static bool compare_mapped(value_type const&, value_type const&)
{
return true;
}
};
template <class Key, class ValueType>
struct map_extractor
{
typedef ValueType value_type;
typedef typename boost::remove_const<Key>::type key_type;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Key>::type key_type;
static key_type const& extract(value_type const& v)
{
return v.first;
}
static key_type const& extract(key_type const& v)
{
return v;
}
template <class Second>
static key_type const& extract(std::pair<key_type, Second> const& v)
{
@@ -106,6 +100,20 @@ namespace detail {
return v.first;
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class Arg1, class... Args>
static key_type const& extract(key_type const& k,
Arg1 const&, Args const&...)
{
return k;
}
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
@@ -123,66 +131,18 @@ namespace detail {
return no_key();
}
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class Arg3, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
Args const&...)
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
{
return no_key();
}
#endif
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_ tuple<> const&, T2 const&) \
{ \
return no_key(); \
} \
\
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_ tuple<T> const& k, T2 const&) \
{ \
return typename is_key<key_type, T>::type( \
namespace_ get<0>(k)); \
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;
}
#else
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_ tuple<> const&) \
{ \
return no_key(); \
} \
\
template <typename T> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_ tuple<T> const& k) \
{ \
return typename is_key<key_type, T>::type( \
namespace_ get<0>(k)); \
}
#endif
BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
#endif
};
}}}
}}
#endif
File diff suppressed because it is too large Load Diff
+243
View File
@@ -0,0 +1,243 @@
/*
Copyright 2005-2007 Adobe Systems Incorporated
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
/*************************************************************************************************/
#ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER
#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
/*************************************************************************************************/
#if defined(BOOST_NO_SFINAE)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif defined(__GNUC__) && \
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#endif
/*************************************************************************************************/
namespace boost {
namespace unordered_detail {
/*************************************************************************************************/
namespace move_detail {
/*************************************************************************************************/
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
/*************************************************************************************************/
template <typename T>
struct class_has_move_assign {
class type {
typedef T& (T::*E)(T t);
typedef char (&no_type)[1];
typedef char (&yes_type)[2];
template <E e> struct sfinae { typedef yes_type type; };
template <class U>
static typename sfinae<&U::operator=>::type test(int);
template <class U>
static no_type test(...);
public:
enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};
};
};
/*************************************************************************************************/
template<typename T>
struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
/*************************************************************************************************/
class test_can_convert_anything { };
/*************************************************************************************************/
#endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
/*************************************************************************************************/
/*
REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where
boost::is_convertible<T, T> fails to compile.
*/
template <typename T, typename U>
struct is_convertible : boost::mpl::or_<
boost::is_same<T, U>,
boost::is_convertible<T, U>
> { };
/*************************************************************************************************/
} //namespace move_detail
/*************************************************************************************************/
/*!
\ingroup move_related
\brief move_from is used for move_ctors.
*/
template <typename T>
struct move_from
{
explicit move_from(T& x) : source(x) { }
T& source;
private:
move_from& operator=(move_from const&);
};
/*************************************************************************************************/
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
/*************************************************************************************************/
/*!
\ingroup move_related
\brief The is_movable trait can be used to identify movable types.
*/
template <typename T>
struct is_movable : boost::mpl::and_<
boost::is_convertible<move_from<T>, T>,
move_detail::has_move_assign<T>,
boost::mpl::not_<boost::is_convertible<move_detail::test_can_convert_anything, T> >
> { };
/*************************************************************************************************/
#else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
// On compilers which don't have adequate SFINAE support, treat most types as unmovable,
// unless the trait is specialized.
template <typename T>
struct is_movable : boost::mpl::false_ { };
#endif
/*************************************************************************************************/
#if !defined(BOOST_NO_SFINAE)
/*************************************************************************************************/
/*!
\ingroup move_related
\brief copy_sink and move_sink are used to select between overloaded operations according to
whether type T is movable and convertible to type U.
\sa move
*/
template <typename T,
typename U = T,
typename R = void*>
struct copy_sink : boost::enable_if<
boost::mpl::and_<
boost::unordered_detail::move_detail::is_convertible<T, U>,
boost::mpl::not_<is_movable<T> >
>,
R
>
{ };
/*************************************************************************************************/
/*!
\ingroup move_related
\brief move_sink and copy_sink are used to select between overloaded operations according to
whether type T is movable and convertible to type U.
\sa move
*/
template <typename T,
typename U = T,
typename R = void*>
struct move_sink : boost::enable_if<
boost::mpl::and_<
boost::unordered_detail::move_detail::is_convertible<T, U>,
is_movable<T>
>,
R
>
{ };
/*************************************************************************************************/
/*!
\ingroup move_related
\brief This version of move is selected when T is_movable . It in turn calls the move
constructor. This call, with the help of the return value optimization, will cause x to be moved
instead of copied to its destination. See adobe/test/move/main.cpp for examples.
*/
template <typename T>
T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
/*************************************************************************************************/
/*!
\ingroup move_related
\brief This version of move is selected when T is not movable . The net result will be that
x gets copied.
*/
template <typename T>
T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
/*************************************************************************************************/
#else // BOOST_NO_SFINAE
// On compilers without SFINAE, define copy_sink to always use the copy function.
template <typename T,
typename U = T,
typename R = void*>
struct copy_sink
{
typedef R type;
};
// Always copy the element unless this is overloaded.
template <typename T>
T& move(T& x) {
return x;
}
#endif // BOOST_NO_SFINAE
} // namespace unordered_detail
} // namespace boost
/*************************************************************************************************/
#endif
/*************************************************************************************************/
+226
View File
@@ -0,0 +1,226 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
// This contains the basic data structure, apart from the actual values. There's
// no construction or deconstruction here. So this only depends on the pointer
// type.
#ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/unordered/detail/fwd.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
#else
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
#endif
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// ungrouped node implementation
template <class A>
inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
ungrouped_node_base<A>::next_group(node_ptr ptr)
{
return ptr->next_;
}
template <class A>
inline std::size_t ungrouped_node_base<A>::group_count(node_ptr)
{
return 1;
}
template <class A>
inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
{
n->next_ = b.next_;
b.next_ = n;
}
template <class A>
inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
node_ptr position)
{
n->next_ = position->next_;
position->next_ = position;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
node_ptr begin, node_ptr end)
{
node_ptr* pos = &b.next_;
while(*pos != begin) pos = &(*pos)->next_;
*pos = end;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
{
b.next_ = end;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
{
unlink_nodes(b, n, n->next_);
}
////////////////////////////////////////////////////////////////////////////
// grouped node implementation
// If ptr is the first element in a group, return pointer to next group.
// Otherwise returns a pointer to ptr.
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
grouped_node_base<A>::next_group(node_ptr ptr)
{
return get(ptr).group_prev_->next_;
}
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
grouped_node_base<A>::first_in_group(node_ptr ptr)
{
while(next_group(ptr) == ptr)
ptr = get(ptr).group_prev_;
return ptr;
}
template <class A>
inline std::size_t grouped_node_base<A>::group_count(node_ptr ptr)
{
node_ptr start = ptr;
std::size_t size = 0;
do {
++size;
ptr = get(ptr).group_prev_;
} while(ptr != start);
return size;
}
template <class A>
inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
{
n->next_ = b.next_;
get(n).group_prev_ = n;
b.next_ = n;
}
template <class A>
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
{
n->next_ = next_group(pos);
get(n).group_prev_ = get(pos).group_prev_;
next_group(pos) = n;
get(pos).group_prev_ = n;
}
// Break a ciruclar list into two, with split as the beginning
// of the second group (if split is at the beginning then don't
// split).
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
grouped_node_base<A>::split_group(node_ptr split)
{
node_ptr first = first_in_group(split);
if(first == split) return split;
node_ptr last = get(first).group_prev_;
get(first).group_prev_ = get(split).group_prev_;
get(split).group_prev_ = last;
return first;
}
template <class A>
void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
{
node_ptr next = n->next_;
node_ptr* pos = &next_group(n);
if(*pos != n) {
// The node is at the beginning of a group.
// Find the previous node pointer:
pos = &b.next_;
while(*pos != n) pos = &next_group(*pos);
// Remove from group
if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
get(next).group_prev_ == n)
{
get(next).group_prev_ = get(n).group_prev_;
}
}
else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
get(next).group_prev_ == n)
{
// The deleted node is not at the end of the group, so
// change the link from the next node.
get(next).group_prev_ = get(n).group_prev_;
}
else {
// The deleted node is at the end of the group, so the
// first node in the group is pointing to it.
// Find that to change its pointer.
node_ptr x = get(n).group_prev_;
while(get(x).group_prev_ != n) {
x = get(x).group_prev_;
}
get(x).group_prev_ = get(n).group_prev_;
}
*pos = next;
}
template <class A>
void grouped_node_base<A>::unlink_nodes(bucket& b,
node_ptr begin, node_ptr end)
{
node_ptr* pos = &next_group(begin);
if(*pos != begin) {
// The node is at the beginning of a group.
// Find the previous node pointer:
pos = &b.next_;
while(*pos != begin) pos = &next_group(*pos);
// Remove from group
if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
}
else {
node_ptr group1 = split_group(begin);
if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
node_ptr group2 = split_group(end);
if(begin == group2) {
node_ptr end1 = get(group1).group_prev_;
node_ptr end2 = get(group2).group_prev_;
get(group1).group_prev_ = end2;
get(group2).group_prev_ = end1;
}
}
}
*pos = end;
}
template <class A>
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
{
split_group(end);
b.next_ = end;
}
}}
#endif
File diff suppressed because it is too large Load Diff
+354 -595
View File
@@ -1,628 +1,387 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2011 Daniel James
// Copyright (C) 2005-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)
#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
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered_detail {
template <typename A, typename T> struct unique_node;
template <typename T> struct ptr_node;
template <typename Types> struct table_impl;
////////////////////////////////////////////////////////////////////////////
// Equality
template <typename A, typename T>
struct unique_node :
boost::unordered::detail::value_base<T>
template <class T>
bool hash_unique_table<T>
::equals(hash_unique_table<T> const& other) const
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
typedef node_pointer link_pointer;
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
link_pointer next_;
std::size_t hash_;
unique_node() :
next_(),
hash_(0)
{}
void init(node_pointer)
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
{
}
private:
unique_node& operator=(unique_node const&);
};
template <typename T>
struct ptr_node :
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(),
hash_(0)
{}
void init(node_pointer)
{
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
ptr_node& operator=(ptr_node const&);
};
// If the allocator uses raw pointers use ptr_node
// Otherwise use node.
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_node2
{
typedef boost::unordered::detail::unique_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
>::pointer node_pointer;
typedef boost::unordered::detail::bucket<node_pointer> bucket;
typedef node_pointer link_pointer;
};
template <typename A, typename T>
struct pick_node2<A, T,
boost::unordered::detail::ptr_node<T>*,
boost::unordered::detail::ptr_bucket*>
{
typedef boost::unordered::detail::ptr_node<T> node;
typedef boost::unordered::detail::ptr_bucket bucket;
typedef bucket* link_pointer;
};
template <typename A, typename T>
struct pick_node
{
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_node<T> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_node2<A, T,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::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 typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
struct table_impl : boost::unordered::detail::table<Types>
{
typedef boost::unordered::detail::table<Types> table;
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
typedef typename table::bucket_pointer bucket_pointer;
typedef typename table::link_pointer link_pointer;
typedef typename table::hasher hasher;
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
typedef std::pair<iterator, bool> emplace_return;
// Constructors
table_impl(std::size_t n,
hasher const& hf,
key_equal const& eq,
node_allocator const& a)
: table(n, hf, eq, a)
{}
table_impl(table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
table_impl(table_impl const& x,
node_allocator const& a)
: table(x, a)
{
this->init(x);
}
table_impl(table_impl& x,
boost::unordered::detail::move_tag m)
: table(x, m)
{}
table_impl(table_impl& x,
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
for (;;)
node_ptr it1 = i->next_;
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
{
if (!n.node_) return n;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
++n;
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k).node_ ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
iterator it = this->find_node(k);
if (it.node_) return *it;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
}
// equals
bool equals(table_impl const& other) const
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_; ++n1)
{
iterator n2 = other.find_matching_node(n1);
if (!n2.node_ || *n1 != *n2)
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
if(!extractor::compare_mapped(
node::get_value(it1), node::get_value(it2)))
return false;
it1 = it1->next_;
}
return true;
}
// Emplace/Insert
return true;
}
inline iterator add_node(
node_constructor& a,
std::size_t key_hash)
{
node_pointer n = a.release();
n->hash_ = key_hash;
////////////////////////////////////////////////////////////////////////////
// A convenience method for adding nodes.
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::node_ptr
hash_unique_table<T>::add_node(node_constructor& a,
bucket_ptr bucket)
{
node_ptr n = a.release();
node::add_to_bucket(n, *bucket);
++this->size_;
if(bucket < this->cached_begin_bucket_)
this->cached_begin_bucket_ = bucket;
return n;
}
////////////////////////////////////////////////////////////////////////////
// Insert methods
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::value_type&
hash_unique_table<T>::operator[](key_type const& k)
{
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
if(!this->buckets_) {
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
return *this->emplace_empty_impl_with_node(a, 1);
}
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
return node::get_value(pos);
}
else {
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return node::get_value(add_node(a, bucket));
}
}
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl_with_node(node_constructor& a)
{
// No side effects in this initial code
key_type const& k = this->get_key(a.value());
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Found an existing key, return it (no throw).
return emplace_return(iterator_base(bucket, pos), false);
} else {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return emplace_return(
iterator_base(bucket, add_node(a, bucket)),
true);
}
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl(key_type const& k,
Args&&... args)
{
// No side effects in this initial code
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Found an existing key, return it (no throw).
return emplace_return(iterator_base(bucket, pos), false);
} else {
// Doesn't already exist, add to bucket.
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return emplace_return(
iterator_base(bucket, add_node(a, bucket)),
true);
}
}
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl(no_key, Args&&... args)
{
// Construct the node regardless - in order to get the key.
// It will be discarded if it isn't used
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_impl_with_node(a);
}
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_empty_impl(Args&&... args)
{
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true);
}
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>::emplace_impl( \
key_type const& k, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
std::size_t hash_value = this->hash_function()(k); \
bucket_ptr bucket \
= this->bucket_ptr_from_hash(hash_value); \
node_ptr pos = this->find_iterator(bucket, k); \
\
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
return emplace_return(iterator_base(bucket, pos), false); \
} else { \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
\
if(this->reserve_for_insert(this->size_ + 1)) \
bucket = this->bucket_ptr_from_hash(hash_value); \
\
return emplace_return(iterator_base(bucket, \
add_node(a, bucket)), true); \
} \
} \
\
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>:: \
emplace_impl(no_key, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_impl_with_node(a); \
} \
\
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>:: \
emplace_empty_impl( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD)
// Emplace (unique keys)
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
template<class... Args>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace(Args&&... args)
{
return this->size_ ?
emplace_impl(
extractor::extract(std::forward<Args>(args)...),
std::forward<Args>(args)...) :
emplace_empty_impl(std::forward<Args>(args)...);
}
#else
template <class T>
template <class Arg0>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace(Arg0 const& arg0)
{
return this->size_ ?
emplace_impl(extractor::extract(arg0), arg0) :
emplace_empty_impl(arg0);
}
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return \
hash_unique_table<T>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
return this->size_ ? \
emplace_impl(extractor::extract(arg0, arg1), \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)) : \
emplace_empty_impl( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
}
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
////////////////////////////////////////////////////////////////////////////
// Insert range methods
if (!b->next_)
{
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
template <class T>
template <class InputIt>
inline void hash_unique_table<T>::insert_range_impl(
key_type const&, InputIt i, InputIt j)
{
node_constructor a(*this);
if(!this->size_) {
a.construct(*i);
this->emplace_empty_impl_with_node(a, 1);
++i;
if(i == j) return;
}
do {
// No side effects in this initial code
// Note: can't use get_key as '*i' might not be value_type - it
// could be a pair with first_types as key_type without const or a
// different second_type.
key_type const& k = extractor::extract(*i);
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Doesn't already exist, add to bucket.
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
a.construct(*i);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->size_ + 1 >= this->max_load_) {
this->reserve_for_insert(this->size_ + insert_size(i, j));
bucket = this->bucket_ptr_from_hash(hash_value);
}
b->next_ = start_node;
n->next_ = start_node->next_;
start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = n;
}
++this->size_;
return iterator(n);
}
value_type& operator[](key_type const& k)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return *pos;
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
this->reserve_for_insert(this->size_ + 1);
return *add_node(a, key_hash);
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_impl(
extractor::extract(args.a0, args.a1),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
{
return emplace_impl(extractor::extract(args.a0), args);
}
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
// Don't have a key, so construct the node first in order
// to be able to lookup the position.
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
//
// if hash function throws, or inserting > 1 element, basic exception
// safety strong otherwise
template <class InputIt>
void insert_range(InputIt i, InputIt j)
{
if(i != j)
return insert_range_impl(extractor::extract(*i), i, j);
}
template <class InputIt>
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
insert_range_impl2(a, k, i, j);
while(++i != j) {
// Note: can't use get_key as '*i' might not be value_type - it
// could be a pair with first_types as key_type without const or
// a different second_type.
//
// TODO: Might be worth storing the value_type instead of the
// key here. Could be more efficient if '*i' is expensive. Could
// be less efficient if copying the full value_type is
// expensive.
insert_range_impl2(a, extractor::extract(*i), i, j);
}
}
template <class InputIt>
void insert_range_impl2(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (!pos.node_) {
a.construct_with_value2(*i);
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
// Nothing after this point can throw.
this->add_node(a, key_hash);
add_node(a, bucket);
}
} while(++i != j);
}
template <class T>
template <class InputIt>
inline void hash_unique_table<T>::insert_range_impl(
no_key, InputIt i, InputIt j)
{
node_constructor a(*this);
if(!this->size_) {
a.construct(*i);
this->emplace_empty_impl_with_node(a, 1);
++i;
if(i == j) return;
}
template <class InputIt>
void insert_range_impl(no_key, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
do {
// No side effects in this initial code
a.construct(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
do {
a.construct_with_value2(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
std::size_t erase_key(key_type const& k)
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
{
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = prev->next_;
}
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
}
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
void erase_nodes(node_pointer i, node_pointer j)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
// Find the node before i.
link_pointer prev = this->get_previous_start(bucket_index);
while(prev->next_ != i) prev = prev->next_;
// Delete the nodes.
do {
this->delete_node(prev);
bucket_index = this->fix_bucket(bucket_index, prev);
} while (prev->next_ != j);
}
////////////////////////////////////////////////////////////////////////
// fill_buckets
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
link_pointer prev = dst.get_previous_start();
while (n.node_) {
node_pointer node = creator.create(*n);
node->hash_ = n.node_->hash_;
prev->next_ = node;
++dst.size_;
++n;
prev = place_in_bucket(dst, prev);
}
}
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
BOOST_ASSERT(this->buckets_);
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev);
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {
b->next_ = prev;
return n;
}
else {
prev->next_ = n->next_;
n->next_ = b->next_->next_;
b->next_->next_ = n;
return prev;
}
}
};
}}}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class InputIt>
void hash_unique_table<T>::insert_range(InputIt i, InputIt j)
{
if(i != j)
return insert_range_impl(extractor::extract(*i), i, j);
}
}}
#endif
+209 -152
View File
@@ -1,68 +1,45 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2011 Daniel James
// Copyright (C) 2005-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)
#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
#endif
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_empty.hpp>
#include <cstddef>
#include <utility>
#include <algorithm>
#include <boost/limits.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/swap.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost { namespace unordered { namespace detail {
static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11;
struct move_tag {};
struct empty_emplace {};
namespace func {
template <class T>
inline void ignore_unused_variable_warning(T const&) {}
}
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
// convert double to std::size_t
template <typename I>
struct is_forward :
boost::is_convertible<
typename boost::iterator_traversal<I>::type,
boost::forward_traversal_tag>
{};
template <typename I, typename ReturnType>
struct enable_if_forward :
boost::enable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
template <typename I, typename ReturnType>
struct disable_if_forward :
boost::disable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
inline std::size_t double_to_size_t(double f)
{
return f >= static_cast<double>(
(std::numeric_limits<std::size_t>::max)()) ?
(std::numeric_limits<std::size_t>::max)() :
static_cast<std::size_t>(f);
}
////////////////////////////////////////////////////////////////////////////
// primes
template<class T> struct prime_list_template
{
static std::size_t const value[];
static std::ptrdiff_t const length;
};
#define BOOST_UNORDERED_PRIMES \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
@@ -70,28 +47,14 @@ namespace boost { namespace unordered { namespace detail {
(50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
(1610612741ul)(3221225473ul)(4294967291ul)
template<class T> struct prime_list_template
{
static std::size_t const value[];
#if !defined(SUNPRO_CC)
static std::ptrdiff_t const length;
#else
static std::ptrdiff_t const length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
};
template<class T>
std::size_t const prime_list_template<T>::value[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
};
#if !defined(SUNPRO_CC)
template<class T>
std::ptrdiff_t const prime_list_template<T>::length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
#undef BOOST_UNORDERED_PRIMES
@@ -121,146 +84,240 @@ namespace boost { namespace unordered { namespace detail {
return *bound;
}
////////////////////////////////////////////////////////////////////////////
// pair_cast - because some libraries don't have the full pair constructors.
template <class Dst1, class Dst2, class Src1, class Src2>
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
{
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
}
////////////////////////////////////////////////////////////////////////////
// insert_size/initial_size
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
template <class I>
inline typename
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
insert_size(I i, I j)
inline std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
{
return std::distance(i, j);
}
template <class I>
inline typename
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
insert_size(I, I)
inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
{
return 1;
}
template <class I>
inline std::size_t initial_size(I i, I j,
std::size_t num_buckets =
boost::unordered::detail::default_bucket_count)
inline std::size_t insert_size(I i, I j)
{
// TODO: Why +1?
return (std::max)(
boost::unordered::detail::insert_size(i, j) + 1,
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
iterator_traversal_tag;
return insert_size(i, j, iterator_traversal_tag);
}
template <class I>
inline std::size_t initial_size(I i, I j,
std::size_t num_buckets = boost::unordered_detail::default_bucket_count)
{
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
num_buckets);
}
////////////////////////////////////////////////////////////////////////////
// compressed
// Node Constructors
template <typename T, int Index>
struct compressed_base : private T
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class T, class... Args>
inline void construct_impl(T*, void* address, Args&&... args)
{
compressed_base(T const& x) : T(x) {}
compressed_base(T& x, move_tag) : T(boost::move(x)) {}
new(address) T(std::forward<Args>(args)...);
}
T& get() { return *this; }
T const& get() const { return *this; }
};
template <typename T, int Index>
struct uncompressed_base
#if defined(BOOST_UNORDERED_CPP0X_PAIR)
template <class First, class Second, class Key, class Arg0, class... Args>
inline void construct_impl(std::pair<First, Second>*, void* address,
Key&& k, Arg0&& arg0, Args&&... args)
)
{
uncompressed_base(T const& x) : value_(x) {}
uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
new(address) std::pair<First, Second>(k,
Second(arg0, std::forward<Args>(args)...);
}
#endif
T& get() { return value_; }
T const& get() const { return value_; }
private:
T value_;
};
template <typename T, int Index>
struct generate_base
: boost::detail::if_true<
boost::is_empty<T>::value
>:: BOOST_NESTED_TEMPLATE then<
boost::unordered::detail::compressed_base<T, Index>,
boost::unordered::detail::uncompressed_base<T, Index>
>
{};
template <typename T1, typename T2>
struct compressed
: private boost::unordered::detail::generate_base<T1, 1>::type,
private boost::unordered::detail::generate_base<T2, 2>::type
#else
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
class T, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
T*, void* address, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
) \
{ \
new(address) T( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
} \
\
template <class First, class Second, class Key, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
std::pair<First, Second>*, void* address, \
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
new(address) std::pair<First, Second>(k, \
Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
#endif
// hash_node_constructor
//
// Used to construct nodes in an exception safe manner.
template <class Alloc, class Grouped>
class hash_node_constructor
{
typedef typename generate_base<T1, 1>::type base1;
typedef typename generate_base<T2, 2>::type base2;
typedef hash_buckets<Alloc, Grouped> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
typedef T1 first_type;
typedef T2 second_type;
first_type& first() {
return static_cast<base1*>(this)->get();
}
buckets& buckets_;
real_node_ptr node_;
bool node_constructed_;
bool value_constructed_;
first_type const& first() const {
return static_cast<base1 const*>(this)->get();
}
public:
second_type& second() {
return static_cast<base2*>(this)->get();
}
second_type const& second() const {
return static_cast<base2 const*>(this)->get();
}
template <typename First, typename Second>
compressed(First const& x1, Second const& x2)
: base1(x1), base2(x2) {}
compressed(compressed const& x)
: base1(x.first()), base2(x.second()) {}
compressed(compressed& x, move_tag m)
: base1(x.first(), m), base2(x.second(), m) {}
void assign(compressed const& x)
hash_node_constructor(buckets& m) :
buckets_(m),
node_(),
node_constructed_(false),
value_constructed_(false)
{
first() = x.first();
second() = x.second();
}
void move_assign(compressed& x)
~hash_node_constructor();
void construct_preamble();
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class... Args>
void construct(Args&&... args)
{
first() = boost::move(x.first());
second() = boost::move(x.second());
construct_preamble();
construct_impl((value_type*) 0, node_->address(),
std::forward<Args>(args)...);
value_constructed_ = true;
}
void swap(compressed& x)
{
boost::swap(first(), x.first());
boost::swap(second(), x.second());
#else
#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _) \
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
void construct( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
) \
{ \
construct_preamble(); \
construct_impl( \
(value_type*) 0, node_->address(), \
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
); \
value_constructed_ = true; \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT, _)
#undef BOOST_UNORDERED_CONSTRUCT
#endif
template <class K, class M>
void construct_pair(K const& k, M*)
{
construct_preamble();
new(node_->address()) value_type(k, M());
value_constructed_ = true;
}
value_type& value() const
{
BOOST_ASSERT(node_);
return node_->value();
}
// no throw
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
{
real_node_ptr p = node_;
node_ = real_node_ptr();
// node_ptr cast
return buckets_.bucket_alloc().address(*p);
}
private:
// Prevent assignment just to make use of assign or
// move_assign explicit.
compressed& operator=(compressed const&);
hash_node_constructor(hash_node_constructor const&);
hash_node_constructor& operator=(hash_node_constructor const&);
};
}}}
// hash_node_constructor
template <class Alloc, class Grouped>
inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
{
if (node_) {
if (value_constructed_) {
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { hash_node<Alloc, Grouped> x; };
#endif
boost::unordered_detail::destroy(&node_->value());
}
if (node_constructed_)
buckets_.node_alloc().destroy(node_);
buckets_.node_alloc().deallocate(node_, 1);
}
}
template <class Alloc, class Grouped>
inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
node_ = buckets_.node_alloc().allocate(1);
buckets_.node_alloc().construct(node_, node());
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_ && value_constructed_);
boost::unordered_detail::destroy(&node_->value());
value_constructed_ = false;
}
}
}}
#endif
File diff suppressed because it is too large Load Diff
+34 -46
View File
@@ -1,65 +1,53 @@
// Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
namespace unordered
{
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K,
class T,
class H = hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
bool operator!=(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>&,
unordered_multimap<K, T, H, P, A>&);
}
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
template <class K,
class T,
class H = hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
void swap(unordered_multimap<K, T, H, P, A>&,
unordered_multimap<K, T, H, P, A>&);
}
#endif
File diff suppressed because it is too large Load Diff
+32 -44
View File
@@ -1,63 +1,51 @@
// Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
namespace unordered
{
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T,
class H = hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T, class H, class P, class A>
bool operator==(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
bool operator!=(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class T, class H, class P, class A>
inline bool operator==(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2);
}
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
template <class T,
class H = hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2);
}
#endif
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_map.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_set.hpp>
-17
View File
@@ -1,17 +0,0 @@
{
"key": "unordered",
"name": "Unordered",
"authors": [
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
]
}
+7 -2
View File
@@ -12,8 +12,13 @@ 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 -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<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
+9 -28
View File
@@ -3,6 +3,8 @@
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -11,7 +13,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
test::seed_t seed(12847);
template <class T>
struct self_assign_base : public test::exception_base
@@ -39,40 +41,26 @@ template <class T>
struct assign_base : public test::exception_base
{
const test::random_values<T> x_values, y_values;
T x,y;
const T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
float mlf1 = 1.0, float mlf2 = 1.0) :
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
x_values(count1),
y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
{}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const { x1 = y; }
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.
T& y = const_cast<T&>(x1);
if (x_values.size()) {
y.emplace(*x_values.begin());
test::check_equivalent_keys(y);
}
}
{ test::check_equivalent_keys(x1); }
};
template <class T>
@@ -99,14 +87,7 @@ struct assign_test4 : assign_base<T>
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
};
template <class T>
struct assign_test5 : assign_base<T>
{
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
(assign_test1)(assign_test2)(assign_test3)(assign_test4),
CONTAINER_SEQ)
RUN_TESTS()
+5 -32
View File
@@ -3,13 +3,13 @@
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/input_iterator.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t initialize_seed(91274);
test::seed_t seed(91274);
struct objects
{
@@ -24,7 +24,6 @@ struct construct_test1 : public objects, test::exception_base
{
void run() const {
T x;
avoid_unused_warning(x);
}
};
@@ -33,7 +32,6 @@ struct construct_test2 : public objects, test::exception_base
{
void run() const {
T x(300);
avoid_unused_warning(x);
}
};
@@ -42,7 +40,6 @@ struct construct_test3 : public objects, test::exception_base
{
void run() const {
T x(0, hash);
avoid_unused_warning(x);
}
};
@@ -51,7 +48,6 @@ struct construct_test4 : public objects, test::exception_base
{
void run() const {
T x(0, hash, equal_to);
avoid_unused_warning(x);
}
};
@@ -60,7 +56,6 @@ struct construct_test5 : public objects, test::exception_base
{
void run() const {
T x(50, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
@@ -69,7 +64,6 @@ struct construct_test6 : public objects, test::exception_base
{
void run() const {
T x(allocator);
avoid_unused_warning(x);
}
};
@@ -87,7 +81,6 @@ struct range_construct_test1 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end());
avoid_unused_warning(x);
}
};
@@ -96,7 +89,6 @@ struct range_construct_test2 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 0);
avoid_unused_warning(x);
}
};
@@ -105,7 +97,6 @@ struct range_construct_test3 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash);
avoid_unused_warning(x);
}
};
@@ -114,7 +105,6 @@ struct range_construct_test4 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
avoid_unused_warning(x);
}
};
@@ -128,7 +118,6 @@ struct range_construct_test5 : public range<T>, objects
void run() const {
T x(this->values.begin(), this->values.end(), 0,
hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
@@ -142,24 +131,10 @@ struct input_range_construct_test : public range<T>, objects
begin = this->values.begin(), end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
template <class T>
struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
void run() const {
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(construct_test1)
(construct_test2)
(construct_test3)
@@ -171,7 +146,5 @@ EXCEPTION_TESTS(
(range_construct_test3)
(range_construct_test4)
(range_construct_test5)
(input_range_construct_test)
(copy_range_construct_test),
(input_range_construct_test),
CONTAINER_SEQ)
RUN_TESTS()
+2 -4
View File
@@ -3,10 +3,8 @@
// 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_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include "../objects/exception.hpp"
typedef boost::unordered_set<
@@ -18,13 +16,13 @@ typedef boost::unordered_multiset<
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator2<test::exception::object> > test_multiset;
test::exception::allocator<test::exception::object> > test_multiset;
typedef boost::unordered_map<
test::exception::object,
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator2<test::exception::object> > test_map;
test::exception::allocator<test::exception::object> > test_map;
typedef boost::unordered_multimap<
test::exception::object,
test::exception::object,
+4 -9
View File
@@ -3,12 +3,12 @@
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t initialize_seed(73041);
test::seed_t seed(73041);
template <class T>
struct copy_test1 : public test::exception_base
@@ -17,7 +17,6 @@ struct copy_test1 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -31,7 +30,6 @@ struct copy_test2 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -45,7 +43,6 @@ struct copy_test3 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -60,11 +57,9 @@ struct copy_with_allocator_test : public test::exception_base
void run() const {
T y(x, allocator);
avoid_unused_warning(y);
}
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
CONTAINER_SEQ)
RUN_TESTS()
+4 -3
View File
@@ -3,12 +3,14 @@
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
test::seed_t initialize_seed(835193);
test::seed_t seed(835193);
template <class T>
struct erase_test_base : public test::exception_base
@@ -49,7 +51,6 @@ struct erase_by_key_test1 : public erase_test_base<T>
}
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(erase_by_key_test1),
CONTAINER_SEQ)
RUN_TESTS()
+13 -12
View File
@@ -3,6 +3,8 @@
// 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 "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -11,7 +13,7 @@
#include <boost/utility.hpp>
#include <cmath>
test::seed_t initialize_seed(747373);
test::seed_t seed(747373);
template <class T>
struct insert_test_base : public test::exception_base
@@ -32,12 +34,12 @@ struct insert_test_base : public test::exception_base
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
strong.test(x, test::exception::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class T>
struct emplace_test1 : public insert_test_base<T>
@@ -49,7 +51,7 @@ struct emplace_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.emplace(*it);
}
}
@@ -67,7 +69,7 @@ struct insert_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(*it);
}
}
@@ -83,7 +85,7 @@ struct insert_test2 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
@@ -111,7 +113,7 @@ struct insert_test4 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
@@ -150,7 +152,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
@@ -174,7 +176,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(*it);
}
@@ -236,12 +238,11 @@ struct insert_test_rehash3 : public insert_test_base<T>
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#define ALL_TESTS (emplace_test1)BASIC_TESTS
#else
#define ALL_TESTS BASIC_TESTS
#endif
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
RUN_TESTS()
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
+5 -3
View File
@@ -3,6 +3,8 @@
// 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 "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -11,7 +13,7 @@
#include <iostream>
test::seed_t initialize_seed(3298597);
test::seed_t seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
@@ -79,7 +81,7 @@ struct rehash_test4 : rehash_test_base<T>
void run(T& x) const { x.rehash(0); }
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
CONTAINER_SEQ)
RUN_TESTS()
+13 -13
View File
@@ -3,6 +3,8 @@
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -11,7 +13,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(9387);
test::seed_t seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
@@ -25,12 +27,13 @@ struct self_swap_base : public test::exception_base
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_TEST(
scope == "hash::hash(hash)" ||
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::check_equivalent_keys(x);
}
@@ -60,9 +63,7 @@ struct swap_base : public test::exception_base
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
key_equal(tag1), allocator_type(tag1)),
initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
key_equal(tag2), allocator_type(
T::allocator_type::propagate_on_container_swap::value ?
tag2 : tag1))
key_equal(tag2), allocator_type(tag2))
{}
struct data_type {
@@ -73,7 +74,6 @@ struct swap_base : public test::exception_base
};
data_type init() const { return data_type(initial_x, initial_y); }
void run(data_type& d) const {
try {
d.x.swap(d.y);
@@ -82,12 +82,13 @@ struct swap_base : public test::exception_base
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_TEST(
scope == "hash::hash(hash)" ||
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
@@ -118,8 +119,7 @@ struct swap_test4 : swap_base<T>
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
};
EXCEPTION_TESTS(
RUN_EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
RUN_TESTS()
+84
View File
@@ -0,0 +1,84 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER
#include <cstddef>
#include <cstdlib>
#include <boost/limits.hpp>
#include <new>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace test
{
template <class T>
struct malloc_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef malloc_allocator<U> other; };
malloc_allocator() {}
template <class Y> malloc_allocator(malloc_allocator<Y> const&) {}
malloc_allocator(malloc_allocator const&) {}
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
pointer allocate(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(T)));
if(!ptr) throw std::bad_alloc();
return ptr;
}
pointer allocate(size_type n, void const* u) { return allocate(n); }
void deallocate(pointer p, size_type) {
using namespace std;
free(p);
}
void construct(pointer p, T const& t) { new(p) T(t); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const&) const { return true; }
bool operator!=(malloc_allocator const&) const { return false; }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void deallocate(T* p, size_type) {
using namespace std;
free(p);
}
char* _Charalloc(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(char)));
if(!ptr) throw std::bad_alloc();
return (char*) ptr;
}
#endif
};
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#endif
+4 -4
View File
@@ -6,7 +6,7 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
#include <boost/static_assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
@@ -18,19 +18,19 @@ namespace test
template <class T2>
static void equals(T2)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
}
template <class T2>
static void convertible(T2)
{
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
}
};
}
+16 -15
View File
@@ -52,28 +52,29 @@ namespace test {
}
};
template <class T>
struct counted_object
{
static object_count count_;
counted_object() { count_.construct(); }
counted_object(counted_object const&) { count_.construct(); }
~counted_object() { count_.destruct(); }
};
template <class T> object_count counted_object<T>::count_;
struct globally_counted_object
: counted_object<globally_counted_object> {};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count global_object_count;
object_count& global_object_count = globally_counted_object::count_;
}
struct counted_object
{
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
struct check_instances {
int instances;
check_instances() : instances(global_object_count.instances) {}
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
};
}
#endif
+8 -23
View File
@@ -20,37 +20,22 @@
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
# define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
UNORDERED_AUTO_TEST(name) \
{ \
for (unsigned i = 0; i < n; ++i) { \
test_func< type > fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
} \
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
#define EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
(test_seq)((1))(param_seq))
#define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
(test_seq)(param_seq)) \
RUN_TESTS() \
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
(test_seq)((n))(param_seq))
#define EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
#define RUN_EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product)) \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product) \
BOOST_PP_SEQ_ELEM(1, product) \
) \
#define UNORDERED_SCOPE(scope_name) \
+1 -91
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2010 Daniel James.
// Copyright 2005-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)
@@ -69,96 +69,6 @@ namespace test
{
return input_iterator_adaptor<Iterator>(it);
}
template <class Iterator>
struct copy_iterator_adaptor
: public boost::iterator<
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type;
copy_iterator_adaptor()
: base_() {}
explicit copy_iterator_adaptor(Iterator const& it)
: base_(it) {}
value_type operator*() const {
return *base_;
}
value_type* operator->() const {
return &*base_;
}
value_type operator[](difference_type d) {
return base_[d];
}
copy_iterator_adaptor& operator++() {
++base_; return *this;
}
copy_iterator_adaptor operator++(int) {
copy_iterator_adaptor tmp(*this); ++base_; return tmp;
}
copy_iterator_adaptor& operator--() {
--base_; return *this;
}
copy_iterator_adaptor operator--(int) {
copy_iterator_adaptor tmp(*this); --base_; return tmp;
}
copy_iterator_adaptor operator+=(difference_type x) {
base_ += x;
return *this;
}
copy_iterator_adaptor operator-=(difference_type x) {
base_ -= x;
return *this;
}
copy_iterator_adaptor operator+(difference_type n) {
return copy_iterator_adaptor(base_+n);
}
copy_iterator_adaptor operator-(difference_type n) {
return copy_iterator_adaptor(base_-n);
}
friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x) {
return x+n;
}
difference_type operator-(copy_iterator_adaptor const& other) {
return base_-other.base_;
}
bool operator==(copy_iterator_adaptor const& x) const {
return base_ == x.base_;
}
bool operator!=(copy_iterator_adaptor const& x) const {
return base_ != x.base_;
}
bool operator<(copy_iterator_adaptor const& x) const {
return base_ < x.base_;
}
bool operator>(copy_iterator_adaptor const& x) const {
return base_ > x.base_;
}
bool operator<=(copy_iterator_adaptor const& x) const {
return base_ <= x.base_;
}
bool operator>=(copy_iterator_adaptor const& x) const {
return base_ >= x.base_;
}
private:
Iterator base_;
};
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
return copy_iterator_adaptor<Iterator>(it);
}
}
#endif
+34 -49
View File
@@ -13,6 +13,7 @@
#include <cmath>
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#include "./allocator.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -28,13 +29,16 @@ namespace test
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
std::set<key_type, std::less<key_type> > found_;
// Boost.Test was reporting memory leaks for std::set on g++-3.3.
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>,
test::malloc_allocator<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while(it != end) {
// First test that the current key has not occurred before, required
// First test that the current key has not occured before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
@@ -61,61 +65,42 @@ namespace test
std::cerr<<x1.count(key)<<","<<count<<"\n";
}
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
BOOST_DEDUCED_TYPENAME X::const_local_iterator
lit = x1.begin(bucket), lend = x1.end(bucket);
for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
if(lit == lend)
BOOST_ERROR("Unable to find element with a local_iterator");
unsigned int count2 = 0;
for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
if(count != count2)
BOOST_ERROR("Element count doesn't match local_iterator.");
for(; lit != lend; ++lit) {
if(eq(get_key<X>(*lit), key)) {
BOOST_ERROR("Non-adjacent element with equivalent key "
"in bucket.");
break;
}
}
// I'm not bothering with the following test for now, as the
// previous test is probably more enough to catch the kind of
// errors that this would catch (if an element was in the wrong
// bucket it not be found by the call to count, if elements are not
// adjacent then they would be caught when checking against
// found_.
// // Check that the keys are in the correct bucket and are
// // adjacent in the bucket.
// BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
// BOOST_DEDUCED_TYPENAME X::const_local_iterator
// lit = x1.begin(bucket), lend = x1.end(bucket);
// for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
// if(lit == lend)
// BOOST_ERROR("Unable to find element with a local_iterator");
// unsigned int count2 = 0;
// for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
// if(count != count2)
// BOOST_ERROR("Element count doesn't match local_iterator.");
// for(; lit != lend; ++lit) {
// if(eq(get_key<X>(*lit), key)) {
// BOOST_ERROR("Non-adjacent element with equivalent key "
// "in bucket.");
// break;
// }
// }
};
// Check that size matches up.
if(x1.size() != size) {
// Finally, check that size matches up.
if(x1.size() != size)
BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout<<x1.size()<<"/"<<size<<std::endl;
}
// Check the load factor.
float load_factor =
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
using namespace std;
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
// Check that size in the buckets matches up.
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
for (BOOST_DEDUCED_TYPENAME X::size_type
i = 0; i < x1.bucket_count(); ++i)
{
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
begin2 = x1.begin(i), end2 = x1.end(i);
begin2 != end2; ++begin2)
{
++bucket_size;
}
}
if(x1.size() != bucket_size) {
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
}
}
}
+4 -4
View File
@@ -94,7 +94,7 @@ namespace test
node* ptr_;
public:
list_iterator() : ptr_(0) {}
list_iterator() : ptr_(0) {};
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
@@ -219,14 +219,14 @@ namespace test
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator i, const_iterator j) {
void erase(const_iterator start, const_iterator end) {
node** ptr = &data_.first_;
while(*ptr != i.ptr_) {
while(*ptr != start.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != j.ptr_) {
while(*ptr != end.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
+29 -19
View File
@@ -8,8 +8,10 @@
#include <memory>
#include <map>
#include <boost/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include "../helpers/test.hpp"
namespace test
@@ -51,10 +53,30 @@ namespace test
}
};
struct memory_tracker {
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> >
> allocated_memory_type;
Alloc> type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_memory_type_gen<int> {
typedef std::map<memory_area, memory_track, memory_area_compare>
type;
};
#endif
template <class Alloc = std::allocator<int> >
struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc,
std::pair<memory_area const, memory_track> >::type
allocator_type;
typedef BOOST_DEDUCED_TYPENAME
allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
@@ -115,9 +137,9 @@ namespace test
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag, bool check_tag_ = true)
int tag)
{
allocated_memory_type::iterator pos =
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
@@ -125,7 +147,7 @@ namespace test
} else {
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
if (check_tag_) BOOST_TEST(pos->second.tag_ == tag);
BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_TEST(count_allocations > 0);
@@ -146,18 +168,6 @@ namespace test
}
};
}
namespace detail
{
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
}
#endif
+48 -9
View File
@@ -8,11 +8,32 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test
{
/*
struct unordered_set_type { char x[100]; };
struct unordered_multiset_type { char x[200]; };
struct unordered_map_type { char x[300]; };
struct unordered_multimap_type { char x[400]; };
template <class V, class H, class P, class A>
unordered_set_type container_type(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
unordered_multiset_type container_type(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_map_type container_type(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_multimap_type container_type(
boost::unordered_multimap<K, M, H, P, A> const*);
*/
template <class Container>
struct is_set
: public boost::is_same<
@@ -20,21 +41,39 @@ namespace test
BOOST_DEDUCED_TYPENAME Container::value_type> {};
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
struct is_map
: public boost::mpl::not_<is_set<Container> > {};
struct yes_type { char x[100]; };
struct no_type { char x[200]; };
template <class V, class H, class P, class A>
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
yes_type has_unique_key_impl(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value = true);
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(yes_type));
};
template <class K, class M, class H, class P, class A>
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
template <class Container>
struct has_equivalent_keys
{
BOOST_STATIC_CONSTANT(bool, value = true);
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
};
}
-10
View File
@@ -1,10 +0,0 @@
// Copyright 2012 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Include this after the boost headers, but before other test headers.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+18 -20
View File
@@ -8,7 +8,7 @@
#include "./list.hpp"
#include <algorithm>
#include <boost/detail/select_type.hpp>
#include <boost/mpl/if.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
@@ -33,15 +33,14 @@ namespace test
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) {
for(std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr);
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(value);
}
}
@@ -65,15 +64,16 @@ namespace test
mapped_type* mapped_ptr = 0;
int* int_ptr = 0;
for (std::size_t i = 0; i < len; ++i) {
for(std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr);
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(
std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
}
}
}
@@ -81,12 +81,10 @@ namespace test
template <class X>
struct unordered_generator_base
: public boost::detail::if_true<
test::is_set<X>::value
>::BOOST_NESTED_TEMPLATE then<
: public boost::mpl::if_<
test::is_set<X>,
test::unordered_generator_set<X>,
test::unordered_generator_map<X>
>
test::unordered_generator_map<X> >
{
};
@@ -106,7 +104,7 @@ namespace test
random_values(int count, test::random_generator const& generator =
test::default_generator)
{
test::unordered_generator<X> gen(generator);
static test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
+1
View File
@@ -8,6 +8,7 @@
#include <boost/config.hpp>
#include <iterator>
#include "./metafunctions.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
+5 -13
View File
@@ -76,29 +76,21 @@ namespace test {
// Run test with every combination of the parameters (a sequence of sequences)
#define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, \
((name))((1)) parameters) \
#define UNORDERED_TEST_REPEAT(name, n, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, \
((name))((n)) parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name)) parameters) \
#define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2( \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product))) \
BOOST_PP_SEQ_HEAD(product), \
BOOST_PP_SEQ_TAIL(product)) \
#define UNORDERED_TEST_OP2(name, n, params) \
#define UNORDERED_TEST_OP2(name, params) \
UNORDERED_AUTO_TEST( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
{ \
for (int i = 0; i < n; ++i) \
name BOOST_PP_SEQ_TO_TUPLE(params); \
name BOOST_PP_SEQ_TO_TUPLE(params); \
} \
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem)) \
#endif
+63 -45
View File
@@ -13,6 +13,9 @@
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
#include "../objects/fwd.hpp"
#include "./metafunctions.hpp"
@@ -22,17 +25,21 @@
namespace test
{
template <typename X>
struct equals_to_compare
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<
std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type>
type;
};
template <>
struct equals_to_compare<test::equal_to>
template <class X>
struct equals_to_compare
: public boost::mpl::eval_if<
boost::is_same<X, test::equal_to>,
boost::mpl::identity<test::less>,
equals_to_compare2<X>
>
{
typedef test::less type;
};
template <class X1, class X2>
@@ -60,40 +67,51 @@ namespace test
values2.begin(), test::equivalent));
}
template <typename X>
struct ordered_base;
template <class X>
struct ordered_set : public
boost::mpl::if_<
test::has_unique_keys<X>,
std::set<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>,
std::multiset<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_set<V, H, P, A> >
{
typedef std::set<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
struct ordered_map : public
boost::mpl::if_<
test::has_unique_keys<X>,
std::map<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>,
std::multimap<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
{
typedef std::map<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
{
typedef std::multimap<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
struct ordered_base : public
boost::mpl::eval_if<
test::is_set<X>,
test::ordered_set<X>,
test::ordered_map<X>
> {};
template <class X>
class ordered : public ordered_base<X>::type
@@ -106,8 +124,8 @@ namespace test
: base()
{}
explicit ordered(key_compare const& kc)
: base(kc)
explicit ordered(key_compare const& compare)
: base(compare)
{}
void compare(X const& x)
@@ -125,10 +143,10 @@ namespace test
}
template <class It>
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
void insert_range(It begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
}
}
};
-317
View File
@@ -1,317 +0,0 @@
// Copyright 2006-2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <cstddef>
#include "../helpers/fwd.hpp"
#include "../helpers/memory.hpp"
namespace test
{
struct allocator_false
{
enum {
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
struct allocator_flags_all
{
enum {
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
struct select_copy : allocator_false
{ enum { is_select_on_copy = 1 }; };
struct propagate_swap : allocator_false
{ enum { is_propagate_on_swap = 1 }; };
struct propagate_assign : allocator_false
{ enum { is_propagate_on_assign = 1 }; };
struct propagate_move : allocator_false
{ enum { is_propagate_on_move = 1 }; };
struct no_select_copy : allocator_flags_all
{ enum { is_select_on_copy = 0 }; };
struct no_propagate_swap : allocator_flags_all
{ enum { is_propagate_on_swap = 0 }; };
struct no_propagate_assign : allocator_flags_all
{ enum { is_propagate_on_assign = 0 }; };
struct no_propagate_move : allocator_flags_all
{ enum { is_propagate_on_move = 0 }; };
template <typename Flag>
struct swap_allocator_base
{
struct propagate_on_container_swap {
enum { value = Flag::is_propagate_on_swap }; };
};
template <typename Flag>
struct assign_allocator_base
{
struct propagate_on_container_copy_assignment {
enum { value = Flag::is_propagate_on_assign }; };
};
template <typename Flag>
struct move_allocator_base
{
struct propagate_on_container_move_assignment {
enum { value = Flag::is_propagate_on_move }; };
};
namespace
{
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
struct force_equal_allocator
{
bool old_value_;
explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value)
{ force_equal_allocator_value = value; }
~force_equal_allocator()
{ force_equal_allocator_value = old_value_; }
};
template <typename T>
struct cxx11_allocator_base
{
int tag_;
int selected_;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
explicit cxx11_allocator_base(int t)
: tag_(t), selected_(0)
{
detail::tracker.allocator_ref();
}
template <typename Y> cxx11_allocator_base(
cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
}
~cxx11_allocator_base()
{
detail::tracker.allocator_unref();
}
pointer address(reference r)
{
return pointer(&r);
}
const_pointer address(const_reference r)
{
return const_pointer(&r);
}
pointer allocate(size_type n) {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
pointer allocate(size_type n, void const* u)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_,
!force_equal_allocator_value);
::operator delete((void*) p);
}
void construct(T* p, T const& t) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
};
template <typename T, typename Flags = propagate_swap,
typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<
T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
{
}
template <typename Y> cxx11_allocator(
cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
{
}
cxx11_allocator(cxx11_allocator const& x)
: cxx11_allocator_base<T>(x)
{
}
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const
{
return !(*this == x);
}
};
template <typename T, typename Flags>
struct cxx11_allocator<
T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
cxx11_allocator select_on_container_copy_construction() const
{
cxx11_allocator tmp(*this);
++tmp.selected_;
return tmp;
}
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
{
}
template <typename Y> cxx11_allocator(
cxx11_allocator<Y, Flags> const& x)
: cxx11_allocator_base<T>(x)
{
}
cxx11_allocator(cxx11_allocator const& x)
: cxx11_allocator_base<T>(x)
{
}
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const
{
return !(*this == x);
}
};
template <typename T, typename Flags>
bool equivalent_impl(
cxx11_allocator<T, Flags> const& x,
cxx11_allocator<T, Flags> const& y,
test::derived_type)
{
return x.tag_ == y.tag_;
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
inline int selected_count(convert_from_anything)
{
return 0;
}
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
return x.selected_;
}
}
#endif
+25 -210
View File
@@ -13,28 +13,27 @@
#include <boost/limits.hpp>
#include <new>
#include "../helpers/fwd.hpp"
#include "../helpers/allocator.hpp"
#include "../helpers/memory.hpp"
namespace test
{
namespace exception
{
namespace detail
{
namespace
{
test::detail::memory_tracker<test::malloc_allocator<int> > tracker;
}
}
class object;
class hash;
class equal_to;
template <class T> class allocator;
object generate(object const*);
struct true_type
{
enum { value = true };
};
struct false_type
{
enum { value = false };
};
class object
{
public:
@@ -250,7 +249,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator default constructor.");
}
test::detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
@@ -258,7 +257,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator template copy constructor.");
}
test::detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
allocator(allocator const& x) : tag_(x.tag_)
@@ -266,11 +265,11 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator copy constructor.");
}
test::detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
~allocator() {
test::detail::tracker.allocator_unref();
detail::tracker.allocator_unref();
}
allocator& operator=(allocator const& x) {
@@ -308,7 +307,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -324,7 +323,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -334,32 +333,32 @@ namespace exception
{
//::operator delete((void*) p);
if(p) {
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std;
free(p);
}
}
void construct(pointer p, T const& t) {
UNORDERED_SCOPE(allocator::construct(T*, T)) {
UNORDERED_SCOPE(allocator::construct(pointer, T)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(t);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(boost::forward<Args>(args)...);
new(p) T(std::forward<Args>(args)...);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(T* p) {
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
void destroy(pointer p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
@@ -369,10 +368,6 @@ namespace exception
}
return (std::numeric_limits<std::size_t>::max)();
}
typedef true_type propagate_on_container_copy_assignment;
typedef true_type propagate_on_container_move_assignment;
typedef true_type propagate_on_container_swap;
};
template <class T>
@@ -401,186 +396,6 @@ namespace exception
//}
return x.tag_ != y.tag_;
}
template <class T>
class allocator2
{
public:
int tag_;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator2<U> other; };
explicit allocator2(int t = 0) : tag_(t)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 default constructor.");
}
test::detail::tracker.allocator_ref();
}
allocator2(allocator<T> const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
}
test::detail::tracker.allocator_ref();
}
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
}
test::detail::tracker.allocator_ref();
}
allocator2(allocator2 const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 copy constructor.");
}
test::detail::tracker.allocator_ref();
}
~allocator2() {
test::detail::tracker.allocator_unref();
}
allocator2& operator=(allocator2 const& x) {
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 assignment operator.");
tag_ = x.tag_;
}
return *this;
}
// If address throws, then it can't be used in erase or the
// destructor, which is very limiting. I need to check up on
// this.
pointer address(reference r) {
//UNORDERED_SCOPE(allocator2::address(reference)) {
// UNORDERED_EPOINT("Mock allocator2 address function.");
//}
return pointer(&r);
}
const_pointer address(const_reference r) {
//UNORDERED_SCOPE(allocator2::address(const_reference)) {
// UNORDERED_EPOINT("Mock allocator2 const address function.");
//}
return const_pointer(&r);
}
pointer allocate(size_type n) {
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type)) {
UNORDERED_EPOINT("Mock allocator2 allocate function.");
using namespace std;
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const* u)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
UNORDERED_EPOINT("Mock allocator2 allocate function.");
using namespace std;
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
void deallocate(pointer p, size_type n)
{
//::operator delete((void*) p);
if(p) {
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std;
free(p);
}
}
void construct(pointer p, T const& t) {
UNORDERED_SCOPE(allocator2::construct(T*, T)) {
UNORDERED_EPOINT("Mock allocator2 construct function.");
new(p) T(t);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
UNORDERED_EPOINT("Mock allocator2 construct function.");
new(p) T(boost::forward<Args>(args)...);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(T* p) {
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const {
UNORDERED_SCOPE(allocator2::construct(pointer, T)) {
UNORDERED_EPOINT("Mock allocator2 max_size function.");
}
return (std::numeric_limits<std::size_t>::max)();
}
typedef false_type propagate_on_container_copy_assignment;
typedef false_type propagate_on_container_move_assignment;
typedef false_type propagate_on_container_swap;
};
template <class T>
void swap(allocator2<T>& x, allocator2<T>& y)
{
std::swap(x.tag_, y.tag_);
}
// It's pretty much impossible to write a compliant swap when these
// two can throw. So they don't.
template <class T>
inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
{
//UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
// UNORDERED_EPOINT("Mock allocator2 equality operator.");
//}
return x.tag_ == y.tag_;
}
template <class T>
inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
{
//UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
// UNORDERED_EPOINT("Mock allocator2 inequality operator.");
//}
return x.tag_ != y.tag_;
}
}
}
+38 -241
View File
@@ -11,64 +11,33 @@
#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
#include <cstddef>
#include <boost/move/move.hpp>
#include <utility>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test
{
namespace minimal
{
class destructible;
class copy_constructible;
class copy_constructible_equality_comparable;
class default_assignable;
class default_copy_constructible;
class assignable;
struct ampersand_operator_used {
ampersand_operator_used() { BOOST_TEST(false); }
};
template <class T> class hash;
template <class T> class equal_to;
template <class T> class ptr;
template <class T> class const_ptr;
template <class T> class allocator;
template <class T> class cxx11_allocator;
struct constructor_param
{
operator int() const { return 0; }
};
class destructible
{
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
};
class copy_constructible
{
public:
copy_constructible(constructor_param const&) {}
static copy_constructible create() { return copy_constructible(); }
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
@@ -77,7 +46,9 @@ namespace minimal
class copy_constructible_equality_comparable
{
public:
copy_constructible_equality_comparable(constructor_param const&) {}
static copy_constructible_equality_comparable create() {
return copy_constructible_equality_comparable();
}
copy_constructible_equality_comparable(
copy_constructible_equality_comparable const&)
@@ -88,15 +59,10 @@ 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
};
bool operator==(
@@ -113,185 +79,81 @@ namespace minimal
return false;
}
class default_assignable
class default_copy_constructible
{
public:
default_assignable(constructor_param const&) {}
static default_copy_constructible create()
{
return default_copy_constructible();
}
default_assignable()
default_copy_constructible()
{
}
default_assignable(default_assignable const&)
default_copy_constructible(default_copy_constructible const&)
{
}
default_assignable& operator=(default_assignable const&)
{
return *this;
}
~default_assignable()
~default_copy_constructible()
{
}
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
default_copy_constructible& operator=(
default_copy_constructible const&);
};
class assignable
{
public:
assignable(constructor_param const&) {}
static assignable create() { return assignable(); }
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
};
struct movable_init {};
class movable1
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1)
public:
movable1(constructor_param const&) {}
movable1() {}
explicit movable1(movable_init) {}
movable1(BOOST_RV_REF(movable1)) {}
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
~movable1() {}
void dummy_member() const {}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
class movable2
{
public:
movable2(constructor_param const&) {}
explicit movable2(movable_init) {}
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
private:
movable2() {}
movable2(movable2 const&);
movable2& operator=(movable2 const&);
};
#else
typedef movable1 movable2;
#endif
template <class T>
class hash
{
public:
hash(constructor_param const&) {}
static hash create() { return hash<T>(); }
hash() {}
hash(hash const&) {}
hash& operator=(hash const&) { return *this; }
~hash() {}
std::size_t operator()(T const&) const { return 0; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
class equal_to
{
public:
equal_to(constructor_param const&) {}
static equal_to create() { return equal_to<T>(); }
equal_to() {}
equal_to(equal_to const&) {}
equal_to& operator=(equal_to const&) { return *this; }
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T> class ptr;
template <class T> class const_ptr;
struct void_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class ptr;
private:
#endif
void* ptr_;
public:
void_ptr() : ptr_(0) {}
template <typename T>
explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
};
class void_const_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class const_ptr;
private:
#endif
void* ptr_;
public:
void_const_ptr() : ptr_(0) {}
template <typename T>
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
};
template <class T>
class ptr
{
friend class allocator<T>;
friend class const_ptr<T>;
friend struct void_ptr;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
@@ -313,17 +175,19 @@ 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
bool operator==(const_ptr<T> const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr<T> const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr<T> const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr<T> const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr<T> const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr<T> const& x) const { return ptr_ >= x.ptr_; }
};
template <class T>
class const_ptr
{
friend class allocator<T>;
friend struct const_void_ptr;
T const* ptr_;
@@ -331,7 +195,6 @@ namespace minimal
public:
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
@@ -345,16 +208,19 @@ namespace minimal
bool operator!() const { return !ptr_; }
operator bool() const { return !!ptr_; }
bool operator==(ptr<T> const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr<T> const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr<T> const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr<T> const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr<T> const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr<T> const& x) const { return ptr_ >= x.ptr_; }
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -363,8 +229,6 @@ namespace minimal
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
@@ -396,15 +260,15 @@ namespace minimal
::operator delete((void*) p.ptr_);
}
void construct(T* p, T const& t) { new((void*)p) T(t); }
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
new((void*)p.ptr_) T(std::forward<Args>(args)...);
}
#endif
void destroy(T* p) { p->~T(); }
void destroy(pointer p) { ((T*)p.ptr_)->~T(); }
size_type max_size() const { return 1000; }
@@ -413,10 +277,6 @@ namespace minimal
public: allocator& operator=(allocator const&) { return *this;}
#else
private: allocator& operator=(allocator const&);
#endif
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
@@ -436,69 +296,6 @@ namespace minimal
void swap(allocator<T>&, allocator<T>&)
{
}
// C++11 allocator
//
// Not a fully minimal C++11 allocator, just what I support. Hopefully will
// cut down further in the future.
template <class T>
class cxx11_allocator
{
public:
typedef T value_type;
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
cxx11_allocator(cxx11_allocator const&) {}
~cxx11_allocator() {}
T* address(T& r) { return &r; }
T const* address(T const& r) { return &r; }
T* allocate(std::size_t n) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
template <class Y>
T* allocate(std::size_t n, const_ptr<Y> u) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
void deallocate(T* p, std::size_t) {
::operator delete((void*) p);
}
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p) { p->~T(); }
std::size_t max_size() const { return 1000u; }
};
template <class T>
inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
{
return true;
}
template <class T>
inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
{
return false;
}
template <class T>
void swap(cxx11_allocator<T>&, cxx11_allocator<T>&)
{
}
}
}
+72 -393
View File
@@ -9,29 +9,24 @@
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <cstddef>
#include <iostream>
#include "../helpers/fwd.hpp"
#include "../helpers/count.hpp"
#include "../helpers/memory.hpp"
#include <map>
namespace test
{
// Note that the default hash function will work for any equal_to (but not
// very well).
class object;
class movable;
class implicitly_convertible;
class hash;
class less;
class equal_to;
template <class T> class allocator1;
template <class T> class allocator2;
template <class T> class allocator;
object generate(object const*);
movable generate(movable const*);
implicitly_convertible generate(implicitly_convertible const*);
inline void ignore_variable(void const*) {}
class object : private counted_object
class object : globally_counted_object
{
friend class hash;
friend class equal_to;
@@ -69,112 +64,6 @@ namespace test
}
};
class movable : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
int tag1_, tag2_;
BOOST_COPYABLE_AND_MOVABLE(movable)
public:
explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
movable(movable const& x) :
counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
}
movable(BOOST_RV_REF(movable) x) :
counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
x.tag1_ = -1;
x.tag2_ = -1;
}
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
return *this;
}
movable& operator=(BOOST_RV_REF(movable) x) //Move assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
x.tag1_ = -1;
x.tag2_ = -1;
return *this;
}
~movable() {
tag1_ = -1;
tag2_ = -1;
}
friend bool operator==(movable const& x1, movable const& x2) {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
friend bool operator!=(movable const& x1, movable const& x2) {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend bool operator<(movable const& x1, movable const& x2) {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend movable generate(movable const*) {
int* x = 0;
return movable(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, movable const& o)
{
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
}
};
class implicitly_convertible : private counted_object
{
int tag1_, tag2_;
public:
explicit implicitly_convertible(int t1 = 0, int t2 = 0)
: tag1_(t1), tag2_(t2)
{}
operator object() const
{
return object(tag1_, tag2_);
}
operator movable() const
{
return movable(tag1_, tag2_);
}
friend implicitly_convertible generate(implicitly_convertible const*) {
int* x = 0;
return implicitly_convertible(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, implicitly_convertible const& o)
{
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
}
};
// Note: This is a deliberately bad hash function.
class hash
{
int type_;
@@ -192,17 +81,6 @@ namespace test
}
}
std::size_t operator()(movable const& x) const {
switch(type_) {
case 1:
return x.tag1_;
case 2:
return x.tag2_;
default:
return x.tag1_ + x.tag2_;
}
}
std::size_t operator()(int x) const {
return x;
}
@@ -220,10 +98,6 @@ namespace test
return hash()(x);
}
std::size_t hash_value(test::movable const& x) {
return hash()(x);
}
class less
{
int type_;
@@ -241,17 +115,6 @@ namespace test
}
}
bool operator()(movable const& x1, movable const& x2) const {
switch(type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 < x2;
}
@@ -278,17 +141,6 @@ namespace test
}
}
bool operator()(movable const& x1, movable const& x2) const {
switch(type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 == x2;
}
@@ -306,253 +158,56 @@ namespace test
}
};
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class.
namespace detail
{
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker<std::allocator<int> > tracker;
}
}
template <class T>
class allocator1
{
public:
int tag_;
typedef T value_type;
template <class U> struct rebind { typedef allocator1<U> other; };
explicit allocator1(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator1(allocator1<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator1(allocator1 const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator1()
{
detail::tracker.allocator_unref();
}
T* allocate(std::size_t n) {
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
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_);
return ptr;
}
void deallocate(T* p, std::size_t n)
{
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
::operator delete((void*) p);
}
void construct(T* p, T const& t) {
// Don't count constructions here as it isn't always called.
//detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
void destroy(T* p) {
//detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
// Work around MSVC buggy unused parameter warning.
ignore_variable(&p);
}
bool operator==(allocator1 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator1 const& x) const
{
return tag_ != x.tag_;
}
enum {
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
template <class T> class ptr;
template <class T> class const_ptr;
struct void_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class ptr;
private:
#endif
void* ptr_;
public:
void_ptr() : ptr_(0) {}
template <typename T>
explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
};
class void_const_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class const_ptr;
private:
#endif
void* ptr_;
public:
void_const_ptr() : ptr_(0) {}
template <typename T>
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
};
template <class T>
class ptr
{
friend class allocator2<T>;
friend class const_ptr<T>;
friend struct void_ptr;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
ptr& operator++() { ++ptr_; return *this; }
ptr operator++(int) { ptr tmp(*this); ++ptr_; return tmp; }
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p)
{ return ptr<T>(s + p.ptr_); }
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!ptr_; }
bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
};
template <class T>
class const_ptr
{
friend class allocator2<T>;
friend struct const_void_ptr;
T const* ptr_;
const_ptr(T const* ptr) : ptr_(ptr) {}
public:
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
const_ptr& operator++() { ++ptr_; return *this; }
const_ptr operator++(int) { const_ptr tmp(*this); ++ptr_; return tmp; }
const_ptr operator+(std::ptrdiff_t s) const
{ return const_ptr(ptr_ + s); }
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
{ return ptr<T>(s + p.ptr_); }
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
operator bool() const { return !!ptr_; }
bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
};
template <class T>
class allocator2
class allocator
{
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
# else
template <class> friend class allocator2;
template <class> friend class allocator;
# endif
int tag_;
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator2<U> other; };
template <class U> struct rebind { typedef allocator<U> other; };
explicit allocator2(int t = 0) : tag_(t)
explicit allocator(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator2(allocator2<Y> const& x)
template <class Y> allocator(allocator<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator2(allocator2 const& x)
allocator(allocator const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator2()
~allocator()
{
detail::tracker.allocator_unref();
}
@@ -568,9 +223,9 @@ namespace test
}
pointer allocate(size_type n) {
pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) p.ptr_, n, sizeof(T), tag_);
return p;
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
pointer allocate(size_type n, void const* u)
@@ -582,23 +237,23 @@ namespace test
void deallocate(pointer p, size_type n)
{
detail::tracker.track_deallocate((void*) p.ptr_, n, sizeof(T), tag_);
::operator delete((void*) p.ptr_);
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
::operator delete((void*) p);
}
void construct(T* p, T const& t) {
void construct(pointer p, T const& t) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(boost::forward<Args>(args)...);
new(p) T(std::forward<Args>(args)...);
}
#endif
void destroy(T* p) {
void destroy(pointer p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
@@ -607,37 +262,61 @@ namespace test
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator2 const& x) const
bool operator==(allocator const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator2 const& x) const
bool operator!=(allocator const& x) const
{
return tag_ != x.tag_;
}
enum {
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
template <class T>
bool equivalent_impl(allocator1<T> const& x, allocator1<T> const& y,
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y,
test::derived_type)
{
return x == y;
}
#if BOOST_WORKAROUND(__GNUC__, < 3)
void swap(test::object& x, test::object& y) {
test::object tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::hash& x, test::hash& y) {
test::hash tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::less& x, test::less& y) {
test::less tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::equal_to& x, test::equal_to& y) {
test::equal_to tmp;
tmp = x;
x = y;
y = tmp;
}
template <class T>
bool equivalent_impl(allocator2<T> const& x, allocator2<T> const& y,
test::derived_type)
{
return x == y;
void swap(test::allocator<T>& x, test::allocator<T>& y) {
test::allocator<T> tmp;
tmp = x;
x = y;
y = tmp;
}
#endif
}
#endif
+9 -25
View File
@@ -9,28 +9,28 @@ 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 -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<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
:
[ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ]
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run noexcept_tests.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
[ run copy_tests.cpp ]
[ run move_tests.cpp ]
[ run move_tests.cpp : : : <test-info>always_show_run_output ]
[ run assign_tests.cpp ]
[ run insert_tests.cpp ]
[ run insert_stable_tests.cpp ]
@@ -43,21 +43,5 @@ test-suite unordered
[ 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 ]
[ run swap_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
-254
View File
@@ -1,254 +0,0 @@
// Copyright 2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/limits.hpp>
// Boilerplate
#define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r;} \
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
T* allocate(std::size_t n, void const* u) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
void deallocate(T* p, std::size_t n) { ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
{ return (std::numeric_limits<std::size_t>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
#define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r;} \
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ return pointer(::operator new(n * sizeof(T))); } \
pointer allocate(std::size_t n, void const* u) \
{ return pointer(::operator new(n * sizeof(T))); } \
void deallocate(pointer p, std::size_t n) \
{ ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
size_type max_size() const \
{ return (std::numeric_limits<size_type>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
struct yes_type { enum { value = true }; };
struct no_type { enum { value = false }; };
// For tracking calls...
static int selected;
void reset() {
selected = 0;
}
template <typename Allocator>
int call_select()
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected;
}
// Empty allocator test
template <typename T>
struct empty_allocator
{
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
};
void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 0);
}
// allocator 1
template <typename T>
struct allocator1
{
typedef T value_type;
ALLOCATOR_METHODS(allocator1)
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
allocator1<T> select_on_container_copy_construction() const {
++selected;
return allocator1<T>();
}
};
void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 2
template <typename Alloc>
struct allocator2_base
{
Alloc select_on_container_copy_construction() const {
++selected;
return Alloc();
}
};
template <typename T>
struct allocator2 : allocator2_base<allocator2<T> >
{
typedef T value_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::size_t size_type;
ALLOCATOR_METHODS(allocator2)
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
};
void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 3
template <typename T>
struct ptr
{
T* value_;
ptr(void* v) : value_((T*) v) {}
T& operator*() const { return *value_; }
};
template <>
struct ptr<void>
{
void* value_;
ptr(void* v) : value_(v) {}
};
template <>
struct ptr<const void>
{
void const* value_;
ptr(void const* v) : value_(v) {}
};
template <typename T>
struct allocator3
{
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
allocator3<T> select_on_container_copy_construction() const {
++selected;
return allocator3<T>();
}
};
void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
}
int main()
{
test_empty_allocator();
test_allocator1();
test_allocator2();
test_allocator3();
return boost::report_errors();
}
+21 -171
View File
@@ -4,36 +4,30 @@
// 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 "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include <iostream>
#if defined(BOOST_MSVC)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace assign_tests {
test::seed_t initialize_seed(96785);
test::seed_t seed(96785);
template <class T>
void assign_tests1(T*, test::random_generator generator)
void assign_tests1(T*,
test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
std::cerr<<"assign_tests1.1\n";
{
test::check_instances check_;
T x;
x = x;
BOOST_TEST(x.empty());
@@ -43,8 +37,6 @@ void assign_tests1(T*, test::random_generator generator)
std::cerr<<"assign_tests1.2\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
@@ -56,18 +48,15 @@ void assign_tests1(T*, test::random_generator generator)
T y;
y.max_load_factor(x.max_load_factor() / 20);
float mlf = x.max_load_factor();
y = x;
tracker.compare(x);
tracker.compare(y);
BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf);
BOOST_TEST(y.load_factor() <= y.max_load_factor());
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
}
}
template <class T>
void assign_tests2(T*, test::random_generator generator)
void assign_tests2(T*,
test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
@@ -75,199 +64,58 @@ void assign_tests2(T*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
std::cerr<<"assign_tests2.1\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, v);
test::check_container(x2, v);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr<<"assign_tests2.1a\n";
{
test::check_instances check_;
test::random_values<T> v1(0, generator);
test::random_values<T> v2(1000, generator);
T x1(0, hf2, eq2);
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr<<"assign_tests2.2\n";
{
test::check_instances check_;
test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr<<"assign_tests2.3\n";
{
test::check_instances check_;
test::random_values<T> v1(100, generator), v2(1000, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr<<"assign_tests2.4\n";
{
test::check_instances check_;
test::random_values<T> v1(1000, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
}
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multiset_prop_assign;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multimap_prop_assign;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multiset_no_prop_assign;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
template <typename T>
bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
UNORDERED_AUTO_TEST(check_traits)
{
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
}
UNORDERED_TEST(assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
UNORDERED_TEST(assign_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(assign_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
UNORDERED_TEST(assign_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -282,7 +130,9 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
+1 -12
View File
@@ -4,40 +4,29 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include <string>
namespace at_tests {
UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
x["one"] = 1;
x["two"] = 2;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl;
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
try {
x.at("three");
BOOST_ERROR("Should have thrown.");
}
catch(std::out_of_range) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
+8 -21
View File
@@ -4,10 +4,9 @@
// 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 <algorithm>
#include "../objects/test.hpp"
@@ -21,13 +20,11 @@
namespace bucket_tests {
test::seed_t initialize_seed(54635);
test::seed_t seed(54635);
template <class X>
void tests(X*, test::random_generator generator)
void tests(X* = 0, test::random_generator generator = test::default_generator)
{
test::check_instances check_;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
test::random_values<X> v(1000, generator);
@@ -68,30 +65,20 @@ void tests(X*, test::random_generator generator)
}
}
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(tests,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(test_multimap)))
}
+39 -95
View File
@@ -7,8 +7,8 @@
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <iostream>
#include "../helpers/test.hpp"
@@ -17,120 +17,82 @@
// Explicit instantiation to catch compile-time errors
template class boost::unordered_map<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_multimap<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::default_copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const,
test::minimal::assignable> value_type;
value_type value(x, x);
test::minimal::copy_constructible> value_type;
value_type value(
test::minimal::assignable::create(),
test::minimal::copy_constructible::create());
std::cout<<"Test unordered_map.\n";
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
}
UNORDERED_AUTO_TEST(equality_tests) {
typedef std::pair<
test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable> value_type;
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> value_type;
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > map;
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
@@ -144,90 +106,72 @@ UNORDERED_AUTO_TEST(test1) {
boost::unordered_map<int, int> map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> map2;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> multimap2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
unordered_test(multimap, value, map_value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
test::minimal::assignable assignable
= test::minimal::assignable::create();
test::minimal::copy_constructible copy_constructible
= test::minimal::copy_constructible::create();
test::minimal::hash<test::minimal::assignable> hash
= test::minimal::hash<test::minimal::assignable>::create();
test::minimal::equal_to<test::minimal::assignable> equal_to
= test::minimal::equal_to<test::minimal::assignable>::create();
typedef std::pair<test::minimal::assignable const,
test::minimal::assignable> map_value_type;
map_value_type map_value(assignable, assignable);
test::minimal::copy_constructible> map_value_type;
map_value_type map_value(assignable, copy_constructible);
std::cout<<"Test unordered_map.\n";
boost::unordered_map<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > map;
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
unordered_map_test(map, assignable, copy_constructible);
unordered_test(map, assignable, map_value, hash, equal_to);
boost::unordered_map<
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::default_copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > map2;
test::minimal::default_assignable default_assignable;
test::minimal::default_copy_constructible default_copy_constructible;
unordered_map_functions(map2, assignable, default_assignable);
unordered_map_functions(map2, assignable, default_copy_constructible);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
unordered_map_test(multimap, assignable, copy_constructible);
unordered_test(multimap, assignable, map_value, hash, equal_to);
}
RUN_TESTS()
+23 -175
View File
@@ -7,8 +7,8 @@
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <iostream>
#include "../helpers/test.hpp"
@@ -17,17 +17,6 @@
// Explicit instantiation to catch compile-time errors
template class boost::unordered_set<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_multiset<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@@ -41,19 +30,10 @@ template class boost::unordered_multiset<
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::assignable assignable = test::minimal::assignable::create();
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> int_set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@@ -61,18 +41,10 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<test::minimal::assignable> > set;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@@ -80,45 +52,32 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<test::minimal::assignable> > multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(equality_tests) {
typedef test::minimal::copy_constructible_equality_comparable value_type;
typedef test::minimal::assignable value_type;
boost::unordered_set<int> int_set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > set;
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
}
@@ -128,49 +87,33 @@ UNORDERED_AUTO_TEST(test1)
std::equal_to<int> equal_to;
int value = 0;
std::cout<<"Test unordered_set." << std::endl;
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> set2;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_test(set, value, value, hash, equal_to);
unordered_unique_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
std::cout<<"Test unordered_multiset." << std::endl;
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> multiset2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
unordered_test(multiset, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
test::minimal::assignable assignable
= test::minimal::assignable::create();
test::minimal::copy_constructible copy_constructible
= test::minimal::copy_constructible::create();
test::minimal::hash<test::minimal::assignable> hash
= test::minimal::hash<test::minimal::assignable>::create();
test::minimal::equal_to<test::minimal::assignable> equal_to
= test::minimal::equal_to<test::minimal::assignable>::create();
std::cout<<"Test unordered_set.\n";
@@ -182,8 +125,7 @@ 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);
unordered_test(set, assignable, assignable, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
@@ -195,101 +137,7 @@ 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)
{
test::minimal::constructor_param x;
test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
std::cout<<"Test unordered_set.\n";
boost::unordered_set<
test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> > set;
//unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<
test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> > multiset;
//unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
}
UNORDERED_AUTO_TEST(movable2_tests)
{
test::minimal::constructor_param x;
test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
std::cout<<"Test unordered_set.\n";
boost::unordered_set<
test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> > set;
//unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<
test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> > multiset;
//unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
}
UNORDERED_AUTO_TEST(destructible_tests)
{
test::minimal::constructor_param x;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
std::cout<<"Test unordered_set.\n";
boost::unordered_set<
test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> > set;
unordered_destructible_test(set);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<
test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> > multiset;
unordered_destructible_test(multiset);
unordered_test(multiset, assignable, assignable, hash, equal_to);
}
RUN_TESTS()
+79 -277
View File
@@ -16,19 +16,18 @@
#pragma warning(pop)
#endif
#include <boost/static_assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/limits.hpp>
#include <boost/utility/swap.hpp>
#include "../helpers/check_return_type.hpp"
typedef long double comparison_type;
template <class T> void sink(T const&) {}
template <class T> T rvalue(T const& v) { return v; }
template <class T> T rvalue_default() { return T(); }
template <class X, class T>
void container_test(X& r, T const&)
@@ -54,38 +53,42 @@ void container_test(X& r, T const&)
// value_type
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
BOOST_MPL_ASSERT((boost::is_same<T, value_type>));
boost::function_requires<boost::CopyConstructibleConcept<X> >();
// reference_type / const_reference_type
BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
BOOST_MPL_ASSERT((boost::is_same<T&, reference>));
BOOST_MPL_ASSERT((boost::is_same<T const&, const_reference>));
// iterator
boost::function_requires<boost::InputIteratorConcept<iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
BOOST_MPL_ASSERT((boost::is_same<T, iterator_value_type>));
BOOST_MPL_ASSERT((boost::is_convertible<iterator, const_iterator>));
// const_iterator
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
BOOST_MPL_ASSERT((boost::is_same<T, const_iterator_value_type>));
// difference_type
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
iterator_difference_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>::value));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_integer>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
iterator_difference_type>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>));
// size_type
BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer);
BOOST_MPL_ASSERT_NOT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_integer>));
// size_type can represent any non-negative value type of difference_type
// I'm not sure about either of these tests...
@@ -106,50 +109,15 @@ void container_test(X& r, T const&)
BOOST_TEST(X().size() == 0);
X a,b;
X a_const;
sink(X(a));
X u2(a);
X u3 = a;
a.swap(b);
boost::swap(a, b);
test::check_return_type<X>::equals_ref(r = a);
// Allocator
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
// Avoid unused variable warnings:
sink(u);
sink(u2);
sink(u3);
}
template <class X>
void unordered_destructible_test(X&)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
X x1;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x2(rvalue_default<X>());
X x3 = rvalue_default<X>();
// This can only be done if propagate_on_container_move_assignment::value
// is true.
// x2 = rvalue_default<X>();
#endif
X* ptr = new X();
X& a1 = *ptr;
(&a1)->~X();
X a,b;
X const a_const;
test::check_return_type<iterator>::equals(a.begin());
test::check_return_type<const_iterator>::equals(a_const.begin());
@@ -161,8 +129,7 @@ void unordered_destructible_test(X&)
test::check_return_type<const_iterator>::equals(a_const.cend());
a.swap(b);
boost::swap(a, b);
test::check_return_type<X>::equals_ref(r = a);
test::check_return_type<size_type>::equals(a.size());
test::check_return_type<size_type>::equals(a.max_size());
test::check_return_type<bool>::convertible(a.empty());
@@ -179,29 +146,7 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
BOOST_MPL_ASSERT((boost::is_same<value_type, key_type>));
}
template <class X, class Key, class T>
@@ -209,33 +154,8 @@ void unordered_map_test(X& r, Key const& k, T const& v)
{
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
// Calling functions
BOOST_MPL_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >));
r.insert(std::pair<Key const, T>(k, v));
@@ -254,8 +174,6 @@ void equality_test(X& r)
test::check_return_type<bool>::equals(a == b);
test::check_return_type<bool>::equals(a != b);
test::check_return_type<bool>::equals(boost::operator==(a, b));
test::check_return_type<bool>::equals(boost::operator!=(a, b));
}
template <class X, class T>
@@ -287,11 +205,9 @@ void unordered_map_functions(X&, Key const& k, T const&)
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
}
template <class X, class Key, class Hash, class Pred>
void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
template <class X, class Key, class T, class Hash, class Pred>
void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
{
unordered_destructible_test(x);
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
@@ -354,36 +270,36 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
//boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
test::check_return_type<std::size_t>::equals(hf(k));
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
BOOST_MPL_ASSERT((boost::is_same<Pred, key_equal>));
test::check_return_type<bool>::convertible(eq(k, k));
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_category,
iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>::value));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_category,
iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>));
boost::function_requires<
boost::InputIteratorConcept<const_local_iterator> >();
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>));
X(10, hf, eq);
X a(10, hf, eq);
@@ -394,18 +310,45 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
X();
X a4;
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
X a6(i, j, 10, hf);
X(i, j, 10);
X a7(i, j, 10);
X(i, j);
X a8(i, j);
X const b;
sink(X(b));
X a9(b);
a = b;
test::check_return_type<hasher>::equals(b.hash_function());
test::check_return_type<key_equal>::equals(b.key_eq());
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);
test::check_return_type<size_type>::equals(a.erase(k));
BOOST_TEST(a.empty());
if(a.empty()) {
a.insert(t);
q = a.cbegin();
test::check_return_type<iterator>::equals(a.erase(q));
}
const_iterator q1 = a.cbegin(), q2 = a.cend();
test::check_return_type<iterator>::equals(a.erase(q1, q2));
a.clear();
X const b;
test::check_return_type<hasher>::equals(b.hash_function());
test::check_return_type<key_equal>::equals(b.key_eq());
test::check_return_type<iterator>::equals(a.find(k));
test::check_return_type<const_iterator>::equals(b.find(k));
test::check_return_type<size_type>::equals(b.count(k));
@@ -432,145 +375,4 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<float>::equals(b.max_load_factor());
a.max_load_factor((float) 2.0);
a.rehash(100);
// Avoid unused variable warnings:
sink(a);
sink(a2);
sink(a3);
sink(a4);
}
template <class X, class Key, class T, class Hash, class Pred>
void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
{
unordered_test(x, k, hf, eq);
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
X a;
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
X a6(i, j, 10, hf);
X(i, j, 10);
X a7(i, j, 10);
X(i, j);
X a8(i, j);
X const b;
sink(X(b));
X a9(b);
a = b;
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);
X a10;
a10.insert(t);
q = a10.cbegin();
test::check_return_type<iterator>::equals(a10.erase(q));
// Avoid unused variable warnings:
sink(a);
sink(a5);
sink(a6);
sink(a7);
sink(a8);
sink(a9);
}
template <class X, class Key, class T, class Hash, class Pred>
void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
{
unordered_test(x, k, hf, eq);
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>());
X x2(boost::move(x1));
x1 = rvalue_default<X>();
x2 = boost::move(x1);
#endif
test::minimal::constructor_param* i = 0;
test::minimal::constructor_param* j = 0;
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
X a6(i, j, 10, hf);
X(i, j, 10);
X a7(i, j, 10);
X(i, j);
X a8(i, j);
X a;
const_iterator q = a.cbegin();
test::minimal::constructor_param v;
a.emplace(v);
test::check_return_type<iterator>::equals(a.emplace_hint(q, v));
T v1(v);
a.emplace(boost::move(v1));
T v2(v);
a.insert(boost::move(v2));
T v3(v);
test::check_return_type<iterator>::equals(
a.emplace_hint(q, boost::move(v3)));
T v4(v);
test::check_return_type<iterator>::equals(
a.insert(q, boost::move(v4)));
a.insert(i, j);
X a10;
T v5(v);
a10.insert(boost::move(v5));
q = a10.cbegin();
test::check_return_type<iterator>::equals(a10.erase(q));
// Avoid unused variable warnings:
sink(a);
sink(a5);
sink(a6);
sink(a7);
sink(a8);
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();
}
+22 -77
View File
@@ -1,13 +1,12 @@
// Copyright 2006-2010 Daniel James.
// 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 "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -16,12 +15,15 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
namespace constructor_tests {
test::seed_t initialize_seed(356730);
test::seed_t seed(356730);
template <class T>
void constructor_tests1(T*, test::random_generator generator)
void constructor_tests1(T*,
test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -29,8 +31,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
T x(0, hf, eq);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -41,8 +41,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
@@ -54,8 +52,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
T x(2000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
@@ -67,8 +63,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
T x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -79,8 +73,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_TEST(x.bucket_count() >= 10000);
@@ -93,8 +85,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_TEST(x.bucket_count() >= 10000);
@@ -107,8 +97,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_TEST(x.bucket_count() >= 100);
@@ -121,8 +109,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 8\n";
{
test::check_instances check_;
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -134,8 +120,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 9\n";
{
test::check_instances check_;
T x(0, hf, eq, al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -146,8 +130,6 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 10\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_TEST(x.bucket_count() >= 10000);
@@ -160,8 +142,7 @@ void constructor_tests1(T*, test::random_generator generator)
std::cerr<<"Construct 11\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -172,7 +153,8 @@ void constructor_tests1(T*, test::random_generator generator)
}
template <class T>
void constructor_tests2(T*, test::random_generator const& generator)
void constructor_tests2(T*,
test::random_generator const& generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
@@ -186,7 +168,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 1\n";
{
test::check_instances check_;
T x(10000, hf1, eq1);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
@@ -197,7 +178,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
@@ -209,7 +189,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
@@ -221,7 +200,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_TEST(x.bucket_count() >= 1000);
@@ -235,7 +213,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 5\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2);
@@ -247,7 +224,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 6\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq);
@@ -259,7 +235,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 7\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf2, eq2);
@@ -271,7 +246,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Construct 8 - from input iterator\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
v_begin = v.begin(), v_end = v.end();
@@ -287,24 +261,8 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(y);
}
std::cerr<<"Construct 8.5 - from copy iterator\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(test::copy_iterator(v.begin()),
test::copy_iterator(v.end()), 0, hf1, eq1);
T y(test::copy_iterator(x.begin()),
test::copy_iterator(x.end()), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr<<"Construct 9\n";
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(50);
BOOST_TEST(x.bucket_count() >= 50);
@@ -316,13 +274,11 @@ void constructor_tests2(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::cerr<<"Initializer list construct 1\n";
{
test::check_instances check_;
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -332,8 +288,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Initializer list construct 2\n";
{
test::check_instances check_;
T x(list, 1000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000);
@@ -344,8 +298,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Initializer list construct 3\n";
{
test::check_instances check_;
T x(list, 10, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
@@ -356,8 +308,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Initializer list construct 4\n";
{
test::check_instances check_;
T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
@@ -368,8 +318,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
std::cerr<<"Initializer list construct 5\n";
{
test::check_instances check_;
T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
@@ -381,7 +329,8 @@ void constructor_tests2(T*, test::random_generator const& generator)
}
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
void map_constructor_test(T* = 0,
test::random_generator const& generator = test::default_generator)
{
std::cerr<<"map_constructor_test\n";
@@ -399,28 +348,24 @@ void map_constructor_test(T*, test::random_generator const& generator)
test::check_equivalent_keys(x);
}
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
@@ -430,11 +375,10 @@ UNORDERED_TEST(constructor_tests2,
)
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
((test_map)(test_multimap))
)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -445,7 +389,8 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
+17 -86
View File
@@ -4,35 +4,30 @@
// 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 "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
test::seed_t initialize_seed(9063);
test::seed_t seed(9063);
namespace copy_tests
{
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator)
void copy_construct_tests1(T*,
test::random_generator const& generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
{
test::check_instances check_;
T x;
T y(x);
BOOST_TEST(y.empty());
@@ -40,28 +35,20 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
// In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate
@@ -74,25 +61,22 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
BOOST_TEST(equivalent(y));
// This isn't guaranteed:
BOOST_TEST(y.load_factor() < y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
}
template <class T>
void copy_construct_tests2(T*, test::random_generator const& generator)
void copy_construct_tests2(T* ptr,
test::random_generator const& generator = test::default_generator)
{
copy_construct_tests1(ptr);
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
test::check_instances check_;
T x(10000, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
@@ -100,14 +84,10 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
@@ -115,13 +95,10 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
@@ -129,14 +106,10 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
@@ -144,74 +117,32 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_set_select_copy;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_multiset_select_copy;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_map_select_copy;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_multimap_select_copy;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_set_no_select_copy;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multiset_no_select_copy;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_map_no_select_copy;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(copy_construct_tests1, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
)
((default_generator)(generate_collisions))
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
)
UNORDERED_TEST(copy_construct_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
)
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
+5 -15
View File
@@ -4,10 +4,9 @@
// 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/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
@@ -137,25 +136,15 @@ namespace equality_tests
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), !=, (1001))
(1), ==, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
);
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
}
// Test that equality still works when the two containers have
@@ -176,6 +165,7 @@ namespace equality_tests
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+1 -2
View File
@@ -4,10 +4,9 @@
// 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 <algorithm>
#include <map>
+3 -30
View File
@@ -7,12 +7,10 @@
// hairy with several tricky edge cases - so explicitly test each one.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include "../helpers/invariants.hpp"
#include <set>
#include <iostream>
#include <iterator>
@@ -52,21 +50,12 @@ struct collision2_hash
int operator()(int x) const { return x & 1; }
};
// For testing erase in lots of buckets.
struct collision3_hash
{
int operator()(int x) const { return x; }
};
typedef boost::unordered_multimap<int, int,
collision_hash, std::equal_to<int>,
test::allocator1<std::pair<int const, int> > > collide_map;
test::allocator<std::pair<int const, int> > > collide_map;
typedef boost::unordered_multimap<int, int,
collision2_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > > collide_map2;
typedef boost::unordered_multimap<int, int,
collision3_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > > collide_map3;
test::allocator<std::pair<int const, int> > > collide_map2;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
@@ -76,7 +65,6 @@ UNORDERED_AUTO_TEST(empty_range_tests)
x.erase(x.begin(), x.end());
x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end());
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(single_item_tests)
@@ -87,13 +75,10 @@ UNORDERED_AUTO_TEST(single_item_tests)
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.end(), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
@@ -106,7 +91,6 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
{
@@ -115,7 +99,6 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
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);
}
{
@@ -124,7 +107,6 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
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);
}
}
@@ -146,8 +128,6 @@ bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
collide_list l(x.begin(), x.end());
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
x.erase(boost::next(x.begin(), start), boost::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
}
@@ -210,11 +190,4 @@ UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
std::cout<<"\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
{
std::cout<<"exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*) 0, 8, 4);
std::cout<<"\n";
}
RUN_TESTS()
+12 -40
View File
@@ -4,10 +4,9 @@
// 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 <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -15,25 +14,22 @@
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
namespace erase_tests
{
test::seed_t initialize_seed(85638);
test::seed_t seed(85638);
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
void erase_tests1(Container*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"Erase by key.\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
it = v.begin(); it != v.end(); ++it)
{
@@ -43,18 +39,14 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
}
std::cerr<<"erase(begin()).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while(size > 0 && !x.empty())
{
BOOST_DEDUCED_TYPENAME Container::key_type
@@ -66,19 +58,15 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr<<"erase(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while(size > 0 && !x.empty())
{
using namespace std;
@@ -102,15 +90,12 @@ void erase_tests1(Container*, test::random_generator generator)
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr<<"erase(ranges).\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
@@ -123,47 +108,37 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_TEST(x.size() == size);
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
test::check_equivalent_keys(x);
}
std::cerr<<"quick_erase(begin()).\n";
std::cerr<<"erase_return_void(begin()).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while(size > 0 && !x.empty())
{
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
x.quick_erase(x.begin());
x.erase_return_void(x.begin());
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr<<"quick_erase(random position).\n";
std::cerr<<"erase_return_void(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while(size > 0 && !x.empty())
{
using namespace std;
@@ -180,14 +155,13 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
x.quick_erase(pos);
x.erase_return_void(pos);
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
@@ -195,8 +169,6 @@ void erase_tests1(Container*, test::random_generator generator)
std::cerr<<"clear().\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
@@ -209,16 +181,16 @@ void erase_tests1(Container*, test::random_generator generator)
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+10 -13
View File
@@ -4,10 +4,9 @@
// 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 "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -17,16 +16,14 @@
namespace find_tests
{
test::seed_t initialize_seed(78937);
test::seed_t seed(78937);
template <class X>
void find_tests1(X*, test::random_generator generator)
void find_tests1(X*, test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
X const& x_const = x;
@@ -72,8 +69,6 @@ void find_tests1(X*, test::random_generator generator)
}
{
test::check_instances check_;
X x;
test::random_values<X> v2(5, generator);
@@ -115,8 +110,10 @@ struct compatible_predicate
};
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
void find_compatible_keys_test(X*,
test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator;
test::random_values<X> v(500, generator);
@@ -140,16 +137,16 @@ void find_compatible_keys_test(X*, test::random_generator generator)
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+12 -29
View File
@@ -4,57 +4,40 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_map_fwd.hpp>
#include "../helpers/postfix.hpp"
template <typename T>
void call_swap(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
#include <boost/unordered/unordered_map_fwd.hpp>
typedef boost::unordered_map<int, int> int_map;
void call_swap(int_map& x, int_map& y) {
swap(x,y);
}
template <typename T>
bool call_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
bool call_equals(int_map& x, int_map& y) {
return x == y;
}
template <typename T>
bool call_not_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
bool call_not_equals(int_map& x, int_map& y) {
return x != y;
}
template <typename T>
void call_swap(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
typedef boost::unordered_multimap<int, int> int_multimap;
void call_swap(int_multimap& x, int_multimap& y) {
swap(x,y);
}
template <typename T>
bool call_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
bool call_equals(int_multimap& x, int_multimap& y) {
return x == y;
}
template <typename T>
bool call_not_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
bool call_not_equals(int_multimap& x, int_multimap& y) {
return x != y;
}
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
int_map x, y;
x[1] = 2;
+13 -29
View File
@@ -4,8 +4,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_set_fwd.hpp>
#include "../helpers/postfix.hpp"
struct true_type { char x[100]; };
struct false_type { char x; };
@@ -16,53 +16,36 @@ template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*);
template<typename T>
void call_swap(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
typedef boost::unordered_set<int> int_set;
void call_swap(int_set& x, int_set& y) {
swap(x,y);
}
template<typename T>
bool call_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
bool call_equals(int_set& x, int_set& y) {
return x == y;
}
template<typename T>
bool call_not_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
bool call_not_equals(int_set& x, int_set& y) {
return x != y;
}
template<typename T>
void call_swap(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
typedef boost::unordered_multiset<int> int_multiset;
void call_swap(int_multiset& x, int_multiset& y) {
swap(x,y);
}
template<typename T>
bool call_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
bool call_equals(int_multiset& x, int_multiset& y) {
return x == y;
}
template<typename T>
bool call_not_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
bool call_not_equals(int_multiset& x, int_multiset& y) {
return x != y;
}
#include "../helpers/test.hpp"
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0))
== sizeof(true_type));
@@ -74,7 +57,8 @@ UNORDERED_AUTO_TEST(use_fwd_declared_trait) {
boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*) 0)) == sizeof(false_type));
int dummy;
BOOST_TEST(sizeof(is_unordered_set_impl(&dummy)) == sizeof(false_type));
}
UNORDERED_AUTO_TEST(use_set_fwd_declared_function) {
+26 -32
View File
@@ -4,36 +4,35 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <utility>
namespace x
{
struct D { boost::unordered_map<D, D> x; };
}
namespace incomplete_test
namespace test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T> struct allocator;
template <class T>
struct malloc_allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > > map;
malloc_allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
allocator<std::pair<value const, value> > > multimap;
malloc_allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
allocator<value> > set;
malloc_allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
allocator<value> > multiset;
malloc_allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
@@ -48,17 +47,12 @@ namespace incomplete_test
bool operator()(T const&, T const&) const { return true; }
};
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T>
struct allocator : std::allocator<T> {
allocator() {}
}
template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
#include "../helpers/allocator.hpp"
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
@@ -66,19 +60,19 @@ namespace incomplete_test
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > > x;
malloc_allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > > x;
malloc_allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
allocator<struct3> > x;
malloc_allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
allocator<struct4> > x;
malloc_allocator<struct4> > x;
};
// Now define the value type.
@@ -87,15 +81,15 @@ namespace incomplete_test
// Create some instances.
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
@@ -117,7 +111,7 @@ namespace incomplete_test
void use_types()
{
incomplete_test::value x;
test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
@@ -149,5 +143,5 @@ int main() {
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
incomplete_test::use_types();
test::use_types();
}
+1 -2
View File
@@ -4,10 +4,9 @@
// 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 <iostream>
+49 -355
View File
@@ -1,15 +1,13 @@
// Copyright 2006-2010 Daniel James.
// 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 "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/predef.h>
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -17,19 +15,17 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp"
#include <iostream>
namespace insert_tests {
test::seed_t initialize_seed(243432);
test::seed_t seed(243432);
template <class X>
void unique_insert_tests1(X*, test::random_generator generator)
void unique_insert_tests1(X*,
test::random_generator generator = test::default_generator)
{
test::check_instances check_;
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
@@ -56,7 +52,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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -64,13 +60,11 @@ void unique_insert_tests1(X*, test::random_generator generator)
}
template <class X>
void equivalent_insert_tests1(X*, test::random_generator generator)
void equivalent_insert_tests1(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
@@ -89,7 +83,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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -97,7 +91,8 @@ void equivalent_insert_tests1(X*, test::random_generator generator)
}
template <class X>
void insert_tests2(X*, test::random_generator generator)
void insert_tests2(X*,
test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME test::ordered<X> tracker_type;
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
@@ -107,8 +102,6 @@ void insert_tests2(X*, test::random_generator generator)
std::cerr<<"insert(begin(), value) tests.\n";
{
test::check_instances check_;
X x;
tracker_type tracker = test::create_ordered(x);
@@ -125,7 +118,7 @@ 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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -135,8 +128,6 @@ void insert_tests2(X*, test::random_generator generator)
std::cerr<<"insert(end(), value) tests.\n";
{
test::check_instances check_;
X x;
X const& x_const = x;
tracker_type tracker = test::create_ordered(x);
@@ -154,7 +145,7 @@ 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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -164,8 +155,6 @@ void insert_tests2(X*, test::random_generator generator)
std::cerr<<"insert(pos, value) tests.\n";
{
test::check_instances check_;
X x;
const_iterator pos = x.begin();
tracker_type tracker = test::create_ordered(x);
@@ -183,7 +172,7 @@ 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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -193,8 +182,6 @@ void insert_tests2(X*, test::random_generator generator)
std::cerr<<"insert single item range tests.\n";
{
test::check_instances check_;
X x;
tracker_type tracker = test::create_ordered(x);
@@ -210,7 +197,7 @@ void insert_tests2(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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -220,8 +207,6 @@ void insert_tests2(X*, test::random_generator generator)
std::cerr<<"insert range tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
@@ -231,29 +216,9 @@ void insert_tests2(X*, test::random_generator generator)
test::check_equivalent_keys(x);
}
std::cerr<<"insert range with rehash tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
x.insert(*v.begin());
x.clear();
x.insert(v.begin(), v.end());
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr<<"insert input iterator range tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
@@ -264,39 +229,13 @@ void insert_tests2(X*, test::random_generator generator)
test::check_equivalent_keys(x);
}
std::cerr<<"insert copy iterator range tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
x.insert(test::copy_iterator(v.begin()), test::copy_iterator(v.end()));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr<<"insert copy iterator range test 2.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v1(500, generator);
test::random_values<X> v2(500, generator);
x.insert(test::copy_iterator(v1.begin()), test::copy_iterator(v1.end()));
x.insert(test::copy_iterator(v2.begin()), test::copy_iterator(v2.end()));
test::check_equivalent_keys(x);
}
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class X>
void unique_emplace_tests1(X*, test::random_generator generator)
void unique_emplace_tests1(X*,
test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
@@ -324,7 +263,7 @@ 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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -332,7 +271,8 @@ void unique_emplace_tests1(X*, test::random_generator generator)
}
template <class X>
void equivalent_emplace_tests1(X*, test::random_generator generator)
void equivalent_emplace_tests1(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"emplace(value) tests for containers with equivalent keys.\n";
@@ -354,80 +294,17 @@ void equivalent_emplace_tests1(X*, test::random_generator generator)
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
if(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
template <class X>
void move_emplace_tests(X*, test::random_generator generator)
{
std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
{
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
typename X::value_type value = *it;
x.emplace(boost::move(value));
tracker.insert(*it);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
tracker.compare(x);
}
#endif
template <class X>
void default_emplace_tests(X*, test::random_generator)
{
std::cerr<<"emplace() tests.\n";
bool is_unique = test::has_unique_keys<X>::value;
X x;
x.emplace();
BOOST_TEST(x.size() == 1);
x.emplace();
BOOST_TEST(x.size() == is_unique ? 1: 2);
x.emplace();
BOOST_TEST(x.size() == is_unique ? 1: 3);
typename X::value_type y;
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 ? 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();
BOOST_TEST(x.empty());
x.emplace(y);
BOOST_TEST(x.size() == 1);
x.emplace(y);
BOOST_TEST(x.size() == is_unique ? 1: 2);
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);
}
template <class X>
void map_tests(X*, test::random_generator generator)
void map_tests(X*, test::random_generator generator = test::default_generator)
{
std::cerr<<"map tests.\n";
@@ -446,7 +323,7 @@ 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(x.size() < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -457,12 +334,11 @@ void map_tests(X*, test::random_generator generator)
// value type.
template <class X>
void map_insert_range_test1(X*, test::random_generator generator)
void map_insert_range_test1(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"map_insert_range_test1\n";
test::check_instances check_;
typedef test::list<
std::pair<
BOOST_DEDUCED_TYPENAME X::key_type,
@@ -478,17 +354,16 @@ void map_insert_range_test1(X*, test::random_generator generator)
}
template <class X>
void map_insert_range_test2(X*, test::random_generator generator)
void map_insert_range_test2(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"map_insert_range_test2\n";
test::check_instances check_;
typedef test::list<
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, test::implicitly_convertible>
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, int>
> list;
test::random_values<
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, test::implicitly_convertible>
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, int>
> v(1000, generator);
list l(v.begin(), v.end());
@@ -497,65 +372,48 @@ void map_insert_range_test2(X*, test::random_generator generator)
test::check_equivalent_keys(x);
}
boost::unordered_set<test::movable,
test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::movable,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::movable> >* test_multiset;
boost::unordered_map<test::movable, test::movable,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))
((test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_insert_tests1,
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(insert_tests2,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))
((test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_emplace_tests1,
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((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))
)
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
(test_multiset)(test_multimap))
((test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
#endif
UNORDERED_TEST(map_tests,
((test_map))
@@ -563,31 +421,17 @@ UNORDERED_TEST(map_tests,
)
UNORDERED_TEST(map_insert_range_test1,
((test_multimap_std_alloc)(test_map)(test_multimap))
((test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_multimap_std_alloc)(test_map)(test_multimap))
((test_map)(test_multimap))
((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 x.a + x.b;
}
bool operator==(initialize_from_two_ints const& x) const
{
return a == x.a && b == x.b;
}
};
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
@@ -596,38 +440,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 BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4,5,0)
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;
@@ -644,8 +458,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;
@@ -667,124 +479,6 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
#endif
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_) {}
int x1, x2, x3, x4;
bool operator==(overloaded_constructor const& rhs) const
{
return x1 == rhs.x1 && x2 == rhs.x2 && x3 == rhs.x3 && x4 == rhs.x4;
}
friend std::size_t hash_value(overloaded_constructor const& x)
{
std::size_t hash = 0;
boost::hash_combine(hash, x.x1);
boost::hash_combine(hash, x.x2);
boost::hash_combine(hash, x.x3);
boost::hash_combine(hash, x.x4);
return hash;
}
};
UNORDERED_AUTO_TEST(map_emplace_test)
{
boost::unordered_map<int, overloaded_constructor> x;
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
x.emplace();
BOOST_TEST(x.find(0) != x.end() &&
x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(x.find(2) != x.end() &&
x.find(2)->second == overloaded_constructor(3));
}
UNORDERED_AUTO_TEST(set_emplace_test)
{
boost::unordered_set<overloaded_constructor> x;
overloaded_constructor check;
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
x.emplace();
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
#endif
x.clear();
x.emplace(1);
check = overloaded_constructor(1);
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(2, 3);
check = overloaded_constructor(2, 3);
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(4, 5, 6);
check = overloaded_constructor(4, 5, 6);
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(7, 8, 9, 10);
check = overloaded_constructor(7, 8, 9, 10);
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
struct derived_from_piecewise_construct_t :
boost::unordered::piecewise_construct_t {};
derived_from_piecewise_construct_t piecewise_rvalue() {
return derived_from_piecewise_construct_t();
}
struct convertible_to_piecewise {
operator boost::unordered::piecewise_construct_t() const {
return boost::unordered::piecewise_construct;
}
};
UNORDERED_AUTO_TEST(map_emplace_test2)
{
boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
x.emplace(convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(piecewise_rvalue(), boost::make_tuple(2,3), boost::make_tuple(4,5,6));
BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
derived_from_piecewise_construct_t d;
x.emplace(d, boost::make_tuple(9,3,1), boost::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9,3,1)) != x.end() &&
x.find(overloaded_constructor(9,3,1))->second == overloaded_constructor(10));
}
UNORDERED_AUTO_TEST(set_emplace_test2)
{
boost::unordered_set<std::pair<overloaded_constructor, overloaded_constructor> > x;
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple(2,3));
check = std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));;
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
}
RUN_TESTS()
+1 -1
View File
@@ -4,9 +4,9 @@
// 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"
void foo(boost::unordered_set<int>&,
boost::unordered_map<int, int>&,
+1 -1
View File
@@ -4,9 +4,9 @@
// 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"
void foo(boost::unordered_set<int>& x1,
boost::unordered_map<int, int>& x2,
+12 -18
View File
@@ -4,10 +4,9 @@
// 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 <boost/limits.hpp>
#include "../helpers/random_values.hpp"
@@ -20,10 +19,10 @@
namespace load_factor_tests
{
test::seed_t initialize_seed(783656);
test::seed_t seed(783656);
template <class X>
void set_load_factor_tests(X*)
void set_load_factor_tests(X* = 0)
{
X x;
@@ -37,7 +36,8 @@ void set_load_factor_tests(X*)
}
template <class X>
void insert_test(X*, float mlf, test::random_generator generator)
void insert_test(X*, float mlf,
test::random_generator generator = test::default_generator)
{
X x;
x.max_load_factor(mlf);
@@ -51,24 +51,22 @@ void insert_test(X*, float mlf, test::random_generator generator)
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
x.insert(*it);
if(static_cast<double>(old_size + 1) < b * static_cast<double>(old_bucket_count))
if(old_size + 1 < b * old_bucket_count)
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
}
template <class X>
void load_factor_insert_tests(X* ptr, test::random_generator generator)
void load_factor_insert_tests(X* ptr = 0)
{
insert_test(ptr, 1.0f, generator);
insert_test(ptr, 0.1f, generator);
insert_test(ptr, 100.0f, generator);
insert_test(ptr, 1.0f);
insert_test(ptr, 0.1f);
insert_test(ptr, 100.0f);
insert_test(ptr, (std::numeric_limits<float>::min)(),
generator);
insert_test(ptr, (std::numeric_limits<float>::min)());
if(std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity(),
generator);
insert_test(ptr, std::numeric_limits<float>::infinity());
}
boost::unordered_set<int>* int_set_ptr;
@@ -76,16 +74,12 @@ boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
}
-95
View File
@@ -1,95 +0,0 @@
// Copyright 2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include "../objects/test.hpp"
template <class Tp>
struct SimpleAllocator
{
typedef Tp value_type;
SimpleAllocator()
{
}
template <class T> SimpleAllocator(const SimpleAllocator<T>& other)
{
}
Tp *allocate(std::size_t n)
{
return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
}
void deallocate(Tp* p, std::size_t)
{
::operator delete((void*) p);
}
};
template <typename T>
void test_simple_allocator()
{
test::check_instances check_;
typedef boost::unordered::detail::allocator_traits<
SimpleAllocator<T> > traits;
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T* >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_pointer, T const*>::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void* >::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
// rebind_alloc
// rebind_traits
SimpleAllocator<T> a;
T* ptr1 = traits::allocate(a, 1);
//T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
traits::construct(a, ptr1, T(10));
//traits::construct(a, ptr2, T(30), ptr1);
BOOST_TEST(*ptr1 == T(10));
//BOOST_TEST(*ptr2 == T(30));
traits::destroy(a, ptr1);
//traits::destroy(a, ptr2);
//traits::deallocate(a, ptr2, 1);
traits::deallocate(a, ptr1, 1);
traits::max_size(a);
}
int main()
{
test_simple_allocator<int>();
test_simple_allocator<test::object>();
return boost::report_errors();
}
+24 -247
View File
@@ -4,30 +4,19 @@
// file LICENSE_1_0.txt or move 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 "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace move_tests
{
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
test::seed_t seed(98624);
template<class T>
T empty(T*) {
@@ -57,15 +46,14 @@ namespace move_tests
}
template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator)
void move_construct_tests1(T* ptr,
test::random_generator const& generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
{
test::check_instances check_;
T y(empty(ptr));
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
@@ -76,8 +64,6 @@ namespace move_tests
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
@@ -90,16 +76,15 @@ namespace move_tests
}
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
void move_assign_tests1(T*,
test::random_generator const& generator = test::default_generator)
{
{
test::check_instances check_;
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
@@ -108,7 +93,8 @@ namespace move_tests
}
template <class T>
void move_construct_tests2(T*, test::random_generator const& generator)
void move_construct_tests2(T*,
test::random_generator const& generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
@@ -118,8 +104,6 @@ namespace move_tests
test::object_count count;
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
#if defined(BOOST_HAS_NRVO)
@@ -134,8 +118,6 @@ namespace move_tests
}
{
test::check_instances check_;
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
@@ -148,27 +130,16 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
/*
{
test::check_instances check_;
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_HAS_RVALUE_REFS)
BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions
- count.constructions) <=
(test::is_set<T>::value ? 1 : 2) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#else
BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions
- count.constructions) <=
(test::is_set<T>::value ? 2 : 4) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 50 : 25));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
@@ -178,226 +149,32 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
}
template <class T>
void move_assign_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::random_values<T> v(500, generator);
test::object_count count;
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{
test::check_instances check_;
test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator);
T x(0, hf, eq, al2);
x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x);
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count1.instances ==
test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
test::global_object_count.constructions);
}
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
}
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
*/ }
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_map_prop_move;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multimap_prop_move;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multimap_no_prop_move;
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(move_construct_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions))
UNORDERED_TEST(move_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
)
UNORDERED_TEST(move_assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions))
UNORDERED_TEST(move_assign_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
)
UNORDERED_TEST(move_construct_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_assign_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
UNORDERED_TEST(move_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
}
-125
View File
@@ -1,125 +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&) {}
};
UNORDERED_AUTO_TEST(test_noexcept)
{
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
#endif
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception>
>::value));
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_multiset<int, boost::hash<int>,
equal_to_possible_exception>
>::value));
}
// Test that the move constructor does actually move without throwing
// an exception when it claims to.
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=(hash_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
};
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=(equal_to_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x, int y) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
};
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{
typedef boost::unordered_set<int,
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
if (boost::is_nothrow_move_constructible<throwing_set>::value)
{
throwing_test_exception = false;
throwing_set x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
} catch(test_exception) {
BOOST_TEST(false);
}
throwing_test_exception = false;
}
}
}
RUN_TESTS()
+17 -143
View File
@@ -4,31 +4,27 @@
// 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/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/metafunctions.hpp"
#include "../objects/test.hpp"
namespace rehash_tests
{
test::seed_t initialize_seed(2974);
test::seed_t seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{
return static_cast<double>(x.bucket_count()) >
static_cast<double>(x.size()) / x.max_load_factor() &&
return x.bucket_count() > x.size() / x.max_load_factor() &&
x.bucket_count() >= n;
}
template <class X>
void rehash_empty_test1(X*)
void rehash_empty_test1(X* = 0)
{
X x;
@@ -37,13 +33,11 @@ void rehash_empty_test1(X*)
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
x.rehash(10000000);
BOOST_TEST(postcondition(x, 10000000));
}
template <class X>
void rehash_empty_test2(X*, test::random_generator generator)
void rehash_empty_test2(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -58,14 +52,11 @@ void rehash_empty_test2(X*, test::random_generator generator)
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000));
x.rehash(10000000);
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000000));
}
template <class X>
void rehash_empty_test3(X*, test::random_generator generator)
void rehash_empty_test3(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -82,8 +73,10 @@ void rehash_empty_test3(X*, test::random_generator generator)
BOOST_TEST(postcondition(x, 0));
}
template <class X>
void rehash_test1(X*, test::random_generator generator)
void rehash_test1(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -105,141 +98,22 @@ void rehash_test1(X*, test::random_generator generator)
tracker.compare(x);
}
template <class X>
void reserve_empty_test1(X*)
{
X x;
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 10000);
x.reserve(0);
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 10000000);
}
template <class X>
void reserve_empty_test2(X*)
{
X x;
x.max_load_factor(0.25);
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 40000);
x.reserve(0);
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 40000000);
}
template <class X>
void reserve_test1(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
// 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
// no iterators to invalidate in the range insert, and it can
// rehash.
typename test::random_values<X>::iterator it = v.begin();
x.insert(*it);
++it;
std::size_t bucket_count = x.bucket_count();
x.insert(it, v.end());
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
template <class X>
void reserve_test2(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
{
x.insert(*it);
}
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset_ptr;
boost::unordered_map<test::movable, test::movable,
test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
}
+1 -2
View File
@@ -6,10 +6,9 @@
// This test checks the runtime requirements of containers.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <cstdlib>
#include <algorithm>
+35 -122
View File
@@ -4,28 +4,22 @@
// 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/config.hpp>
#include <algorithm>
#include <iterator>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace swap_tests
{
test::seed_t initialize_seed(783472);
test::seed_t seed(783472);
template <class X>
void swap_test_impl(X& x1, X& x2)
@@ -40,25 +34,19 @@ void swap_test_impl(X& x1, X& x2)
}
template <class X>
void swap_tests1(X*, test::random_generator generator)
void swap_tests1(X*, test::random_generator generator = test::default_generator)
{
{
test::check_instances check_;
X x;
swap_test_impl(x, x);
}
{
test::check_instances check_;
X x,y;
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x, y(v.begin(), v.end());
swap_test_impl(x, y);
@@ -66,8 +54,6 @@ void swap_tests1(X*, test::random_generator generator)
}
{
test::check_instances check_;
test::random_values<X> vx(1000, generator), vy(1000, generator);
X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
swap_test_impl(x, y);
@@ -76,25 +62,22 @@ void swap_tests1(X*, test::random_generator generator)
}
template <class X>
void swap_tests2(X* ptr, test::random_generator generator)
void swap_tests2(X* ptr = 0,
test::random_generator generator = test::default_generator)
{
swap_tests1(ptr, generator);
swap_tests1(ptr);
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
{
test::check_instances check_;
X x(0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
@@ -102,8 +85,6 @@ void swap_tests2(X* ptr, test::random_generator generator)
}
{
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(50, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
@@ -111,124 +92,56 @@ void swap_tests2(X* ptr, test::random_generator generator)
swap_test_impl(x, y);
}
#if BOOST_UNORDERED_SWAP_METHOD == 1
{
test::random_values<X> vx(100, generator), vy(50, generator);
X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
try {
swap_test_impl(x, y);
BOOST_ERROR("Using swap method 1, "
"swapping with unequal allocators didn't throw.");
} catch (std::runtime_error) {}
}
#else
{
test::force_equal_allocator force_(
!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(50, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator())
{
swap_test_impl(x, y);
}
swap_test_impl(x, y);
}
{
test::force_equal_allocator force_(
!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1),
allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator())
{
swap_test_impl(x, y);
swap_test_impl(x, y);
}
swap_test_impl(x, y);
swap_test_impl(x, y);
}
#endif
}
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_set_prop_swap;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multiset_prop_swap;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_map_prop_swap;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multimap_prop_swap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_set_no_prop_swap;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multiset_no_prop_swap;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_map_no_prop_swap;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multimap_no_prop_swap;
template <typename T>
bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_swap;
}
using test::default_generator;
using test::generate_collisions;
UNORDERED_AUTO_TEST(check_traits)
{
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap));
BOOST_TEST(!is_propagate(test_set_no_prop_swap));
}
UNORDERED_TEST(swap_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
)
((default_generator)(generate_collisions))
UNORDERED_TEST(swap_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
)
UNORDERED_TEST(swap_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
)
((default_generator)(generate_collisions))
UNORDERED_TEST(swap_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
)
}
+42 -263
View File
@@ -4,33 +4,19 @@
// 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 <iostream>
#include "../helpers/test.hpp"
namespace unnecessary_copy_tests
{
struct count_copies
{
private:
BOOST_COPYABLE_AND_MOVABLE(count_copies)
public:
static int copies;
static int moves;
static int id_count;
count_copies() : tag_(0), id_(++id_count) {
++copies;
trace_op("Default construct");
}
explicit count_copies(int tag) : tag_(tag), id_(++id_count) {
++copies;
trace_op("Tag construct");
}
count_copies() : tag_(0) { ++copies; }
explicit count_copies(int tag) : tag_(tag) { ++copies; }
// This bizarre constructor is an attempt to confuse emplace.
//
@@ -42,52 +28,17 @@ namespace unnecessary_copy_tests
// The second emplace should use the single argument contructor for
// the key, and this constructor for the value.
count_copies(count_copies const&, count_copies const& x)
: tag_(x.tag_), id_(++id_count)
{
++copies;
trace_op("Pair construct");
}
: tag_(x.tag_) { ++copies; }
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
{
++copies;
trace_op("Copy construct");
}
count_copies(BOOST_RV_REF(count_copies) x) :
tag_(x.tag_), id_(++id_count)
{
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
#if defined(BOOST_HAS_RVALUE_REFS)
count_copies(count_copies&& x) : tag_(x.tag_) {
x.tag_ = -1; ++moves;
trace_op("Move construct");
}
count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
{
tag_ = p.tag_;
++copies;
trace_op("Copy assign");
return *this;
}
count_copies& operator=(BOOST_RV_REF(count_copies) p) //Move assignment
{
tag_ = p.tag_;
++moves;
trace_op("Move assign");
return *this;
}
~count_copies() {
trace_op("Destruct");
}
void trace_op(char const* str) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_
<< " (#" << id_ << ")" <<std::endl;
}
int tag_;
int id_;
#endif
int tag_;
private:
count_copies& operator=(count_copies const&);
};
bool operator==(count_copies const& x, count_copies const& y) {
@@ -102,9 +53,6 @@ namespace unnecessary_copy_tests
void reset() {
count_copies::copies = 0;
count_copies::moves = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "\nReset\n" << std::endl;
}
}
@@ -119,64 +67,39 @@ namespace unnecessary_copy_tests
}
}
// 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) { \
if(count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< "Number of copies: " << count_copies::copies \
<< " expecting: " << n << std::endl; \
}
#define MOVE_COUNT(n) \
if(::unnecessary_copy_tests::count_copies::moves != n) { \
if(count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< "Number of moves: " << count_copies::moves \
<< " expecting: " <<n << std::endl; \
}
#define COPY_COUNT_RANGE(a, b) \
if(::unnecessary_copy_tests::count_copies::copies < a || \
::unnecessary_copy_tests::count_copies::copies > b) { \
if(count_copies::copies < a || count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< "Number of copies: " << count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define MOVE_COUNT_RANGE(a, b) \
if(::unnecessary_copy_tests::count_copies::moves < a || \
::unnecessary_copy_tests::count_copies::moves > b) { \
if(count_copies::moves < a || count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< "Number of moves: " << count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define COPY_COUNT_EXTRA(a, b) \
COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
#define MOVE_COUNT_EXTRA(a, b) \
MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
namespace unnecessary_copy_tests
{
int count_copies::copies;
int count_copies::moves;
int count_copies::id_count;
template <class T>
void unnecessary_copy_insert_test(T*)
@@ -213,7 +136,7 @@ namespace unnecessary_copy_tests
reset();
T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
COPY_COUNT(1);
#else
COPY_COUNT(2);
@@ -225,9 +148,9 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class T>
void unnecessary_copy_emplace_std_move_test(T*)
void unnecessary_copy_emplace_move_test(T*)
{
reset();
T x;
@@ -237,73 +160,13 @@ namespace unnecessary_copy_tests
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);
#else
// Since std::pair isn't movable, move only works for sets.
COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_test,
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
((set)(multiset)(map)(multimap)))
template <class T>
void unnecessary_copy_emplace_boost_move_set_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT(0);
x.emplace(boost::move(a));
COPY_COUNT(1); MOVE_COUNT(1);
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test,
((set)(multiset)))
template <class T>
void unnecessary_copy_emplace_boost_move_map_test(T*)
{
reset();
T x;
COPY_COUNT(0); MOVE_COUNT(0);
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT_EXTRA(0, 1);
#else
COPY_COUNT(1); MOVE_COUNT(1);
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test,
((map)(multimap)))
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
{
// When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later.
reset();
source<count_copies>();
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
//
reset();
boost::unordered_set<count_copies> x;
count_copies a;
@@ -314,19 +177,11 @@ namespace unnecessary_copy_tests
// 0 arguments
//
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// The container will have to create a copy in order to compare with
// the existing element.
reset();
x.emplace();
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// source_cost doesn't make much sense here, but it seems to fit.
COPY_COUNT(1); MOVE_COUNT(source_cost);
#else
COPY_COUNT(1); MOVE_COUNT(1 + source_cost);
#endif
#endif
COPY_COUNT(1); MOVE_COUNT(0);
//
// 1 argument
@@ -342,18 +197,16 @@ namespace unnecessary_copy_tests
// copied.
reset();
x.emplace(source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(source_cost);
COPY_COUNT(1); MOVE_COUNT(0);
#if defined(BOOST_HAS_RVALUE_REFS)
// No move should take place.
reset();
x.emplace(boost::move(a));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#else
COPY_COUNT(0); MOVE_COUNT(1);
#endif
// Use a new value for cases where a did get moved...
// Just in case a did get moved...
count_copies b;
// The container will have to create a copy in order to compare with
@@ -380,53 +233,22 @@ namespace unnecessary_copy_tests
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
{
// When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later.
reset();
source<count_copies>();
int source_cost = ::unnecessary_copy_tests::count_copies::moves;
reset();
source<std::pair<count_copies, count_copies> >();
int source_pair_cost = ::unnecessary_copy_tests::count_copies::moves;
//
reset();
boost::unordered_map<count_copies, count_copies> x;
// TODO: Run tests for pairs without const etc.
std::pair<count_copies const, count_copies> a;
x.emplace(a);
COPY_COUNT_EXTRA(4, 1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(4); MOVE_COUNT(0);
//
// 0 arguments
//
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// COPY_COUNT(1) would be okay here.
reset();
x.emplace();
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
// This is a little odd, Visual C++ 11 seems to move the pair, which
// results in one copy (for the const key) and one move (for the
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
// has the normal result, it must be some odd consequence of how
// Visual C++ 11 handles calling move for default arguments.
COPY_COUNT(3); MOVE_COUNT(1);
# else
COPY_COUNT_EXTRA(2, 1); MOVE_COUNT_EXTRA(0, 1);
# endif
#endif
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(),
boost::make_tuple());
COPY_COUNT(2); MOVE_COUNT(0);
//
// 1 argument
//
@@ -439,88 +261,45 @@ namespace unnecessary_copy_tests
// copied.
reset();
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)
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
x.emplace(a_ref);
COPY_COUNT(2); MOVE_COUNT(0);
#endif
// TODO: This doesn't work on older versions of gcc.
//count_copies part;
std::pair<count_copies const, count_copies> b;
//reset();
//std::pair<count_copies const&, count_copies const&> a_ref(part, part);
//x.emplace(a_ref);
//COPY_COUNT(0); MOVE_COUNT(0);
#if defined(BOOST_HAS_RVALUE_REFS)
// No move should take place.
// (since a is already in the container)
reset();
x.emplace(boost::move(a));
x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
//
// 2 arguments
//
std::pair<count_copies const, count_copies> b;
reset();
x.emplace(b.first, b.second);
COPY_COUNT(0); MOVE_COUNT(0);
reset();
x.emplace(source<count_copies>(), source<count_copies>());
COPY_COUNT(2); MOVE_COUNT(source_cost * 2);
COPY_COUNT(2); MOVE_COUNT(0);
// source<count_copies> creates a single copy.
reset();
x.emplace(b.first, source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(source_cost);
COPY_COUNT(1); MOVE_COUNT(0);
reset();
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
COPY_COUNT(2); MOVE_COUNT(0);
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(boost::ref(b.first)),
boost::make_tuple(boost::ref(b.second)));
COPY_COUNT(0); MOVE_COUNT(0);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
reset();
x.emplace(boost::unordered::piecewise_construct,
std::make_tuple(std::ref(b.first)),
std::make_tuple(std::ref(b.second)));
COPY_COUNT(0); MOVE_COUNT(0);
std::pair<count_copies const, count_copies> move_source_trial;
reset();
std::make_tuple(std::move(move_source_trial.first));
std::make_tuple(std::move(move_source_trial.second));
int tuple_move_cost = ::unnecessary_copy_tests::count_copies::moves;
int tuple_copy_cost = ::unnecessary_copy_tests::count_copies::copies;
std::pair<count_copies const, count_copies> move_source;
reset();
x.emplace(boost::unordered::piecewise_construct,
std::make_tuple(std::move(move_source.first)),
std::make_tuple(std::move(move_source.second)));
COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
reset();
x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first),
std::forward_as_tuple(b.second));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
#endif
}
}