Compare commits

..

30 Commits

Author SHA1 Message Date
Marshall Clow a4076e1297 Release 1.51.0
[SVN r80098]
2012-08-20 22:07:05 +00:00
Daniel James 8683332b2c Unordered: Merge from trunk
- Avoid an incorrect MSVC unused variable warning in the tests.
- Remove a `try..catch`.
- Adjust SFINAE use to try to supprt g++ 3.4. Fixes #7175.
- Fix some use of rvalues.
- Extra info in `at_tests`.



[SVN r79868]
2012-08-05 08:34:44 +00:00
Daniel James d77453b7ad Unordered: Merge allocator fix + improved tests. Fixes #7100.
[SVN r79547]
2012-07-15 23:58:02 +00:00
Daniel James cf9930fe20 Unordered: Merge updated c++11 config macros.
[SVN r79546]
2012-07-15 23:47:12 +00:00
Daniel James e30a99d2fc Unordered: Merge some of the older changes from trunk.
Code reorganization, simpler tests, better use of Boost.Move.


[SVN r79545]
2012-07-15 23:44:41 +00:00
Daniel James c788780792 Unordered: Merge msvc 11 fix from trunk.
[SVN r78853]
2012-06-07 19:47:01 +00:00
Daniel James e1416d0a3e Unordered: Fix bcp namespace fix. Fixes #6905.
[SVN r78534]
2012-05-21 22:08:19 +00:00
Daniel James 808f1f939f Unordered: Merge unordered from trunk.
- Activate `std::allocator_traits` for gcc 4.7 and Visual C++ 11.
- Implement variadic construct in `boost::unordered::detail::allocator_traits`
  when variadics, rvalue references and SFINAE expression are available.
- Use variadic construct from `allocator_traits`, or when not available move
  the logic for constructing `value_type` to a lower level, so the container
  code is a bit simpler.
- Avoid `-Wshadow` warnings. Fixes #6190.
- Implement `reserve`. Fixes #6857.


[SVN r78432]
2012-05-12 08:14:05 +00:00
Daniel James 880d778ab6 Unordered: Missing revision from last merge.
[SVN r78320]
2012-05-03 22:29:25 +00:00
Daniel James a8cd8cdd0b Unordered/Hash: Merge from trunk.
[SVN r78319]
2012-05-03 22:05:21 +00:00
Daniel James fa3d93ddbc Unordered: Merge to release. Fixes #6522.
Fixes undefined macros, removes some unused code and fix some potential issues
for when `std::allocator_traits` is used.


[SVN r76943]
2012-02-07 20:48:50 +00:00
Daniel James 5622afdafa Iostreams: Merge spelling fix.
[SVN r76787]
2012-01-29 22:54:03 +00:00
Daniel James 63d56953af Unordered: Merge move changes. Fixes #6311.
[SVN r76531]
2012-01-15 20:22:15 +00:00
Daniel James 280b1971b6 Unordered: merge from trunk.
[SVN r75908]
2011-12-11 21:39:18 +00:00
Daniel James abc556950b Unordered: Remove support for TR1 tuples. Fixes #6111.
[SVN r75450]
2011-11-12 12:01:34 +00:00
Daniel James a8f75b7cea Merge to release several changes for 1.48.
[SVN r75293]
2011-11-04 02:31:36 +00:00
Daniel James 1f111edec8 Merge unordered+hash documentation updates.
[SVN r75015]
2011-10-17 20:23:27 +00:00
Daniel James 8591c1f180 Unordered: merge from trunk.
[SVN r74932]
2011-10-12 22:30:02 +00:00
Daniel James 50e8df5e12 Unordered: Merge from trunk.
Anotehr overhaul. Can now use `void_pointer` for links between nodes, although
it doesn't as I don't think `void_pointer` support is strong enough in existing
allocators.

Also no longer relies on using base pointers for custome pointer types.  And
scaled back member function detection to just detect if an allocator has a
member, not what its signature is. I found that the trait could be confused by
ambiguous overloads. This might be fixable.

Better documentation of C++11 compliance to come.


[SVN r74859]
2011-10-09 18:30:10 +00:00
Daniel James 17ba6c9916 Unordered: Merge from trunk.
Remove some workarounds for old compilers, some documentation updates and tweak
some tests for problem compilers.


[SVN r74469]
2011-09-19 18:22:18 +00:00
Daniel James 0618d01f86 Unordered: Move from trunk.
[SVN r74308]
2011-09-08 07:33:34 +00:00
Daniel James 5867994b8c Unordered: Merge from trunk
- Remove use of BOOST_DEDUCED_TYPENAME and BOOST_UNORDERED_PAIR_CAST, it's
  unlikely that the compilers which require them will be able to cope with the
  new version of unordered.
- Use the old equality algorithm if BOOST_UNORDERED_DEPRECATED_EQUALITY is
  defined.
- Use SFINAE to control which overloads of `construct_impl` are available.
  Fixes problems with differing overload resolution on different compilers.
- Support for piecewise pair construction.
- Only support the old variadic pair construction when
  BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT is defined (also fixed some bugs).
- Avoid instantiating BOOST_RV_REF for non-classes.
- Support optional allocator member functions for compilers with SFINAE
  expressions and Visual C++ 9.0/10.0
- Follow boost macro naming conventions.
- Improved portability for `allocator_traits` emulation.

Current compiler support:

- Full support for GCC 4.4+, Visual C++ 9.0+, Clang.
- All other compilers odn't support optional allocator members.
- No other errors for GCC 3.4.6+, Visual C++ 8.0, Intel, Pathscale.
- Visual Age has a compile error if `select_on_container_copy_construction`
  isn't `const` (it should ignore it).
- `select_on_container_copy_construction` detection doesn't work on Sun.
- `unnecessary_copy_tests` is failling for vacpp on AIX, but not on linux.
- Warnings causing failures for Visual C++ with STLport and WM5.


[SVN r74234]
2011-09-04 19:37:45 +00:00
Daniel James f6f19aaaaa Unordered: Merge from trunk.
Portability fixes, and fix some issues with constructing std::pair.


[SVN r74101]
2011-08-28 11:26:38 +00:00
Daniel James a4372314c2 Unordered: Merge to release.
Using Boost.Move and better C++11 support.


[SVN r73987]
2011-08-21 19:19:12 +00:00
Daniel James 3fd5635d7d Unordered: Fix some overly strict tests.
[SVN r70443]
2011-03-23 00:07:17 +00:00
Daniel James 147181530d Add copy constructors and assignment operators when using rvalue references. Fixes #5119.
[SVN r69469]
2011-03-02 08:47:34 +00:00
Daniel James 54f9626c12 Merge unordered from trunk.
- Avoid using operator& with the value type.
- More comments in headers.
- Remove old clang workaround.
- Adjust use of inline to make Borland a little happier.
- Avoid `-Wconversion` warnings.


[SVN r67663]
2011-01-04 23:05:55 +00:00
Daniel James dc8e65043b Merge fix for unordered container insertion bug.
[SVN r66151]
2010-10-23 12:02:18 +00:00
Daniel James 8b4c480d47 Merge unordered build and documentation tweaks.
[SVN r63503]
2010-07-01 21:42:52 +00:00
Daniel James 70ca44b503 Merge unordered.
[SVN r62610]
2010-06-08 23:23:43 +00:00
81 changed files with 11864 additions and 5618 deletions
+11 -2
View File
@@ -3,13 +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)
using boostbook ;
using quickbook ;
path-constant images_location : ../ ;
path-constant admonishment_location : ../../../../doc/src/images ;
xml unordered : unordered.qbk ;
boostbook standalone : unordered :
<xsl:param>boost.root=../../../..
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
<xsl:param>generate.section.toc.level=2
@@ -20,7 +21,15 @@ 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 Methods for Controlling Bucket Size
[table:bucket_size Methods for Controlling Bucket Size
[[Method] [Description]]
[
+70
View File
@@ -129,4 +129,74 @@ First official 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.
[endsect]
+5 -8
View File
@@ -1,10 +1,10 @@
[/ Copyright 2006-2008 Daniel James.
[/ 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) ]
[section:comparison Comparison with Associative Containers]
[table Interface differences.
[table:interface_differences Interface differences.
[[Associative Containers] [Unordered Associative Containers]]
[
@@ -66,15 +66,12 @@
[
[No equivalent]
[Local iterators can be used to iterate through individual buckets.
(I don't think that the order of local iterators and iterators are
(The order of local iterators and iterators aren't
required to have any correspondence.)]
]
[
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
[No comparison operators are defined in the standard, although
[link unordered.rationale.equality_operators
implementations might extend the containers to support `==` and
`!=`].]
[Can be compared using the `==` and `!=` operators.]
]
[
[]
@@ -88,7 +85,7 @@
]
]
[table Complexity Guarantees
[table:complexity_guarantees Complexity Guarantees
[[Operation] [Associative Containers] [Unordered Associative Containers]]
[
[Construction of empty container]
+111
View File
@@ -0,0 +1,111 @@
[/ 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 you'll need to use Boost.Move
to take advantage of using movable container elements, also note that:
* Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be 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]
+3 -2
View File
@@ -67,9 +67,10 @@ 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 on other implementations of the unordered associative containers.
won't work for other implementations of the unordered associative containers,
you'll need to explicitly use Boost.Hash.
[table Methods for accessing the hash and equality functions.
[table:access_methods Methods for accessing the hash and equality functions.
[[Method] [Description]]
[
+4 -15
View File
@@ -2,15 +2,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) ]
[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
@@ -31,12 +22,10 @@ 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, 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__.
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.
`unordered_set` and `unordered_multiset` are defined in the header
<[headerref boost/unordered_set.hpp]>
+13 -48
View File
@@ -44,6 +44,8 @@ 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)
@@ -63,6 +65,17 @@ 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]
@@ -90,52 +103,4 @@ efficiency advantage of power of 2 hash tables.
So, this implementation uses a prime number for the hash table size.
[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]
+1130
View File
File diff suppressed because it is too large Load Diff
+544 -244
View File
File diff suppressed because it is too large Load Diff
+3 -2
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.4]
[quickbook 1.5]
[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,6 +31,7 @@
[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
@@ -1,111 +0,0 @@
// 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
File diff suppressed because it is too large Load Diff
+70 -12
View File
@@ -1,17 +1,16 @@
// Copyright (C) 2005-2009 Daniel James
// Copyright (C) 2005-2011 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <boost/unordered/detail/table.hpp>
namespace boost {
namespace unordered_detail {
namespace unordered {
namespace detail {
// key extractors
//
@@ -28,6 +27,19 @@ namespace unordered_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
{
@@ -44,13 +56,12 @@ namespace unordered_detail {
return no_key();
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
@@ -58,8 +69,8 @@ namespace unordered_detail {
return no_key();
}
template <class Arg>
static no_key extract(Arg const&, Arg const&)
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
@@ -75,7 +86,7 @@ namespace unordered_detail {
struct map_extractor
{
typedef ValueType value_type;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Key>::type key_type;
typedef typename boost::remove_const<Key>::type key_type;
static key_type const& extract(value_type const& v)
{
@@ -100,7 +111,7 @@ namespace unordered_detail {
return v.first;
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class Arg1, class... Args>
static key_type const& extract(key_type const& k,
Arg1 const&, Args const&...)
@@ -114,6 +125,7 @@ namespace unordered_detail {
return no_key();
}
#else
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
@@ -138,11 +150,57 @@ namespace unordered_detail {
}
#endif
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&, BOOST_FWD_REF(T2)) \
{ \
return no_key(); \
} \
\
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
}
#else
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&) \
{ \
return no_key(); \
} \
\
template <typename T> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
}
#endif
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
#endif
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;
}
};
}}
}}}
#endif
File diff suppressed because it is too large Load Diff
-243
View File
@@ -1,243 +0,0 @@
/*
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
@@ -1,226 +0,0 @@
// 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
File diff suppressed because it is too large Load Diff
+129 -200
View File
@@ -1,39 +1,62 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2009 Daniel James
// Copyright (C) 2005-2011 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#include <cstddef>
#include <utility>
#include <algorithm>
#include <boost/limits.hpp>
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_empty.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <boost/swap.hpp>
namespace boost { namespace unordered_detail {
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 {};
////////////////////////////////////////////////////////////////////////////
// convert double to std::size_t
// iterator SFINAE
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);
}
template <typename I>
struct is_forward :
boost::is_convertible<
typename boost::iterator_traversal<I>::type,
boost::forward_traversal_tag>
{};
template <typename I, typename ReturnType>
struct enable_if_forward :
boost::enable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
template <typename I, typename ReturnType>
struct disable_if_forward :
boost::disable_if_c<
boost::unordered::detail::is_forward<I>::value,
ReturnType>
{};
////////////////////////////////////////////////////////////////////////////
// primes
#define BOOST_UNORDERED_PRIMES \
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(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) \
@@ -92,240 +115,146 @@ namespace boost { namespace unordered_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 std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
inline typename
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
insert_size(I i, I j)
{
return std::distance(i, j);
}
template <class I>
inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
inline typename
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
insert_size(I, I)
{
return 1;
}
template <class I>
inline std::size_t insert_size(I i, I j)
{
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)
std::size_t num_buckets =
boost::unordered::detail::default_bucket_count)
{
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
// TODO: Why +1?
return (std::max)(
boost::unordered::detail::insert_size(i, j) + 1,
num_buckets);
}
////////////////////////////////////////////////////////////////////////////
// Node Constructors
// compressed
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class T, class... Args>
inline void construct_impl(T*, void* address, Args&&... args)
template <typename T, int Index>
struct compressed_base : private T
{
new(address) T(std::forward<Args>(args)...);
}
compressed_base(T const& x) : T(x) {}
compressed_base(T& x, move_tag) : T(boost::move(x)) {}
#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)
)
T& get() { return *this; }
T const& get() const { return *this; }
};
template <typename T, int Index>
struct uncompressed_base
{
new(address) std::pair<First, Second>(k,
Second(arg0, std::forward<Args>(args)...);
}
#endif
uncompressed_base(T const& x) : value_(x) {}
uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
#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
T& get() { return value_; }
T const& get() const { return value_; }
private:
T value_;
};
template <typename T, int Index>
struct generate_base
: boost::detail::if_true<
boost::is_empty<T>::value
>:: BOOST_NESTED_TEMPLATE then<
boost::unordered::detail::compressed_base<T, Index>,
boost::unordered::detail::uncompressed_base<T, Index>
>
{};
template <typename T1, typename T2>
struct compressed
: private boost::unordered::detail::generate_base<T1, 1>::type,
private boost::unordered::detail::generate_base<T2, 2>::type
{
typedef 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 typename generate_base<T1, 1>::type base1;
typedef typename generate_base<T2, 2>::type base2;
buckets& buckets_;
real_node_ptr node_;
bool node_constructed_;
bool value_constructed_;
public:
hash_node_constructor(buckets& m) :
buckets_(m),
node_(),
node_constructed_(false),
value_constructed_(false)
{
typedef T1 first_type;
typedef T2 second_type;
first_type& first() {
return static_cast<base1*>(this)->get();
}
~hash_node_constructor();
void construct_preamble();
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class... Args>
void construct(Args&&... args)
{
construct_preamble();
construct_impl((value_type*) 0, node_->address(),
std::forward<Args>(args)...);
value_constructed_ = true;
}
#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; \
first_type const& first() const {
return static_cast<base1 const*>(this)->get();
}
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;
second_type& second() {
return static_cast<base2*>(this)->get();
}
value_type& value() const
{
BOOST_ASSERT(node_);
return node_->value();
second_type const& second() const {
return static_cast<base2 const*>(this)->get();
}
// no throw
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
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)
{
real_node_ptr p = node_;
node_ = real_node_ptr();
// node_ptr cast
return buckets_.bucket_alloc().address(*p);
first() = x.first();
second() = x.second();
}
void move_assign(compressed& x)
{
first() = boost::move(x.first());
second() = boost::move(x.second());
}
void swap(compressed& x)
{
boost::swap(first(), x.first());
boost::swap(second(), x.second());
}
private:
hash_node_constructor(hash_node_constructor const&);
hash_node_constructor& operator=(hash_node_constructor const&);
// Prevent assignment just to make use of assign or
// move_assign explicit.
compressed& operator=(compressed 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
+43 -31
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2008-2009 Daniel James.
// Copyright (C) 2008-2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -14,40 +14,52 @@
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
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>&);
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_multimap;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
void swap(unordered_multimap<K, T, H, P, A>&,
unordered_multimap<K, T, H, P, A>&);
template <class 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!=;
}
#endif
File diff suppressed because it is too large Load Diff
+41 -29
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2008-2009 Daniel James.
// Copyright (C) 2008-2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -14,38 +14,50 @@
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
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);
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_multiset;
template <class T, class H, class P, class A>
bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2);
template <class 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!=;
}
#endif
+3 -3
View File
@@ -14,9 +14,9 @@ project unordered-test/exception-tests
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>gcc:<define>_GLIBCXX_DEBUG
<toolset>darwin:<define>_GLIBCXX_DEBUG
<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<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
;
+1 -3
View File
@@ -3,8 +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)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(12847);
test::seed_t initialize_seed(12847);
template <class T>
struct self_assign_base : public test::exception_base
+16 -4
View File
@@ -3,15 +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 seed(91274);
test::seed_t initialize_seed(91274);
struct objects
{
@@ -148,6 +146,19 @@ struct input_range_construct_test : public range<T>, objects
}
};
template <class T>
struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
void run() const {
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
RUN_EXCEPTION_TESTS(
(construct_test1)
(construct_test2)
@@ -160,5 +171,6 @@ RUN_EXCEPTION_TESTS(
(range_construct_test3)
(range_construct_test4)
(range_construct_test5)
(input_range_construct_test),
(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
+2
View File
@@ -3,8 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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<
+1 -3
View File
@@ -3,14 +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 seed(73041);
test::seed_t initialize_seed(73041);
template <class T>
struct copy_test1 : public test::exception_base
+1 -3
View File
@@ -3,14 +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"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
test::seed_t seed(835193);
test::seed_t initialize_seed(835193);
template <class T>
struct erase_test_base : public test::exception_base
+8 -10
View File
@@ -3,8 +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)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <boost/utility.hpp>
#include <cmath>
test::seed_t seed(747373);
test::seed_t initialize_seed(747373);
template <class T>
struct insert_test_base : public test::exception_base
@@ -34,7 +32,7 @@ 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::exception::detail::tracker.count_allocations);
strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
@@ -51,7 +49,7 @@ struct emplace_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.emplace(*it);
}
}
@@ -69,7 +67,7 @@ struct insert_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
}
@@ -85,7 +83,7 @@ struct insert_test2 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
@@ -113,7 +111,7 @@ struct insert_test4 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
@@ -152,7 +150,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
@@ -176,7 +174,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
+1 -3
View File
@@ -3,8 +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)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <iostream>
test::seed_t seed(3298597);
test::seed_t initialize_seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
+7 -11
View File
@@ -3,8 +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)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(9387);
test::seed_t initialize_seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
@@ -27,13 +25,12 @@ struct self_swap_base : public test::exception_base
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(
scope == "hash::operator(hash)" ||
scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::check_equivalent_keys(x);
}
@@ -82,13 +79,12 @@ struct swap_base : public test::exception_base
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(
scope == "hash::operator(hash)" ||
scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
#endif
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
-84
View File
@@ -1,84 +0,0 @@
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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/mpl/assert.hpp>
#include <boost/static_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_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
}
+15 -16
View File
@@ -52,29 +52,28 @@ 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 = globally_counted_object::count_;
object_count global_object_count;
}
struct counted_object
{
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
struct check_instances {
int instances;
check_instances() : instances(global_object_count.instances) {}
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
};
}
#endif
+91 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2005-2010 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,6 +69,96 @@ 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
+24 -33
View File
@@ -13,7 +13,6 @@
#include <cmath>
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#include "./allocator.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -29,16 +28,13 @@ namespace test
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
// Boost.Test was reporting memory leaks for std::set on g++-3.3.
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>,
test::malloc_allocator<key_type> > found_;
std::set<key_type, std::less<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while(it != end) {
// First test that the current key has not occured before, required
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
@@ -65,37 +61,32 @@ namespace test
std::cerr<<x1.count(key)<<","<<count<<"\n";
}
// 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 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;
}
}
};
// Finally, check that size matches up.
if(x1.size() != size)
if(x1.size() != size) {
BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout<<x1.size()<<"/"<<size<<std::endl;
}
float load_factor =
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
using namespace std;
+3 -3
View File
@@ -219,14 +219,14 @@ namespace test
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator start, const_iterator end) {
void erase(const_iterator i, const_iterator j) {
node** ptr = &data_.first_;
while(*ptr != start.ptr_) {
while(*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != end.ptr_) {
while(*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
+19 -29
View File
@@ -8,10 +8,8 @@
#include <memory>
#include <map>
#include <boost/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include "../helpers/test.hpp"
namespace test
@@ -53,30 +51,10 @@ namespace test
}
};
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
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;
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> >
> allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
@@ -137,9 +115,9 @@ namespace test
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag)
int tag, bool check_tag_ = true)
{
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
@@ -147,7 +125,7 @@ namespace test
} else {
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
BOOST_TEST(pos->second.tag_ == tag);
if (check_tag_) BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_TEST(count_allocations > 0);
@@ -168,6 +146,18 @@ 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
+10 -49
View File
@@ -8,72 +8,33 @@
#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<
BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type> {};
template <class Container>
struct is_map
: public boost::mpl::not_<is_set<Container> > {};
struct yes_type { char x[100]; };
struct no_type { char x[200]; };
template <class V, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(yes_type));
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class Container>
struct has_equivalent_keys
template <class V, class H, class P, class A>
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class K, class M, class H, class P, class A>
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
+10
View File
@@ -0,0 +1,10 @@
// 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
+6 -4
View File
@@ -8,7 +8,7 @@
#include "./list.hpp"
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/detail/select_type.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
@@ -81,10 +81,12 @@ namespace test
template <class X>
struct unordered_generator_base
: public boost::mpl::if_<
test::is_set<X>,
: public boost::detail::if_true<
test::is_set<X>::value
>::BOOST_NESTED_TEMPLATE then<
test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
test::unordered_generator_map<X>
>
{
};
-1
View File
@@ -8,7 +8,6 @@
#include <boost/config.hpp>
#include <iterator>
#include "./metafunctions.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
+45 -63
View File
@@ -13,9 +13,6 @@
#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"
@@ -25,21 +22,17 @@
namespace test
{
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<
std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
template <typename X>
struct equals_to_compare
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type>
type;
};
template <class X>
struct equals_to_compare
: public boost::mpl::eval_if<
boost::is_same<X, test::equal_to>,
boost::mpl::identity<test::less>,
equals_to_compare2<X>
>
template <>
struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
template <class X1, class X2>
@@ -67,51 +60,40 @@ namespace test
values2.begin(), test::equivalent));
}
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 <typename X>
struct ordered_base;
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_set<V, H, P, A> >
{
typedef std::set<V,
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 V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
{
typedef std::map<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
{
typedef std::multimap<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
class ordered : public ordered_base<X>::type
@@ -124,8 +106,8 @@ namespace test
: base()
{}
explicit ordered(key_compare const& compare)
: base(compare)
explicit ordered(key_compare const& kc)
: base(kc)
{}
void compare(X const& x)
@@ -143,10 +125,10 @@ namespace test
}
template <class It>
void insert_range(It begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
}
}
};
+317
View File
@@ -0,0 +1,317 @@
// 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_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
+30 -25
View File
@@ -13,27 +13,28 @@
#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:
@@ -249,7 +250,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator default constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
@@ -257,7 +258,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator template copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
allocator(allocator const& x) : tag_(x.tag_)
@@ -265,11 +266,11 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
~allocator() {
detail::tracker.allocator_unref();
test::detail::tracker.allocator_unref();
}
allocator& operator=(allocator const& x) {
@@ -307,7 +308,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -323,7 +324,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -333,32 +334,32 @@ namespace exception
{
//::operator delete((void*) p);
if(p) {
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
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(allocator::construct(pointer, T)) {
UNORDERED_SCOPE(allocator::construct(T*, T)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(t);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(std::forward<Args>(args)...);
new(p) T(boost::forward<Args>(args)...);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(pointer p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
void destroy(T* p) {
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
@@ -368,6 +369,10 @@ 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>
+200 -30
View File
@@ -11,6 +11,8 @@
#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
#include <cstddef>
#include <boost/move/move.hpp>
#include <utility>
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -21,21 +23,40 @@ namespace test
{
namespace minimal
{
class destructible;
class copy_constructible;
class copy_constructible_equality_comparable;
class default_copy_constructible;
class assignable;
struct ampersand_operator_used {};
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() {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
};
class copy_constructible
{
public:
static copy_constructible create() { return copy_constructible(); }
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
private:
@@ -46,9 +67,7 @@ namespace minimal
class copy_constructible_equality_comparable
{
public:
static copy_constructible_equality_comparable create() {
return copy_constructible_equality_comparable();
}
copy_constructible_equality_comparable(constructor_param const&) {}
copy_constructible_equality_comparable(
copy_constructible_equality_comparable const&)
@@ -63,6 +82,7 @@ namespace minimal
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
bool operator==(
@@ -82,10 +102,7 @@ namespace minimal
class default_copy_constructible
{
public:
static default_copy_constructible create()
{
return default_copy_constructible();
}
default_copy_constructible(constructor_param const&) {}
default_copy_constructible()
{
@@ -98,62 +115,154 @@ namespace minimal
~default_copy_constructible()
{
}
private:
default_copy_constructible& operator=(
default_copy_constructible const&);
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
};
class assignable
{
public:
static assignable create() { return assignable(); }
assignable(constructor_param const&) {}
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
private:
assignable() {}
// TODO: This messes up a concept check in the tests.
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
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));
~movable1() {}
};
#if !defined(BOOST_NO_RVALUE_REFERENCES)
class movable2
{
public:
movable2(constructor_param const&) {}
explicit movable2(movable_init) {}
movable2(movable2&&) {}
~movable2() {}
private:
movable2() {}
movable2(movable2 const&);
movable2& operator=(movable2 const&);
};
#else
typedef movable1 movable2;
#endif
template <class T>
class hash
{
public:
static hash create() { return hash<T>(); }
hash(constructor_param const&) {}
hash() {}
hash(hash const&) {}
hash& operator=(hash const&) { return *this; }
~hash() {}
std::size_t operator()(T const&) const { return 0; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
class equal_to
{
public:
static equal_to create() { return equal_to<T>(); }
equal_to(constructor_param const&) {}
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; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
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_; }
@@ -175,19 +284,16 @@ 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_; }
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_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
class const_ptr
{
friend class allocator<T>;
friend struct const_void_ptr;
T const* ptr_;
@@ -195,6 +301,7 @@ 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_; }
@@ -208,19 +315,15 @@ 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_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -229,6 +332,8 @@ 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;
@@ -260,15 +365,15 @@ namespace minimal
::operator delete((void*) p.ptr_);
}
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
new((void*)p.ptr_) T(std::forward<Args>(args)...);
#if !defined(BOOST_NO_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(pointer p) { ((T*)p.ptr_)->~T(); }
void destroy(T* p) { p->~T(); }
size_type max_size() const { return 1000; }
@@ -278,6 +383,8 @@ namespace minimal
#else
private: allocator& operator=(allocator const&);
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -296,6 +403,69 @@ 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_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>&)
{
}
}
}
+144 -65
View File
@@ -9,24 +9,27 @@
#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 implicitly_convertible;
class hash;
class less;
class equal_to;
template <class T> class allocator;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*);
implicitly_convertible generate(implicitly_convertible const*);
class object : globally_counted_object
inline void ignore_variable(void const*) {}
class object : private counted_object
{
friend class hash;
friend class equal_to;
@@ -64,6 +67,31 @@ namespace test
}
};
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_);
}
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_<<")";
}
};
class hash
{
int type_;
@@ -158,25 +186,100 @@ 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 require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker<std::allocator<int> > tracker;
}
}
// allocator1 and allocator2 are pretty similar.
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs
template <class T>
class allocator
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 allocator2
{
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
# else
template <class> friend class allocator;
template <class> friend class allocator2;
# endif
int tag_;
public:
@@ -188,26 +291,26 @@ namespace test
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
template <class U> struct rebind { typedef allocator2<U> other; };
explicit allocator(int t = 0) : tag_(t)
explicit allocator2(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x)
template <class Y> allocator2(allocator2<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator(allocator const& x)
allocator2(allocator2 const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator()
~allocator2()
{
detail::tracker.allocator_unref();
}
@@ -241,19 +344,19 @@ namespace test
::operator delete((void*) p);
}
void construct(pointer p, T const& t) {
void construct(T* p, T const& t) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(std::forward<Args>(args)...);
new(p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(pointer p) {
void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
@@ -262,61 +365,37 @@ namespace test
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator const& x) const
bool operator==(allocator2 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator const& x) const
bool operator!=(allocator2 const& x) const
{
return tag_ != x.tag_;
}
enum {
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
template <class T>
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y,
bool equivalent_impl(allocator1<T> const& x, allocator1<T> const& y,
test::derived_type)
{
return x == y;
}
#if BOOST_WORKAROUND(__GNUC__, < 3)
void swap(test::object& x, test::object& y) {
test::object tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::hash& x, test::hash& y) {
test::hash tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::less& x, test::less& y) {
test::less tmp;
tmp = x;
x = y;
y = tmp;
}
void swap(test::equal_to& x, test::equal_to& y) {
test::equal_to tmp;
tmp = x;
x = y;
y = tmp;
}
template <class T>
void swap(test::allocator<T>& x, test::allocator<T>& y) {
test::allocator<T> tmp;
tmp = x;
x = y;
y = tmp;
bool equivalent_impl(allocator2<T> const& x, allocator2<T> const& y,
test::derived_type)
{
return x == y;
}
#endif
}
#endif
+30 -9
View File
@@ -9,19 +9,20 @@ project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>gcc:<define>_GLIBCXX_DEBUG
<toolset>darwin:<define>_GLIBCXX_DEBUG
<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
;
test-suite unordered
:
[ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ]
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
@@ -30,9 +31,12 @@ test-suite unordered
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
[ run copy_tests.cpp ]
[ run move_tests.cpp : : : <test-info>always_show_run_output ]
[ run move_tests.cpp ]
[ run assign_tests.cpp ]
[ run insert_tests.cpp ]
[ run insert_tests.cpp : :
: <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
: insert_deprecated ]
[ run insert_stable_tests.cpp ]
[ run unnecessary_copy_tests.cpp ]
[ run erase_tests.cpp ]
@@ -43,5 +47,22 @@ test-suite unordered
[ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ]
[ run equality_tests.cpp ]
[ run swap_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
[ run equality_deprecated.cpp ]
[ run swap_tests.cpp ]
[ run compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
+254
View File
@@ -0,0 +1,254 @@
// 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();
}
+102 -21
View File
@@ -4,20 +4,25 @@
// 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 seed(96785);
test::seed_t initialize_seed(96785);
template <class T>
void assign_tests1(T*,
@@ -28,6 +33,8 @@ void assign_tests1(T*,
std::cerr<<"assign_tests1.1\n";
{
test::check_instances check_;
T x;
x = x;
BOOST_TEST(x.empty());
@@ -37,6 +44,8 @@ void assign_tests1(T*,
std::cerr<<"assign_tests1.2\n";
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
@@ -48,9 +57,12 @@ void assign_tests1(T*,
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() == y.max_load_factor());
BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf);
}
}
@@ -64,9 +76,13 @@ void assign_tests2(T*,
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);
@@ -78,44 +94,111 @@ void assign_tests2(T*,
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));
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
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(x2, v1);
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multiset_prop_assign;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multimap_prop_assign;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multiset_no_prop_assign;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(assign_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
template <typename T>
bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
UNORDERED_AUTO_TEST(check_traits)
{
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
}
UNORDERED_TEST(assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
((default_generator)(generate_collisions))
)
UNORDERED_TEST(assign_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
UNORDERED_TEST(assign_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
)
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -130,9 +213,7 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
+12 -1
View File
@@ -4,29 +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_map.hpp>
#include "../helpers/postfix.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;
}
}
+20 -13
View File
@@ -4,9 +4,10 @@
// 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"
@@ -20,11 +21,13 @@
namespace bucket_tests {
test::seed_t seed(54635);
test::seed_t initialize_seed(54635);
template <class X>
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);
@@ -65,20 +68,24 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(test_multimap)))
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
UNORDERED_TEST(tests, ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)))
}
+78 -24
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,6 +17,19 @@
// 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_copy_constructible,
@@ -32,16 +45,21 @@ template class boost::unordered_multimap<
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> value_type;
value_type value(
test::minimal::assignable::create(),
test::minimal::copy_constructible::create());
value_type value(x, x);
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::copy_constructible,
@@ -50,12 +68,18 @@ UNORDERED_AUTO_TEST(test0)
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::copy_constructible,
@@ -64,35 +88,49 @@ UNORDERED_AUTO_TEST(test0)
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::assignable const,
typedef std::pair<
test::minimal::copy_constructible_equality_comparable 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::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > map;
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
@@ -106,30 +144,47 @@ 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_test(map, value, map_value, hash, equal_to);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
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_test(multimap, value, map_value, hash, equal_to);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::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();
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> map_value_type;
@@ -146,8 +201,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, copy_constructible);
unordered_test(map, assignable, map_value, hash, equal_to);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
boost::unordered_map<
test::minimal::assignable,
@@ -171,7 +225,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, copy_constructible);
unordered_test(multimap, assignable, map_value, hash, equal_to);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
}
RUN_TESTS()
+173 -23
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,6 +17,17 @@
// 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>,
@@ -30,10 +41,19 @@ template class boost::unordered_multiset<
UNORDERED_AUTO_TEST(test0)
{
test::minimal::assignable assignable = test::minimal::assignable::create();
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
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>,
@@ -41,10 +61,18 @@ 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>,
@@ -52,32 +80,45 @@ 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::assignable value_type;
typedef test::minimal::copy_constructible_equality_comparable value_type;
boost::unordered_set<int> int_set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > set;
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> > multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
}
@@ -87,33 +128,49 @@ UNORDERED_AUTO_TEST(test1)
std::equal_to<int> equal_to;
int value = 0;
std::cout<<"Test unordered_set.\n";
std::cout<<"Test unordered_set." << std::endl;
boost::unordered_set<int> set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> set2;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_test(set, value, value, hash, equal_to);
unordered_copyable_test(set, value, value, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
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;
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_test(multiset, value, value, hash, equal_to);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::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();
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
std::cout<<"Test unordered_set.\n";
@@ -125,7 +182,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_test(set, assignable, assignable, hash, equal_to);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
@@ -137,7 +194,100 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_test(multiset, assignable, assignable, hash, equal_to);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
}
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);
}
RUN_TESTS()
+209 -95
View File
@@ -16,18 +16,19 @@
#pragma warning(pop)
#endif
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/limits.hpp>
#include <boost/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&)
@@ -53,42 +54,38 @@ void container_test(X& r, T const&)
// value_type
BOOST_MPL_ASSERT((boost::is_same<T, value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
boost::function_requires<boost::CopyConstructibleConcept<X> >();
// reference_type / const_reference_type
BOOST_MPL_ASSERT((boost::is_same<T&, reference>));
BOOST_MPL_ASSERT((boost::is_same<T const&, const_reference>));
BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
// iterator
boost::function_requires<boost::InputIteratorConcept<iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, iterator_value_type>));
BOOST_MPL_ASSERT((boost::is_convertible<iterator, const_iterator>));
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
// const_iterator
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, const_iterator_value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
// difference_type
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>));
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));
// size_type
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>));
BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
BOOST_STATIC_ASSERT(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...
@@ -109,30 +106,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;
X* ptr = new X();
X& a1 = *ptr;
(&a1)->~X();
X const a_const;
test::check_return_type<iterator>::equals(a.begin());
test::check_return_type<const_iterator>::equals(a_const.begin());
test::check_return_type<const_iterator>::equals(a.cbegin());
test::check_return_type<const_iterator>::equals(a_const.cbegin());
test::check_return_type<iterator>::equals(a.end());
test::check_return_type<const_iterator>::equals(a_const.end());
test::check_return_type<const_iterator>::equals(a.cend());
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());
// Allocator
@@ -146,13 +128,58 @@ void container_test(X& r, T const&)
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_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());
test::check_return_type<const_iterator>::equals(a.cbegin());
test::check_return_type<const_iterator>::equals(a_const.cbegin());
test::check_return_type<iterator>::equals(a.end());
test::check_return_type<const_iterator>::equals(a_const.end());
test::check_return_type<const_iterator>::equals(a.cend());
test::check_return_type<const_iterator>::equals(a_const.cend());
a.swap(b);
boost::swap(a, b);
test::check_return_type<size_type>::equals(a.size());
test::check_return_type<size_type>::equals(a.max_size());
test::check_return_type<bool>::convertible(a.empty());
// Allocator
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
}
template <class X, class Key>
void unordered_set_test(X&, Key const&)
{
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_MPL_ASSERT((boost::is_same<value_type, key_type>));
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
}
template <class X, class Key, class T>
@@ -160,8 +187,9 @@ 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_MPL_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >));
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
r.insert(std::pair<Key const, T>(k, v));
@@ -180,6 +208,8 @@ 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>
@@ -211,9 +241,11 @@ 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 T, class Hash, class Pred>
void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
template <class X, class Key, class Hash, class Pred>
void unordered_test(X& x, Key& k, 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;
@@ -276,36 +308,36 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
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<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
//boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
test::check_return_type<std::size_t>::equals(hf(k));
BOOST_MPL_ASSERT((boost::is_same<Pred, key_equal>));
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
test::check_return_type<bool>::convertible(eq(k, k));
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
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_STATIC_ASSERT((boost::is_same<local_iterator_category,
iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>::value));
boost::function_requires<
boost::InputIteratorConcept<const_local_iterator> >();
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>));
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));
X(10, hf, eq);
X a(10, hf, eq);
@@ -316,45 +348,18 @@ void unordered_test(X&, Key& k, T& t, 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));
@@ -388,9 +393,118 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
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_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);
}
+77 -19
View File
@@ -1,12 +1,13 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2006-2010 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"
@@ -15,11 +16,9 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
namespace constructor_tests {
test::seed_t seed(356730);
test::seed_t initialize_seed(356730);
template <class T>
void constructor_tests1(T*,
@@ -31,6 +30,8 @@ void constructor_tests1(T*,
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,6 +42,8 @@ void constructor_tests1(T*,
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
@@ -52,6 +55,8 @@ void constructor_tests1(T*,
std::cerr<<"Construct 3\n";
{
test::check_instances check_;
T x(2000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
@@ -63,6 +68,8 @@ void constructor_tests1(T*,
std::cerr<<"Construct 4\n";
{
test::check_instances check_;
T x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -73,6 +80,8 @@ void constructor_tests1(T*,
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);
@@ -85,6 +94,8 @@ void constructor_tests1(T*,
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);
@@ -97,6 +108,8 @@ void constructor_tests1(T*,
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);
@@ -109,6 +122,8 @@ void constructor_tests1(T*,
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));
@@ -120,6 +135,8 @@ void constructor_tests1(T*,
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));
@@ -130,6 +147,8 @@ void constructor_tests1(T*,
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);
@@ -142,6 +161,8 @@ void constructor_tests1(T*,
std::cerr<<"Construct 11\n";
{
test::check_instances check_;
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -167,6 +188,7 @@ void constructor_tests2(T*,
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));
@@ -177,6 +199,7 @@ void constructor_tests2(T*,
std::cerr<<"Construct 2\n";
{
test::check_instances check_;
T x(100, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
@@ -188,6 +211,7 @@ void constructor_tests2(T*,
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));
@@ -199,6 +223,7 @@ void constructor_tests2(T*,
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);
@@ -212,6 +237,7 @@ void constructor_tests2(T*,
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);
@@ -223,6 +249,7 @@ void constructor_tests2(T*,
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);
@@ -234,6 +261,7 @@ void constructor_tests2(T*,
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);
@@ -245,6 +273,7 @@ void constructor_tests2(T*,
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();
@@ -260,8 +289,24 @@ void constructor_tests2(T*,
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);
@@ -273,11 +318,13 @@ void constructor_tests2(T*,
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::cerr<<"Initializer list construct 1\n";
{
test::check_instances check_;
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -287,6 +334,8 @@ void constructor_tests2(T*,
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);
@@ -297,6 +346,8 @@ void constructor_tests2(T*,
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);
@@ -307,6 +358,8 @@ void constructor_tests2(T*,
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);
@@ -317,6 +370,8 @@ void constructor_tests2(T*,
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);
@@ -347,24 +402,28 @@ void map_constructor_test(T* = 0,
test::check_equivalent_keys(x);
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(constructor_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
@@ -374,10 +433,10 @@ UNORDERED_TEST(constructor_tests2,
)
UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
((test_map_std_alloc)(test_map)(test_multimap))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -388,8 +447,7 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
+83 -11
View File
@@ -4,17 +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 "../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 seed(9063);
test::seed_t initialize_seed(9063);
namespace copy_tests
{
@@ -23,11 +25,15 @@ template <class T>
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());
@@ -35,20 +41,28 @@ void copy_construct_tests1(T*,
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
@@ -61,6 +75,8 @@ void copy_construct_tests1(T*,
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);
}
}
@@ -75,8 +91,12 @@ void copy_construct_tests2(T* ptr,
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());
@@ -84,10 +104,14 @@ void copy_construct_tests2(T* ptr,
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());
@@ -95,10 +119,13 @@ void copy_construct_tests2(T* ptr,
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);
@@ -106,10 +133,14 @@ void copy_construct_tests2(T* ptr,
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);
@@ -117,32 +148,73 @@ void copy_construct_tests2(T* ptr,
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::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
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;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
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)
)
)
UNORDERED_TEST(copy_construct_tests2,
((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)
)
((default_generator)(generate_collisions))
)
+174
View File
@@ -0,0 +1,174 @@
// Copyright 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_UNORDERED_DEPRECATED_EQUALITY
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
namespace equality_tests
{
struct mod_compare
{
bool alt_hash_;
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
bool operator()(int x, int y) const
{
return x % 1000 == y % 1000;
}
int operator()(int x) const
{
return alt_hash_ ? x % 250 : (x + 5) % 250;
}
};
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
boost::unordered_multiset<int, mod_compare, mod_compare> \
set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost::unordered_map<int, int, mod_compare, mod_compare> \
map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
{ \
boost::unordered_multimap<int, int, mod_compare, mod_compare> \
map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
UNORDERED_AUTO_TEST(equality_size_tests)
{
boost::unordered_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
UNORDERED_AUTO_TEST(equality_key_value_tests)
{
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2))
UNORDERED_EQUALITY_SET_TEST((2), ==, (2))
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)))
}
UNORDERED_AUTO_TEST(equality_collision_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST(
(1)(501), ==, (501)(1))
}
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=,
((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==,
((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST(equality_map_value_test)
{
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), ==, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST(equality_different_hash_test)
{
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_TEST(set1 == set2);
set1.insert(1); set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2); set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10); set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+15 -5
View File
@@ -4,9 +4,10 @@
// 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"
@@ -136,15 +137,25 @@ 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)))
((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), ==, (1001))
(1), !=, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
);
}
// Test that equality still works when the two containers have
@@ -165,7 +176,6 @@ namespace equality_tests
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+2 -1
View File
@@ -4,9 +4,10 @@
// 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>
+4 -3
View File
@@ -7,8 +7,9 @@
// 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 "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include <set>
@@ -52,10 +53,10 @@ struct collision2_hash
typedef boost::unordered_multimap<int, int,
collision_hash, std::equal_to<int>,
test::allocator<std::pair<int const, int> > > collide_map;
test::allocator1<std::pair<int const, int> > > collide_map;
typedef boost::unordered_multimap<int, int,
collision2_hash, std::equal_to<int>,
test::allocator<std::pair<int const, int> > > collide_map2;
test::allocator2<std::pair<int const, int> > > collide_map2;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
+21 -6
View File
@@ -4,9 +4,10 @@
// 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"
@@ -20,7 +21,7 @@
namespace erase_tests
{
test::seed_t seed(85638);
test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*,
@@ -28,6 +29,8 @@ void erase_tests1(Container*,
{
std::cerr<<"Erase by key.\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
@@ -44,6 +47,8 @@ void erase_tests1(Container*,
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();
@@ -64,6 +69,8 @@ void erase_tests1(Container*,
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();
@@ -96,6 +103,8 @@ void erase_tests1(Container*,
std::cerr<<"erase(ranges).\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
@@ -118,6 +127,8 @@ void erase_tests1(Container*,
std::cerr<<"quick_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();
@@ -136,6 +147,8 @@ void erase_tests1(Container*,
std::cerr<<"quick_erase(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
@@ -169,6 +182,8 @@ void erase_tests1(Container*,
std::cerr<<"clear().\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
@@ -181,16 +196,16 @@ void erase_tests1(Container*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+11 -6
View File
@@ -4,9 +4,10 @@
// 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,7 +17,7 @@
namespace find_tests
{
test::seed_t seed(78937);
test::seed_t initialize_seed(78937);
template <class X>
void find_tests1(X*, test::random_generator generator = test::default_generator)
@@ -24,6 +25,8 @@ 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;
@@ -69,6 +72,8 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
}
{
test::check_instances check_;
X x;
test::random_values<X> v2(5, generator);
@@ -137,16 +142,16 @@ void find_compatible_keys_test(X*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+28 -11
View File
@@ -4,40 +4,57 @@
// 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"
typedef boost::unordered_map<int, int> int_map;
void call_swap(int_map& x, int_map& y) {
template <typename T>
void call_swap(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
swap(x,y);
}
bool call_equals(int_map& x, int_map& y) {
template <typename T>
bool call_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
return x == y;
}
bool call_not_equals(int_map& x, int_map& y) {
template <typename T>
bool call_not_equals(boost::unordered_map<T,T>& x,
boost::unordered_map<T,T>& y)
{
return x != y;
}
typedef boost::unordered_multimap<int, int> int_multimap;
void call_swap(int_multimap& x, int_multimap& y) {
template <typename T>
void call_swap(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
swap(x,y);
}
bool call_equals(int_multimap& x, int_multimap& y) {
template <typename T>
bool call_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
return x == y;
}
bool call_not_equals(int_multimap& x, int_multimap& y) {
template <typename T>
bool call_not_equals(boost::unordered_multimap<T,T>& x,
boost::unordered_multimap<T,T>& y)
{
return x != y;
}
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
int_map x, y;
x[1] = 2;
+28 -11
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,36 +16,53 @@ template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*);
typedef boost::unordered_set<int> int_set;
void call_swap(int_set& x, int_set& y) {
template<typename T>
void call_swap(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
swap(x,y);
}
bool call_equals(int_set& x, int_set& y) {
template<typename T>
bool call_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
return x == y;
}
bool call_not_equals(int_set& x, int_set& y) {
template<typename T>
bool call_not_equals(boost::unordered_set<T>& x,
boost::unordered_set<T>& y)
{
return x != y;
}
typedef boost::unordered_multiset<int> int_multiset;
void call_swap(int_multiset& x, int_multiset& y) {
template<typename T>
void call_swap(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
swap(x,y);
}
bool call_equals(int_multiset& x, int_multiset& y) {
template<typename T>
bool call_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
return x == y;
}
bool call_not_equals(int_multiset& x, int_multiset& y) {
template<typename T>
bool call_not_equals(boost::unordered_multiset<T>& x,
boost::unordered_multiset<T>& y)
{
return x != y;
}
#include "../helpers/test.hpp"
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0))
== sizeof(true_type));
+32 -26
View File
@@ -4,35 +4,36 @@
// 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 test
namespace incomplete_test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T>
struct malloc_allocator;
template <class T> struct allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > map;
allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > multimap;
allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
malloc_allocator<value> > set;
allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
malloc_allocator<value> > multiset;
allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
@@ -47,12 +48,17 @@ namespace 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() {}
#include "../helpers/allocator.hpp"
template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
@@ -60,19 +66,19 @@ namespace test
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
malloc_allocator<std::pair<struct1 const, struct1> > > x;
allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
malloc_allocator<std::pair<struct2 const, struct2> > > x;
allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
malloc_allocator<struct3> > x;
allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
malloc_allocator<struct4> > x;
allocator<struct4> > x;
};
// Now define the value type.
@@ -81,15 +87,15 @@ namespace test
// Create some instances.
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
test::struct4 c4;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
@@ -111,7 +117,7 @@ namespace test
void use_types()
{
test::value x;
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
@@ -143,5 +149,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.
test::use_types();
incomplete_test::use_types();
}
+2 -1
View File
@@ -4,9 +4,10 @@
// 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>
+187 -31
View File
@@ -1,12 +1,13 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2006-2010 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/next_prior.hpp>
#include "../objects/test.hpp"
@@ -20,12 +21,14 @@
namespace insert_tests {
test::seed_t seed(243432);
test::seed_t initialize_seed(243432);
template <class X>
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;
@@ -52,7 +55,7 @@ void unique_insert_tests1(X*,
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -65,6 +68,9 @@ void equivalent_insert_tests1(X*,
{
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);
@@ -83,7 +89,7 @@ void equivalent_insert_tests1(X*,
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -102,6 +108,8 @@ void insert_tests2(X*,
std::cerr<<"insert(begin(), value) tests.\n";
{
test::check_instances check_;
X x;
tracker_type tracker = test::create_ordered(x);
@@ -118,7 +126,7 @@ void insert_tests2(X*,
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -128,6 +136,8 @@ void insert_tests2(X*,
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);
@@ -145,7 +155,7 @@ void insert_tests2(X*,
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -155,6 +165,8 @@ void insert_tests2(X*,
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);
@@ -172,7 +184,7 @@ void insert_tests2(X*,
BOOST_TEST(*pos == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -182,6 +194,8 @@ void insert_tests2(X*,
std::cerr<<"insert single item range tests.\n";
{
test::check_instances check_;
X x;
tracker_type tracker = test::create_ordered(x);
@@ -197,7 +211,7 @@ void insert_tests2(X*,
tracker.insert(*it);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -207,6 +221,8 @@ void insert_tests2(X*,
std::cerr<<"insert range tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
@@ -219,6 +235,8 @@ void insert_tests2(X*,
std::cerr<<"insert input iterator range tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
@@ -229,6 +247,20 @@ void insert_tests2(X*,
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);
}
}
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
@@ -263,7 +295,7 @@ void unique_emplace_tests1(X*,
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -294,7 +326,7 @@ void equivalent_emplace_tests1(X*,
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -323,7 +355,7 @@ void map_tests(X*, test::random_generator generator = test::default_generator)
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
@@ -339,6 +371,8 @@ void map_insert_range_test1(X*,
{
std::cerr<<"map_insert_range_test1\n";
test::check_instances check_;
typedef test::list<
std::pair<
BOOST_DEDUCED_TYPENAME X::key_type,
@@ -359,11 +393,13 @@ void map_insert_range_test2(X*,
{
std::cerr<<"map_insert_range_test2\n";
test::check_instances check_;
typedef test::list<
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, int>
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, test::implicitly_convertible>
> list;
test::random_values<
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, int>
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, test::implicitly_convertible>
> v(1000, generator);
list l(v.begin(), v.end());
@@ -374,43 +410,50 @@ void map_insert_range_test2(X*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(unique_insert_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_insert_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(insert_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
UNORDERED_TEST(unique_emplace_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_emplace_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
#endif
@@ -421,17 +464,16 @@ UNORDERED_TEST(map_tests,
)
UNORDERED_TEST(map_insert_range_test1,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
@@ -479,6 +521,120 @@ 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));
#if defined (BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
x.emplace(1);
BOOST_TEST(x.find(1) != x.end() &&
x.find(1)->second == overloaded_constructor());
x.emplace(4, 5, 6);
BOOST_TEST(x.find(4) != x.end() &&
x.find(4)->second == overloaded_constructor(5, 6));
x.emplace(7, 8, 9, 10);
BOOST_TEST(x.find(7) != x.end() &&
x.find(7)->second == overloaded_constructor(8, 9, 10));
#endif
}
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);
}
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(boost::unordered::piecewise_construct, 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(boost::unordered::piecewise_construct, 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));
}
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,
+4 -3
View File
@@ -4,9 +4,10 @@
// 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"
@@ -19,7 +20,7 @@
namespace load_factor_tests
{
test::seed_t seed(783656);
test::seed_t initialize_seed(783656);
template <class X>
void set_load_factor_tests(X* = 0)
@@ -51,7 +52,7 @@ void insert_test(X*, float mlf,
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
x.insert(*it);
if(old_size + 1 < b * old_bucket_count)
if(static_cast<double>(old_size + 1) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
}
+95
View File
@@ -0,0 +1,95 @@
// 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();
}
+236 -16
View File
@@ -4,19 +4,30 @@
// 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 seed(98624);
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template<class T>
T empty(T*) {
@@ -54,6 +65,8 @@ namespace move_tests
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));
@@ -64,6 +77,8 @@ namespace move_tests
}
{
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
@@ -80,11 +95,13 @@ namespace move_tests
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 defined(BOOST_HAS_NRVO)
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
@@ -104,6 +121,8 @@ 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)
@@ -118,6 +137,8 @@ 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);
@@ -130,16 +151,23 @@ 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_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_set<T>::value ? 25 : 50));
BOOST_TEST(count.instances == test::global_object_count.instances);
#else
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 50 : 25));
(test::is_set<T>::value ? 50 : 100));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
@@ -149,34 +177,226 @@ 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 = test::default_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::allocator<test::object> >* test_set;
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
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;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(move_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
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)
)
)
UNORDERED_TEST(move_assign_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)
)
)
UNORDERED_TEST(move_construct_tests2,
((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)
)
)
}
RUN_TESTS()
+80 -3
View File
@@ -4,9 +4,10 @@
// 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"
@@ -14,12 +15,13 @@
namespace rehash_tests
{
test::seed_t seed(2974);
test::seed_t initialize_seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{
return x.bucket_count() > x.size() / x.max_load_factor() &&
return static_cast<double>(x.bucket_count()) >
static_cast<double>(x.size()) / x.max_load_factor() &&
x.bucket_count() >= n;
}
@@ -98,6 +100,75 @@ void rehash_test1(X* = 0,
tracker.compare(x);
}
template <class X>
void reserve_test1(X* = 0,
test::random_generator generator = test::default_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(i);
// 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* = 0,
test::random_generator generator = test::default_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(i);
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<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
@@ -115,6 +186,12 @@ UNORDERED_TEST(rehash_empty_test3,
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
}
+2 -1
View File
@@ -6,9 +6,10 @@
// 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>
+116 -35
View File
@@ -4,22 +4,28 @@
// 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 seed(783472);
test::seed_t initialize_seed(783472);
template <class X>
void swap_test_impl(X& x1, X& x2)
@@ -37,16 +43,22 @@ template <class X>
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);
@@ -54,6 +66,8 @@ void swap_tests1(X*, test::random_generator generator = test::default_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);
@@ -72,12 +86,16 @@ void swap_tests2(X* ptr = 0,
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));
@@ -85,6 +103,8 @@ void swap_tests2(X* ptr = 0,
}
{
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));
@@ -92,57 +112,118 @@ void swap_tests2(X* ptr = 0,
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));
swap_test_impl(x, y);
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator())
{
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));
swap_test_impl(x, y);
swap_test_impl(x, y);
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator())
{
swap_test_impl(x, y);
swap_test_impl(x, y);
}
}
#endif
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
UNORDERED_TEST(swap_tests1,
((test_set)(test_multiset)(test_map)(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;
UNORDERED_TEST(swap_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
)
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;
}
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)
))
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)
))
}
RUN_TESTS()
+172 -32
View File
@@ -4,15 +4,20 @@
// 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;
count_copies() : tag_(0) { ++copies; }
@@ -31,14 +36,25 @@ namespace unnecessary_copy_tests
: tag_(x.tag_) { ++copies; }
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
#if !defined(BOOST_NO_RVALUE_REFERENCES)
count_copies(count_copies&& x) : tag_(x.tag_) {
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_) {
x.tag_ = -1; ++moves;
}
#endif
int tag_;
private:
count_copies& operator=(count_copies const&);
count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
{
tag_ = p.tag_;
++copies;
return *this;
}
count_copies& operator=(BOOST_RV_REF(count_copies) p) //Move assignment
{
tag_ = p.tag_;
++moves;
return *this;
}
int tag_;
};
bool operator==(count_copies const& x, count_copies const& y) {
@@ -68,31 +84,37 @@ namespace unnecessary_copy_tests
}
#define COPY_COUNT(n) \
if(count_copies::copies != n) { \
if(::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " << count_copies::copies \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: " << n << std::endl; \
}
#define MOVE_COUNT(n) \
if(count_copies::moves != n) { \
if(::unnecessary_copy_tests::count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " << count_copies::moves \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< " expecting: " <<n << std::endl; \
}
#define COPY_COUNT_RANGE(a, b) \
if(count_copies::copies < a || count_copies::copies > b) { \
if(::unnecessary_copy_tests::count_copies::copies < a || \
::unnecessary_copy_tests::count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " << count_copies::copies \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define MOVE_COUNT_RANGE(a, b) \
if(count_copies::moves < a || count_copies::moves > b) { \
if(::unnecessary_copy_tests::count_copies::moves < a || \
::unnecessary_copy_tests::count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " << count_copies::copies \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
@@ -136,7 +158,7 @@ namespace unnecessary_copy_tests
reset();
T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#if !defined(BOOST_NO_RVALUE_REFERENCES)
COPY_COUNT(1);
#else
COPY_COUNT(2);
@@ -148,7 +170,7 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class T>
void unnecessary_copy_emplace_move_test(T*)
{
@@ -162,11 +184,52 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
((set)(multiset)(map)(multimap)))
#endif
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(0);
x.emplace(boost::move(a));
#if defined(BOOST_NO_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT(0);
#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;
@@ -177,11 +240,19 @@ 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();
COPY_COUNT(1); MOVE_COUNT(0);
#if !defined(BOOST_NO_VARIADIC_TEMPLATES) || \
!defined(BOOST_NO_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
//
// 1 argument
@@ -197,9 +268,9 @@ namespace unnecessary_copy_tests
// copied.
reset();
x.emplace(source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(0);
COPY_COUNT(1); MOVE_COUNT(source_cost);
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
// No move should take place.
reset();
x.emplace(std::move(a));
@@ -233,6 +304,19 @@ 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.
@@ -244,10 +328,19 @@ namespace unnecessary_copy_tests
// 0 arguments
//
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// COPY_COUNT(1) would be okay here.
reset();
x.emplace();
COPY_COUNT(2); MOVE_COUNT(0);
#endif
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(),
boost::make_tuple());
COPY_COUNT(2); MOVE_COUNT(0);
//
// 1 argument
@@ -261,45 +354,92 @@ 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__) && __GNUC__ > 4) || \
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
x.emplace(a_ref);
COPY_COUNT(2); MOVE_COUNT(0);
// 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);
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_RVALUE_REFERENCES)
// No move should take place.
// (since a is already in the container)
reset();
x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
#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(0);
COPY_COUNT(2); MOVE_COUNT(source_cost * 2);
// source<count_copies> creates a single copy.
reset();
x.emplace(b.first, source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(0);
COPY_COUNT(1); MOVE_COUNT(source_cost);
reset();
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
COPY_COUNT(2); MOVE_COUNT(0);
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(boost::ref(b.first)),
boost::make_tuple(boost::ref(b.second)));
COPY_COUNT(0); MOVE_COUNT(0);
#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(__GNUC__) && __GNUC__ > 4 || \
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
reset();
x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first),
std::forward_as_tuple(b.second));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
#endif
}
}