mirror of
https://github.com/boostorg/unordered.git
synced 2026-08-06 05:34:09 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26fd286966 |
+1
-1
@@ -112,7 +112,7 @@ load factor is /required/ to be less than the maximum is following a call to
|
||||
below the max load factor, and set the maximum load factor to be the same as
|
||||
or close to the hint - unless your hint is unreasonably small or large.
|
||||
|
||||
[table:bucket_size Methods for Controlling Bucket Size
|
||||
[table Methods for Controlling Bucket Size
|
||||
[[Method] [Description]]
|
||||
|
||||
[
|
||||
|
||||
@@ -134,69 +134,4 @@ First official release.
|
||||
* 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]
|
||||
|
||||
+8
-5
@@ -1,10 +1,10 @@
|
||||
[/ Copyright 2006-2011 Daniel James.
|
||||
[/ Copyright 2006-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:comparison Comparison with Associative Containers]
|
||||
|
||||
[table:interface_differences Interface differences.
|
||||
[table Interface differences.
|
||||
[[Associative Containers] [Unordered Associative Containers]]
|
||||
|
||||
[
|
||||
@@ -66,12 +66,15 @@
|
||||
[
|
||||
[No equivalent]
|
||||
[Local iterators can be used to iterate through individual buckets.
|
||||
(The order of local iterators and iterators aren't
|
||||
(I don't think that the order of local iterators and iterators are
|
||||
required to have any correspondence.)]
|
||||
]
|
||||
[
|
||||
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
|
||||
[Can be compared using the `==` and `!=` operators.]
|
||||
[No comparison operators are defined in the standard, although
|
||||
[link unordered.rationale.equality_operators
|
||||
implementations might extend the containers to support `==` and
|
||||
`!=`].]
|
||||
]
|
||||
[
|
||||
[]
|
||||
@@ -85,7 +88,7 @@
|
||||
]
|
||||
]
|
||||
|
||||
[table:complexity_guarantees Complexity Guarantees
|
||||
[table Complexity Guarantees
|
||||
[[Operation] [Associative Containers] [Unordered Associative Containers]]
|
||||
[
|
||||
[Construction of empty container]
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
[/ Copyright 2011 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:compliance C++11 Compliance]
|
||||
|
||||
[section:move Move emulation]
|
||||
|
||||
Support for move semantics is implemented using Boost.Move. If rvalue
|
||||
references are available it will use them, but if not it uses a close,
|
||||
but imperfect emulation. On such compilers 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]
|
||||
@@ -67,10 +67,9 @@ so that the hash function doesn't need to be explicitly given:
|
||||
|
||||
See the [link hash.custom Boost.Hash documentation] for more detail on how to
|
||||
do this. Remember that it relies on extensions to the draft standard - so it
|
||||
won't work for other implementations of the unordered associative containers,
|
||||
you'll need to explicitly use Boost.Hash.
|
||||
won't work on other implementations of the unordered associative containers.
|
||||
|
||||
[table:access_methods Methods for accessing the hash and equality functions.
|
||||
[table Methods for accessing the hash and equality functions.
|
||||
[[Method] [Description]]
|
||||
|
||||
[
|
||||
|
||||
+15
-4
@@ -2,6 +2,15 @@
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[def __tr1__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
|
||||
C++ Standard Library Technical Report]]
|
||||
[def __boost-tr1__
|
||||
[@http://www.boost.org/doc/html/boost_tr1.html
|
||||
Boost.TR1]]
|
||||
[def __draft__
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
|
||||
Working Draft of the C++ Standard]]
|
||||
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
|
||||
hash table]]
|
||||
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function
|
||||
@@ -22,10 +31,12 @@ to order their elements. For some data types this is impossible to implement
|
||||
or isn't practical. In contrast, a hash table only needs an equality function
|
||||
and a hash function for the key.
|
||||
|
||||
With this in mind, unordered associative containers were added to the C++
|
||||
standard. This is an implementation of the containers described in C++11,
|
||||
with some [link unordered.compliance deviations from the standard] in
|
||||
order to work with non-C++11 compilers and libraries.
|
||||
With this in mind, the __tr1__ introduced the unordered associative containers,
|
||||
which are implemented using hash tables, and they have now been added to the
|
||||
__draft__.
|
||||
|
||||
This library supplies an almost complete implementation of the specification in
|
||||
the __draft__.
|
||||
|
||||
`unordered_set` and `unordered_multiset` are defined in the header
|
||||
<[headerref boost/unordered_set.hpp]>
|
||||
|
||||
+48
-13
@@ -44,8 +44,6 @@ bucket but there are a some serious problems with this:
|
||||
|
||||
So chained addressing is used.
|
||||
|
||||
[/ (Removing for now as this is out of date)
|
||||
|
||||
For containers with unique keys I store the buckets in a single-linked list.
|
||||
There are other possible data structures (such as a double-linked list)
|
||||
that allow for some operations to be faster (such as erasing and iteration)
|
||||
@@ -65,17 +63,6 @@ nodes in reverse order. This allows quick navigation to the end of a group (sinc
|
||||
the first element points to the last) and can be quickly updated when elements
|
||||
are inserted or erased. The main disadvantage of this approach is some hairy code
|
||||
for erasing elements.
|
||||
]
|
||||
|
||||
[/ (Starting to write up new structure, might not be ready in time)
|
||||
The node used to be stored in a linked list for each bucket but that
|
||||
didn't meet the complexity requirements for C++11, so now the nodes
|
||||
are stored in one long single linked list. But there needs a way to get
|
||||
the bucket from the node, to do that a copy of the key's hash value is
|
||||
stored in the node. Another possibility would be to store a pointer to
|
||||
the bucket, or the bucket's index, but storing the hash value allows
|
||||
some operations to be faster.
|
||||
]
|
||||
|
||||
[h2 Number of Buckets]
|
||||
|
||||
@@ -103,4 +90,52 @@ 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
File diff suppressed because it is too large
Load Diff
+244
-544
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -3,7 +3,7 @@
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[library Boost.Unordered
|
||||
[quickbook 1.5]
|
||||
[quickbook 1.4]
|
||||
[authors [James, Daniel]]
|
||||
[copyright 2003 2004 Jeremy B. Maitin-Shepard]
|
||||
[copyright 2005 2006 2007 2008 Daniel James]
|
||||
@@ -31,7 +31,6 @@
|
||||
[include:unordered buckets.qbk]
|
||||
[include:unordered hash_equality.qbk]
|
||||
[include:unordered comparison.qbk]
|
||||
[include:unordered compliance.qbk]
|
||||
[include:unordered rationale.qbk]
|
||||
[include:unordered changes.qbk]
|
||||
[xinclude ref.xml]
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
|
||||
// Copyright 2005-2011 Daniel James.
|
||||
// Copyright 2009 Pablo Halpern.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Allocator traits written by Daniel James based on Pablo Halpern's
|
||||
// implementation.
|
||||
|
||||
// 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
|
||||
@@ -15,690 +12,78 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/emplace_args.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pick which version of allocator_traits to use
|
||||
//
|
||||
// 0 = Own partial implementation
|
||||
// 1 = std::allocator_traits
|
||||
// 2 = boost::container::allocator_traits
|
||||
|
||||
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
||||
# elif defined(BOOST_MSVC)
|
||||
# if BOOST_MSVC < 1400
|
||||
// Use container's allocator_traits for older versions of Visual
|
||||
// C++ as I don't test with them.
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
|
||||
# endif
|
||||
# endif
|
||||
#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_TRAITS)
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
|
||||
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
# include <boost/detail/allocator_utilities.hpp>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some utilities for implementing allocator_traits, but useful elsewhere so
|
||||
// they're always defined.
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
|
||||
# include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Integral_constrant, true_type, false_type
|
||||
// rebind_wrap
|
||||
//
|
||||
// Uses the standard versions if available.
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
|
||||
|
||||
using std::integral_constant;
|
||||
using std::true_type;
|
||||
using std::false_type;
|
||||
// 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 <typename T, T Value>
|
||||
struct integral_constant { enum { value = Value }; };
|
||||
|
||||
typedef boost::unordered::detail::integral_constant<bool, true> true_type;
|
||||
typedef boost::unordered::detail::integral_constant<bool, false> false_type;
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Explicitly call a destructor
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Expression test mechanism
|
||||
//
|
||||
// When SFINAE expressions are available, define
|
||||
// BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
|
||||
// supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
|
||||
// can detect if a class has the specified member, but not that it has the
|
||||
// correct type, this is good enough for a passable impression of
|
||||
// allocator_traits.
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
template <typename T, unsigned int> struct expr_test;
|
||||
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
||||
template <typename U> static char for_expr_test(U const&);
|
||||
|
||||
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
|
||||
template <typename U> \
|
||||
static typename boost::unordered::detail::expr_test< \
|
||||
BOOST_PP_CAT(choice, result), \
|
||||
sizeof(boost::unordered::detail::for_expr_test(( \
|
||||
(expression), \
|
||||
0)))>::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
|
||||
template <typename U> \
|
||||
static BOOST_PP_CAT(choice, result)::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
|
||||
struct BOOST_PP_CAT(has_, name) \
|
||||
{ \
|
||||
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
|
||||
boost::unordered::detail::make< thing >().name args); \
|
||||
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
|
||||
\
|
||||
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename T> struct identity { typedef T type; };
|
||||
|
||||
# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
||||
\
|
||||
typedef typename boost::unordered::detail::identity<member>::type \
|
||||
BOOST_PP_CAT(check, count); \
|
||||
\
|
||||
template <BOOST_PP_CAT(check, count) e> \
|
||||
struct BOOST_PP_CAT(test, count) { \
|
||||
typedef BOOST_PP_CAT(choice, result) type; \
|
||||
}; \
|
||||
\
|
||||
template <class U> static typename \
|
||||
BOOST_PP_CAT(test, count)<&U::name>::type \
|
||||
test(BOOST_PP_CAT(choice, count))
|
||||
|
||||
# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
|
||||
template <class U> static BOOST_PP_CAT(choice, result)::type \
|
||||
test(BOOST_PP_CAT(choice, count))
|
||||
|
||||
# define BOOST_UNORDERED_HAS_MEMBER(name) \
|
||||
struct BOOST_PP_CAT(has_, name) \
|
||||
{ \
|
||||
struct impl { \
|
||||
struct base_mixin { int name; }; \
|
||||
struct base : public T, public base_mixin {}; \
|
||||
\
|
||||
BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
|
||||
BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
|
||||
\
|
||||
enum { value = sizeof(choice2::type) == \
|
||||
sizeof(test<base>(choose())) \
|
||||
}; \
|
||||
}; \
|
||||
\
|
||||
enum { value = impl::value }; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Allocator traits
|
||||
//
|
||||
// First our implementation, then later light wrappers around the alternatives
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
|
||||
|
||||
# include <boost/limits.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# include <boost/pointer_to_other.hpp>
|
||||
# if defined(BOOST_NO_SFINAE_EXPR)
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_UNORDERED_VARIADIC_MOVE) && \
|
||||
!defined(BOOST_NO_SFINAE_EXPR)
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||
# else
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||
# endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
|
||||
template <typename Alloc, typename T>
|
||||
template <class Alloc, class T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
|
||||
type;
|
||||
};
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
|
||||
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice1::type test(choice1, typename X::tname* = 0); \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2, void* = 0); \
|
||||
\
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
\
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
\
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
template <typename T, typename T2>
|
||||
struct sfinae : T2 {};
|
||||
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
\
|
||||
template <typename X> \
|
||||
static typename boost::unordered::detail::sfinae< \
|
||||
typename X::tname, choice1>::type \
|
||||
test(choice1); \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2); \
|
||||
\
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
\
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
\
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
|
||||
typename default_type_ ## tname<T, arg>::type
|
||||
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
|
||||
|
||||
# if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
select_on_container_copy_construction, U const, (), 0
|
||||
);
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
max_size, U const, (), 0
|
||||
);
|
||||
|
||||
# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
template <typename T, typename ValueType, typename... Args>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
construct, U, (
|
||||
boost::unordered::detail::make<ValueType*>(),
|
||||
boost::unordered::detail::make<Args const>()...), 2
|
||||
);
|
||||
|
||||
# else
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
construct, U, (
|
||||
boost::unordered::detail::make<ValueType*>(),
|
||||
boost::unordered::detail::make<ValueType const>()), 2
|
||||
);
|
||||
|
||||
# endif
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
|
||||
);
|
||||
|
||||
# else
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_MEMBER(max_size);
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_MEMBER(construct);
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_MEMBER(destroy);
|
||||
|
||||
# endif
|
||||
|
||||
template <typename Alloc>
|
||||
inline typename boost::enable_if_c<
|
||||
boost::unordered::detail::
|
||||
has_select_on_container_copy_construction<Alloc>::value, Alloc
|
||||
>::type call_select_on_container_copy_construction(const Alloc& rhs)
|
||||
{
|
||||
return rhs.select_on_container_copy_construction();
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
inline typename boost::disable_if_c<
|
||||
boost::unordered::detail::
|
||||
has_select_on_container_copy_construction<Alloc>::value, Alloc
|
||||
>::type call_select_on_container_copy_construction(const Alloc& rhs)
|
||||
{
|
||||
return rhs;
|
||||
}
|
||||
|
||||
template <typename SizeType, typename Alloc>
|
||||
inline typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
|
||||
>::type call_max_size(const Alloc& a)
|
||||
{
|
||||
return a.max_size();
|
||||
}
|
||||
|
||||
template <typename SizeType, typename Alloc>
|
||||
inline typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
|
||||
>::type call_max_size(const Alloc&)
|
||||
{
|
||||
return (std::numeric_limits<SizeType>::max)();
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits
|
||||
{
|
||||
typedef Alloc allocator_type;
|
||||
typedef typename Alloc::value_type value_type;
|
||||
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
|
||||
pointer;
|
||||
|
||||
template <typename T>
|
||||
struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
|
||||
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
|
||||
typename pointer_to_other<const value_type>::type)
|
||||
const_pointer;
|
||||
|
||||
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
|
||||
// typename pointer_to_other<void>::type)
|
||||
// void_pointer;
|
||||
//
|
||||
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
|
||||
// typename pointer_to_other<const void>::type)
|
||||
// const_void_pointer;
|
||||
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
|
||||
std::ptrdiff_t) difference_type;
|
||||
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
|
||||
size_type;
|
||||
|
||||
// TODO: rebind_alloc and rebind_traits
|
||||
|
||||
static pointer allocate(Alloc& a, size_type n)
|
||||
{ return a.allocate(n); }
|
||||
|
||||
// I never use this, so I'll just comment it out for now.
|
||||
//
|
||||
//static pointer allocate(Alloc& a, size_type n,
|
||||
// const_void_pointer hint)
|
||||
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
|
||||
|
||||
static void deallocate(Alloc& a, pointer p, size_type n)
|
||||
{ a.deallocate(p, n); }
|
||||
|
||||
public:
|
||||
|
||||
# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||
::value>::type
|
||||
construct(Alloc& a, T* p, Args&&... x)
|
||||
{
|
||||
a.construct(p, boost::forward<Args>(x)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||
::value>::type
|
||||
construct(Alloc&, T* p, Args&&... x)
|
||||
{
|
||||
new ((void*) p) T(boost::forward<Args>(x)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc& a, T* p)
|
||||
{
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# elif !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value>::type
|
||||
construct(Alloc& a, T* p, T const& x)
|
||||
{
|
||||
a.construct(p, x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value>::type
|
||||
construct(Alloc&, T* p, T const& x)
|
||||
{
|
||||
new ((void*) p) T(x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc& a, T* p)
|
||||
{
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
// If we don't have SFINAE expressions, only call construct for the
|
||||
// copy constructor for the allocator's value_type - as that's
|
||||
// the only construct method that old fashioned allocators support.
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
construct(Alloc& a, T* p, T const& x)
|
||||
{
|
||||
a.construct(p, x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
construct(Alloc&, T* p, T const& x)
|
||||
{
|
||||
new ((void*) p) T(x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
destroy(Alloc& a, T* p)
|
||||
{
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
static size_type max_size(const Alloc& a)
|
||||
{
|
||||
return boost::unordered::detail::call_max_size<size_type>(a);
|
||||
}
|
||||
|
||||
// Allocator propagation on construction
|
||||
|
||||
static Alloc select_on_container_copy_construction(Alloc const& rhs)
|
||||
{
|
||||
return boost::unordered::detail::
|
||||
call_select_on_container_copy_construction(rhs);
|
||||
}
|
||||
|
||||
// Allocator propagation on assignment and swap.
|
||||
// Return true if lhs is modified.
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
||||
Alloc, propagate_on_container_copy_assignment, false_type)
|
||||
propagate_on_container_copy_assignment;
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
||||
Alloc,propagate_on_container_move_assignment, false_type)
|
||||
propagate_on_container_move_assignment;
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
||||
Alloc,propagate_on_container_swap,false_type)
|
||||
propagate_on_container_swap;
|
||||
};
|
||||
}}}
|
||||
|
||||
# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
||||
# undef BOOST_UNORDERED_DEFAULT_TYPE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// std::allocator_traits
|
||||
|
||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
|
||||
# include <memory>
|
||||
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits : std::allocator_traits<Alloc> {};
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename std::allocator_traits<Alloc>::
|
||||
template rebind_alloc<T> type;
|
||||
};
|
||||
}}}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// boost::container::allocator_traits
|
||||
|
||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
||||
|
||||
# include <boost/container/allocator_traits.hpp>
|
||||
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits :
|
||||
boost::container::allocator_traits<Alloc> {};
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap :
|
||||
boost::container::allocator_traits<Alloc>::
|
||||
template portable_rebind_alloc<T>
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#else
|
||||
|
||||
#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some helper functions for allocating & constructing
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// construct_node/destroy_node
|
||||
//
|
||||
// Construct a node using the best available method.
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
|
||||
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::construct(
|
||||
a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_node(Alloc& a, T* p)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::construct(a, p, T());
|
||||
try {
|
||||
boost::unordered::detail::construct_impl(
|
||||
p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
} catch(...) {
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_node(Alloc& a, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p->value_ptr());
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// array_constructor
|
||||
// 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 <typename Allocator>
|
||||
struct array_constructor
|
||||
template <class Allocator>
|
||||
struct allocator_array_constructor
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
|
||||
typedef typename traits::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
|
||||
|
||||
Allocator& alloc_;
|
||||
pointer ptr_;
|
||||
pointer constructed_;
|
||||
std::size_t length_;
|
||||
|
||||
array_constructor(Allocator& a)
|
||||
allocator_array_constructor(Allocator& a)
|
||||
: alloc_(a), ptr_(), constructed_(), length_(0)
|
||||
{
|
||||
constructed_ = pointer();
|
||||
ptr_ = pointer();
|
||||
}
|
||||
|
||||
~array_constructor() {
|
||||
~allocator_array_constructor() {
|
||||
if (ptr_) {
|
||||
for(pointer p = ptr_; p != constructed_; ++p)
|
||||
traits::destroy(alloc_, boost::addressof(*p));
|
||||
alloc_.destroy(p);
|
||||
|
||||
traits::deallocate(alloc_, ptr_, length_);
|
||||
alloc_.deallocate(ptr_, length_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
template <class V>
|
||||
void construct(V const& v, std::size_t l)
|
||||
{
|
||||
BOOST_ASSERT(!ptr_);
|
||||
length_ = l;
|
||||
ptr_ = traits::allocate(alloc_, length_);
|
||||
ptr_ = alloc_.allocate(length_);
|
||||
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
|
||||
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
|
||||
traits::construct(alloc_, boost::addressof(*constructed_), v);
|
||||
alloc_.construct(constructed_, v);
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
@@ -712,12 +97,15 @@ namespace boost { namespace unordered { namespace detail {
|
||||
ptr_ = pointer();
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
array_constructor(array_constructor const&);
|
||||
array_constructor& operator=(array_constructor const&);
|
||||
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
@@ -1,518 +0,0 @@
|
||||
|
||||
// Copyright (C) 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)
|
||||
|
||||
// See http://www.boost.org/libs/unordered for documentation
|
||||
|
||||
#ifndef BOOST_UNORDERED_EMPLACE_ARGS_HPP
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/inc.hpp>
|
||||
#include <boost/preprocessor/dec.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
#include <tuple>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated.
|
||||
#pragma warning(disable:4345) // behavior change: an object of POD type
|
||||
// constructed with an initializer of the form ()
|
||||
// will be default-initialized.
|
||||
#endif
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Bits and pieces for implementing traits
|
||||
|
||||
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
||||
struct choice9 { typedef char (&type)[9]; };
|
||||
struct choice8 : choice9 { typedef char (&type)[8]; };
|
||||
struct choice7 : choice8 { typedef char (&type)[7]; };
|
||||
struct choice6 : choice7 { typedef char (&type)[6]; };
|
||||
struct choice5 : choice6 { typedef char (&type)[5]; };
|
||||
struct choice4 : choice5 { typedef char (&type)[4]; };
|
||||
struct choice3 : choice4 { typedef char (&type)[3]; };
|
||||
struct choice2 : choice3 { typedef char (&type)[2]; };
|
||||
struct choice1 : choice2 { typedef char (&type)[1]; };
|
||||
choice1 choose();
|
||||
|
||||
typedef choice1::type yes_type;
|
||||
typedef choice2::type no_type;
|
||||
|
||||
struct private_type
|
||||
{
|
||||
private_type const &operator,(int) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
no_type is_private_type(T const&);
|
||||
yes_type is_private_type(private_type const&);
|
||||
|
||||
struct convert_from_anything {
|
||||
template <typename T>
|
||||
convert_from_anything(T const&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// emplace_args
|
||||
//
|
||||
// Either forwarding variadic arguments, or storing the arguments in
|
||||
// emplace_args##n
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args
|
||||
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
|
||||
#define BOOST_UNORDERED_EMPLACE_FORWARD args
|
||||
|
||||
#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
|
||||
BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
|
||||
|
||||
#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
|
||||
boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
|
||||
|
||||
#define BOOST_UNORDERED_EARGS(z, n, _) \
|
||||
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
struct BOOST_PP_CAT(emplace_args, n) \
|
||||
{ \
|
||||
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
|
||||
BOOST_PP_CAT(emplace_args, n) ( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
|
||||
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
|
||||
{} \
|
||||
\
|
||||
}; \
|
||||
\
|
||||
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
inline BOOST_PP_CAT(emplace_args, n) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
|
||||
> create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
|
||||
) \
|
||||
{ \
|
||||
BOOST_PP_CAT(emplace_args, n) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
|
||||
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
|
||||
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
|
||||
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
|
||||
BOOST_PP_CAT(a, n)( \
|
||||
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(b, n)))
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
|
||||
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
|
||||
BOOST_PP_CAT(Arg, n); \
|
||||
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
|
||||
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
|
||||
_)
|
||||
|
||||
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
|
||||
#undef BOOST_UNORDERED_EARGS_MEMBER
|
||||
#undef BOOST_UNORDERED_EARGS_INIT
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
|
||||
// e.g. for int
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
|
||||
#else
|
||||
struct please_ignore_this_overload {
|
||||
typedef please_ignore_this_overload type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct rv_ref_impl {
|
||||
typedef BOOST_RV_REF(T) type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct rv_ref :
|
||||
boost::detail::if_true<
|
||||
boost::is_class<T>::value
|
||||
>::BOOST_NESTED_TEMPLATE then <
|
||||
boost::unordered::detail::rv_ref_impl<T>,
|
||||
please_ignore_this_overload
|
||||
>::type
|
||||
{};
|
||||
|
||||
# define BOOST_UNORDERED_RV_REF(T) \
|
||||
typename boost::unordered::detail::rv_ref<T>::type
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from tuple
|
||||
//
|
||||
// Used for piecewise construction.
|
||||
|
||||
#if !defined(__SUNPRO_CC)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
template<typename T> \
|
||||
void construct_from_tuple(T* ptr, namespace_ tuple<>) \
|
||||
{ \
|
||||
new ((void*) ptr) T(); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT_FROM_TO(1, n, \
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
|
||||
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
void construct_from_tuple(T* ptr, \
|
||||
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
{ \
|
||||
new ((void*) ptr) T( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
|
||||
); \
|
||||
}
|
||||
|
||||
# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
|
||||
namespace_ get<n>(x)
|
||||
|
||||
#else
|
||||
|
||||
template <int N> struct length {};
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
template<typename T> \
|
||||
void construct_from_tuple_impl( \
|
||||
boost::unordered::detail::length<0>, T* ptr, \
|
||||
namespace_ tuple<>) \
|
||||
{ \
|
||||
new ((void*) ptr) T(); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT_FROM_TO(1, n, \
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
|
||||
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
void construct_from_tuple_impl( \
|
||||
boost::unordered::detail::length<n>, T* ptr, \
|
||||
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
{ \
|
||||
new ((void*) ptr) T( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
|
||||
); \
|
||||
}
|
||||
|
||||
# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
|
||||
namespace_ get<n>(x)
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
|
||||
#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
|
||||
#endif
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
|
||||
#undef BOOST_UNORDERED_GET_TUPLE_ARG
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
|
||||
template <typename T, typename Tuple>
|
||||
void construct_from_tuple(T* ptr, Tuple const& x)
|
||||
{
|
||||
construct_from_tuple_impl(
|
||||
boost::unordered::detail::length<
|
||||
boost::tuples::length<Tuple>::value>(),
|
||||
ptr, x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SFINAE traits for construction.
|
||||
|
||||
// Decide which construction method to use for a three argument
|
||||
// call. Note that this is difficult to do using overloads because
|
||||
// the arguments are packed into 'emplace_args3'.
|
||||
//
|
||||
// The decision is made on the first argument.
|
||||
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
template <typename A, typename B, typename A0>
|
||||
struct emulation1 {
|
||||
static choice1::type test(choice1, std::pair<A, B> const&);
|
||||
static choice2::type test(choice2, A const&);
|
||||
static choice3::type test(choice3, convert_from_anything const&);
|
||||
|
||||
enum { value =
|
||||
sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
|
||||
sizeof(choice2::type) };
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
struct check3_base {
|
||||
static choice1::type test(choice1,
|
||||
boost::unordered::piecewise_construct_t);
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
static choice2::type test(choice2, A const&);
|
||||
#endif
|
||||
|
||||
static choice3::type test(choice3, ...);
|
||||
|
||||
enum { value =
|
||||
sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
struct piecewise3 {
|
||||
enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
|
||||
};
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
template <typename A, typename B, typename A0>
|
||||
struct emulation3 {
|
||||
enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from variadic parameters
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline void construct_impl(T* address, Args&&... args)
|
||||
{
|
||||
new((void*) address) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename A, typename B, typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<piecewise3<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address, A0&&, A1&& a1, A2&& a2)
|
||||
{
|
||||
boost::unordered::detail::construct_from_tuple(
|
||||
boost::addressof(address->first), a1);
|
||||
boost::unordered::detail::construct_from_tuple(
|
||||
boost::addressof(address->second), a2);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
inline typename enable_if<emulation1<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address, A0&& a0)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->second)) B();
|
||||
}
|
||||
|
||||
template <typename A, typename B, typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<emulation3<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address, A0&& a0, A1&& a1, A2&& a2)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
template <typename A, typename B,
|
||||
typename A0, typename A1, typename A2, typename A3,
|
||||
typename... Args>
|
||||
inline void construct_impl(std::pair<A, B>* address,
|
||||
A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2),
|
||||
boost::forward<A3>(a3),
|
||||
boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#else // BOOST_UNORDERED_VARIADIC_MOVE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from emplace_args
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
typename T, \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
|
||||
> \
|
||||
inline void construct_impl(T* address, \
|
||||
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
|
||||
> const& args) \
|
||||
{ \
|
||||
new((void*) address) T( \
|
||||
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
args.a)); \
|
||||
}
|
||||
|
||||
template <typename T, typename A0>
|
||||
inline void construct_impl(T* address, emplace_args1<A0> const& args)
|
||||
{
|
||||
new((void*) address) T(boost::forward<A0>(args.a0));
|
||||
}
|
||||
|
||||
template <typename T, typename A0, typename A1>
|
||||
inline void construct_impl(T* address, emplace_args2<A0, A1> const& args)
|
||||
{
|
||||
new((void*) address) T(
|
||||
boost::forward<A0>(args.a0),
|
||||
boost::forward<A1>(args.a1)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T, typename A0, typename A1, typename A2>
|
||||
inline void construct_impl(T* address, emplace_args3<A0, A1, A2> const& args)
|
||||
{
|
||||
new((void*) address) T(
|
||||
boost::forward<A0>(args.a0),
|
||||
boost::forward<A1>(args.a1),
|
||||
boost::forward<A2>(args.a2)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
|
||||
template <typename A, typename B, typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<piecewise3<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
|
||||
{
|
||||
boost::unordered::detail::construct_from_tuple(
|
||||
boost::addressof(address->first), args.a1);
|
||||
boost::unordered::detail::construct_from_tuple(
|
||||
boost::addressof(address->second), args.a2);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
inline typename enable_if<emulation1<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args1<A0> const& args)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(
|
||||
boost::forward<A0>(args.a0));
|
||||
new((void*) boost::addressof(address->second)) B();
|
||||
}
|
||||
|
||||
template <typename A, typename B, typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<emulation3<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(
|
||||
boost::forward<A0>(args.a0));
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
boost::forward<A1>(args.a1),
|
||||
boost::forward<A2>(args.a2));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
|
||||
template <typename A, typename B, \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
|
||||
> \
|
||||
inline void construct_impl(std::pair<A, B>* address, \
|
||||
boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
|
||||
> const& args) \
|
||||
{ \
|
||||
new((void*) boost::addressof(address->first)) A( \
|
||||
boost::forward<A0>(args.a0)); \
|
||||
new((void*) boost::addressof(address->second)) B( \
|
||||
BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params), \
|
||||
BOOST_UNORDERED_CALL_FORWARD2, args.a)); \
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
|
||||
BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
|
||||
|
||||
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
|
||||
#undef BOOST_UNORDERED_CALL_FORWARD2
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#endif // BOOST_UNORDERED_VARIADIC_MOVE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct without using the emplace args mechanism.
|
||||
|
||||
template <typename T, typename A0>
|
||||
inline void construct_impl2(T* address, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
new((void*) address) T(
|
||||
boost::forward<A0>(a0)
|
||||
);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,17 @@
|
||||
|
||||
// Copyright (C) 2005-2011 Daniel James
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
namespace detail {
|
||||
namespace unordered_detail {
|
||||
|
||||
// key extractors
|
||||
//
|
||||
@@ -27,19 +28,6 @@ namespace detail {
|
||||
template <class T> no_key(T const&) {}
|
||||
};
|
||||
|
||||
template <typename Key, typename T>
|
||||
struct is_key {
|
||||
template <typename T2>
|
||||
static choice1::type test(T2 const&);
|
||||
static choice2::type test(Key const&);
|
||||
|
||||
enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
|
||||
sizeof(choice2::type) };
|
||||
|
||||
typedef typename boost::detail::if_true<value>::
|
||||
BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct set_extractor
|
||||
{
|
||||
@@ -56,12 +44,13 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#else
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
@@ -69,8 +58,8 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&, Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
@@ -86,7 +75,7 @@ namespace detail {
|
||||
struct map_extractor
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
typedef typename boost::remove_const<Key>::type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Key>::type key_type;
|
||||
|
||||
static key_type const& extract(value_type const& v)
|
||||
{
|
||||
@@ -111,7 +100,7 @@ namespace detail {
|
||||
return v.first;
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class Arg1, class... Args>
|
||||
static key_type const& extract(key_type const& k,
|
||||
Arg1 const&, Args const&...)
|
||||
@@ -125,7 +114,6 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
|
||||
template <class Arg1>
|
||||
static key_type const& extract(key_type const& k, Arg1 const&)
|
||||
{
|
||||
@@ -150,57 +138,11 @@ namespace detail {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
template <typename T2> \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_::tuple<> const&, 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, 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_0X_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
|
||||
|
||||
@@ -1,23 +1,932 @@
|
||||
|
||||
// Copyright (C) 2008-2011 Daniel James.
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
|
||||
// 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.
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#ifndef BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/compressed_pair.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// This header defines most of the classes used to implement the unordered
|
||||
// containers. It doesn't include the insert methods as they require a lot
|
||||
// of preprocessor metaprogramming - they are in unique.hpp and equivalent.hpp.
|
||||
|
||||
// Template parameters:
|
||||
//
|
||||
// H = Hash Function
|
||||
// P = Predicate
|
||||
// A = Value Allocator
|
||||
// G = Bucket group policy, 'grouped' or 'ungrouped'
|
||||
// E = Key Extractor
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
// STLport doesn't have std::forward.
|
||||
# else
|
||||
# define BOOST_UNORDERED_STD_FORWARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_EMPLACE_LIMIT)
|
||||
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
struct piecewise_construct_t {};
|
||||
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
|
||||
}
|
||||
}
|
||||
#if !defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
||||
#define BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, class Arg)
|
||||
#define BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, num_params, Arg, const& arg)
|
||||
#define BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, arg)
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
static const float minimum_max_load_factor = 1e-3f;
|
||||
static const std::size_t default_bucket_count = 11;
|
||||
struct move_tag {};
|
||||
|
||||
template <class T> class hash_unique_table;
|
||||
template <class T> class hash_equivalent_table;
|
||||
template <class Alloc, class Grouped>
|
||||
class hash_node_constructor;
|
||||
template <class ValueType>
|
||||
struct set_extractor;
|
||||
template <class Key, class ValueType>
|
||||
struct map_extractor;
|
||||
struct no_key;
|
||||
|
||||
// Explicitly call a destructor
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This section implements buckets and nodes. Here's a rough
|
||||
// inheritance diagram, to show how they pull together.
|
||||
//
|
||||
// For unordered_set/unordered_map:
|
||||
//
|
||||
// hash_bucket<A>
|
||||
// |
|
||||
// ungrouped_node_base<A> value_base<A::value_type>
|
||||
// | |
|
||||
// +--------------+-------------+
|
||||
// |
|
||||
// hash_node<A, ungrouped>
|
||||
//
|
||||
// For unordered_multiset/unordered_multimap:
|
||||
//
|
||||
// hash_bucket<A>
|
||||
// |
|
||||
// grouped_node_base<A> value_base<A::value_type>
|
||||
// | |
|
||||
// +--------------+-------------+
|
||||
// |
|
||||
// hash_node<A, grouped>
|
||||
|
||||
// hash_bucket
|
||||
//
|
||||
// hash_bucket is used for both the buckets and as a base class for
|
||||
// nodes. By using 'bucket_ptr' for 'node_ptr', 'next_' can point
|
||||
// to either a bucket or a node. This is used later to implement a
|
||||
// sentinel at the end of the bucket array.
|
||||
|
||||
template <class A>
|
||||
class hash_bucket
|
||||
{
|
||||
hash_bucket& operator=(hash_bucket const&);
|
||||
public:
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<A, bucket>::type
|
||||
bucket_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket_allocator::pointer bucket_ptr;
|
||||
typedef bucket_ptr node_ptr;
|
||||
|
||||
node_ptr next_;
|
||||
|
||||
hash_bucket() : next_() {}
|
||||
};
|
||||
|
||||
// In containers with equivalent keys (unordered_multimap and
|
||||
// unordered_multiset) equivalent nodes are grouped together, in
|
||||
// containers with unique keys (unordered_map and unordered_set)
|
||||
// individual nodes are treated as groups of one. The following two
|
||||
// classes implement the data structure.
|
||||
|
||||
// This is used for containers with unique keys. There are no groups
|
||||
// so it doesn't add any extra members, and just treats individual
|
||||
// nodes as groups of one.
|
||||
|
||||
template <class A>
|
||||
struct ungrouped_node_base : hash_bucket<A> {
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
ungrouped_node_base() : bucket() {}
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr n);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
};
|
||||
|
||||
// This is used for containers with equivalent keys. It implements a
|
||||
// circular list running in the opposite direction to the linked
|
||||
// list through the nodes.
|
||||
|
||||
template <class A>
|
||||
struct grouped_node_base : hash_bucket<A>
|
||||
{
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
node_ptr group_prev_;
|
||||
|
||||
grouped_node_base() : bucket(), group_prev_() {}
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline node_ptr first_in_group(node_ptr n);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr n);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
|
||||
private:
|
||||
static inline node_ptr split_group(node_ptr split);
|
||||
static inline grouped_node_base& get(node_ptr ptr) {
|
||||
return static_cast<grouped_node_base&>(*ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// These two classes implement an easy way to pass around the node
|
||||
// group policy classes without the messy template parameters.
|
||||
// Whenever you see the template parameter 'G' it's one of these.
|
||||
|
||||
struct ungrouped
|
||||
{
|
||||
template <class A>
|
||||
struct base {
|
||||
typedef ungrouped_node_base<A> type;
|
||||
};
|
||||
};
|
||||
|
||||
struct grouped
|
||||
{
|
||||
template <class A>
|
||||
struct base {
|
||||
typedef grouped_node_base<A> type;
|
||||
};
|
||||
};
|
||||
|
||||
// The space used to store values in a node.
|
||||
|
||||
template <class ValueType>
|
||||
struct value_base
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(value_type),
|
||||
::boost::alignment_of<value_type>::value>::type data_;
|
||||
|
||||
void* address() {
|
||||
return this;
|
||||
}
|
||||
value_type& value() {
|
||||
return *(ValueType*) this;
|
||||
}
|
||||
value_type* value_ptr() {
|
||||
return (ValueType*) this;
|
||||
}
|
||||
private:
|
||||
value_base& operator=(value_base const&);
|
||||
};
|
||||
|
||||
// Node
|
||||
|
||||
template <class A, class G>
|
||||
class hash_node :
|
||||
public G::BOOST_NESTED_TEMPLATE base<A>::type,
|
||||
public value_base<BOOST_DEDUCED_TYPENAME A::value_type>
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME hash_bucket<A>::node_ptr node_ptr;
|
||||
|
||||
static value_type& get_value(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value();
|
||||
}
|
||||
static value_type* get_value_ptr(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value_ptr();
|
||||
}
|
||||
private:
|
||||
hash_node& operator=(hash_node const&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Iterator Base
|
||||
//
|
||||
// This is the iterator used internally, the external iterators are
|
||||
// provided by lightweight wrappers (hash_iterator and
|
||||
// hast_const_iterator) which provide the full iterator interface.
|
||||
|
||||
template <class A, class G>
|
||||
class hash_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef A value_allocator;
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef hash_node<A, G> node;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
bucket_ptr bucket_;
|
||||
node_ptr node_;
|
||||
|
||||
hash_iterator_base() : bucket_(), node_() {}
|
||||
explicit hash_iterator_base(bucket_ptr b)
|
||||
: bucket_(b),
|
||||
node_(b ? b->next_ : node_ptr()) {}
|
||||
hash_iterator_base(bucket_ptr b, node_ptr n)
|
||||
: bucket_(b),
|
||||
node_(n) {}
|
||||
|
||||
bool operator==(hash_iterator_base const& x) const {
|
||||
return node_ == x.node_; }
|
||||
bool operator!=(hash_iterator_base const& x) const {
|
||||
return node_ != x.node_; }
|
||||
value_type& operator*() const {
|
||||
return node::get_value(node_);
|
||||
}
|
||||
|
||||
void increment_bucket(node_ptr n) {
|
||||
while(!n) {
|
||||
++bucket_;
|
||||
n = bucket_->next_;
|
||||
}
|
||||
node_ = bucket_ == n ? node_ptr() : n;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
increment_bucket(node_->next_);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Now the main data structure:
|
||||
//
|
||||
// hash_buckets<A, G> hash_buffered_functions<H, P>
|
||||
// | |
|
||||
// +-------------+--------------+
|
||||
// |
|
||||
// hash_table<T>
|
||||
//
|
||||
// T is a class which contains typedefs for all the types we need.
|
||||
|
||||
// hash_buckets
|
||||
//
|
||||
// This is responsible for allocating and deallocating buckets and nodes.
|
||||
//
|
||||
// Notes:
|
||||
// 1. For the sake exception safety the consturctors don't allocate
|
||||
// anything.
|
||||
// 2. It's the callers responsibility to allocate the buckets before calling
|
||||
// any of the methods (other than getters and setters).
|
||||
|
||||
template <class A, class G>
|
||||
class hash_buckets
|
||||
{
|
||||
hash_buckets(hash_buckets const&);
|
||||
hash_buckets& operator=(hash_buckets const&);
|
||||
public:
|
||||
// Types
|
||||
|
||||
typedef A value_allocator;
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef hash_iterator_base<A, G> iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME iterator_base::node node;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
|
||||
bucket_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
|
||||
node_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
|
||||
|
||||
// Members
|
||||
|
||||
bucket_ptr buckets_;
|
||||
std::size_t bucket_count_;
|
||||
boost::compressed_pair<bucket_allocator, node_allocator> allocators_;
|
||||
|
||||
// Data access
|
||||
|
||||
bucket_allocator const& bucket_alloc() const {
|
||||
return allocators_.first(); }
|
||||
node_allocator const& node_alloc() const {
|
||||
return allocators_.second(); }
|
||||
bucket_allocator& bucket_alloc() {
|
||||
return allocators_.first(); }
|
||||
node_allocator& node_alloc() {
|
||||
return allocators_.second(); }
|
||||
std::size_t max_bucket_count() const;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_buckets(node_allocator const& a, std::size_t n);
|
||||
void create_buckets();
|
||||
~hash_buckets();
|
||||
|
||||
// no throw
|
||||
void swap(hash_buckets& other);
|
||||
void move(hash_buckets& other);
|
||||
|
||||
// For the remaining functions, buckets_ must not be null.
|
||||
|
||||
bucket_ptr get_bucket(std::size_t n) const;
|
||||
bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
|
||||
std::size_t bucket_size(std::size_t index) const;
|
||||
node_ptr bucket_begin(std::size_t n) const;
|
||||
|
||||
// Alloc/Dealloc
|
||||
|
||||
void delete_node(node_ptr);
|
||||
|
||||
//
|
||||
void delete_buckets();
|
||||
void clear_bucket(bucket_ptr);
|
||||
std::size_t delete_nodes(node_ptr begin, node_ptr end);
|
||||
std::size_t delete_to_bucket_end(node_ptr begin);
|
||||
};
|
||||
|
||||
// Assigning and swapping the equality and hash function objects
|
||||
// needs strong exception safety. To implement that normally we'd
|
||||
// require one of them to be known to not throw and the other to
|
||||
// guarantee strong exception safety. Unfortunately they both only
|
||||
// have basic exception safety. So to acheive strong exception
|
||||
// safety we have storage space for two copies, and assign the new
|
||||
// copies to the unused space. Then switch to using that to use
|
||||
// them. This is implemented in 'set_hash_functions' which
|
||||
// atomically assigns the new function objects in a strongly
|
||||
// exception safe manner.
|
||||
|
||||
template <class H, class P> class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
class hash_buffered_functions
|
||||
{
|
||||
friend class set_hash_functions<H, P>;
|
||||
hash_buffered_functions& operator=(hash_buffered_functions const&);
|
||||
|
||||
typedef boost::compressed_pair<H, P> function_pair;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(function_pair),
|
||||
::boost::alignment_of<function_pair>::value>::type aligned_function;
|
||||
|
||||
bool current_; // The currently active functions.
|
||||
aligned_function funcs_[2];
|
||||
|
||||
function_pair const& current() const {
|
||||
return *static_cast<function_pair const*>(
|
||||
static_cast<void const*>(&funcs_[current_]));
|
||||
}
|
||||
|
||||
void construct(bool which, H const& hf, P const& eq)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(hf, eq);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair const& f)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f);
|
||||
}
|
||||
|
||||
void destroy(bool which)
|
||||
{
|
||||
boost::unordered_detail::destroy((function_pair*)(&funcs_[which]));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
hash_buffered_functions(H const& hf, P const& eq)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, hf, eq);
|
||||
}
|
||||
|
||||
hash_buffered_functions(hash_buffered_functions const& bf)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current());
|
||||
}
|
||||
|
||||
~hash_buffered_functions() {
|
||||
destroy(current_);
|
||||
}
|
||||
|
||||
H const& hash_function() const {
|
||||
return current().first();
|
||||
}
|
||||
|
||||
P const& key_eq() const {
|
||||
return current().second();
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef hash_buffered_functions<H, P> buffered_functions;
|
||||
buffered_functions& buffered_functions_;
|
||||
bool tmp_functions_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(buffered_functions& f, H const& h, P const& p)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, h, p);
|
||||
}
|
||||
|
||||
set_hash_functions(buffered_functions& f,
|
||||
buffered_functions const& other)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, other.current());
|
||||
}
|
||||
|
||||
~set_hash_functions()
|
||||
{
|
||||
buffered_functions_.destroy(tmp_functions_);
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
buffered_functions_.current_ = tmp_functions_;
|
||||
tmp_functions_ = !tmp_functions_;
|
||||
}
|
||||
};
|
||||
|
||||
// This implements almost all of the required functionality, apart
|
||||
// from some things that are specific to containers with unique and
|
||||
// equivalent keys which is implemented in hash_unique_table and
|
||||
// hash_equivalent_table. See unique.hpp and equivalent.hpp for
|
||||
// their declaration and implementation.
|
||||
|
||||
template <class T>
|
||||
class hash_table : public T::buckets, public T::buffered_functions
|
||||
{
|
||||
hash_table(hash_table const&);
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::buffered_functions base;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::buckets buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::bucket bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair;
|
||||
|
||||
// Members
|
||||
|
||||
std::size_t size_;
|
||||
float mlf_;
|
||||
// Cached data - invalid if !this->buckets_
|
||||
bucket_ptr cached_begin_bucket_;
|
||||
std::size_t max_load_;
|
||||
|
||||
// Helper methods
|
||||
|
||||
key_type const& get_key(value_type const& v) const {
|
||||
return extractor::extract(v);
|
||||
}
|
||||
key_type const& get_key_from_ptr(node_ptr n) const {
|
||||
return extractor::extract(node::get_value(n));
|
||||
}
|
||||
bool equal(key_type const& k, value_type const& v) const;
|
||||
template <class Key, class Pred>
|
||||
node_ptr find_iterator(bucket_ptr bucket, Key const& k,
|
||||
Pred const&) const;
|
||||
node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
|
||||
node_ptr find_iterator(key_type const& k) const;
|
||||
node_ptr* find_for_erase(bucket_ptr bucket, key_type const& k) const;
|
||||
|
||||
// Load methods
|
||||
|
||||
std::size_t max_size() const;
|
||||
std::size_t bucket_index(key_type const& k) const;
|
||||
void max_load_factor(float z);
|
||||
std::size_t min_buckets_for_size(std::size_t n) const;
|
||||
std::size_t calculate_max_load();
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_table(std::size_t n, hasher const& hf, key_equal const& eq,
|
||||
node_allocator const& a);
|
||||
hash_table(hash_table const& x, node_allocator const& a);
|
||||
hash_table(hash_table& x, move_tag m);
|
||||
hash_table(hash_table& x, node_allocator const& a, move_tag m);
|
||||
~hash_table() {}
|
||||
hash_table& operator=(hash_table const&);
|
||||
|
||||
// Iterators
|
||||
|
||||
iterator_base begin() const {
|
||||
return this->size_ ?
|
||||
iterator_base(this->cached_begin_bucket_) :
|
||||
iterator_base();
|
||||
}
|
||||
iterator_base end() const {
|
||||
return iterator_base();
|
||||
}
|
||||
|
||||
// Swap & Move
|
||||
|
||||
void swap(hash_table& x);
|
||||
void fast_swap(hash_table& other);
|
||||
void slow_swap(hash_table& other);
|
||||
void partial_swap(hash_table& other);
|
||||
void move(hash_table& x);
|
||||
|
||||
// Reserve and rehash
|
||||
|
||||
void create_for_insert(std::size_t n);
|
||||
bool reserve_for_insert(std::size_t n);
|
||||
void rehash(std::size_t n);
|
||||
void rehash_impl(std::size_t n);
|
||||
|
||||
// Move/copy buckets
|
||||
|
||||
void move_buckets_to(buckets& dst);
|
||||
void copy_buckets_to(buckets& dst) const;
|
||||
|
||||
// Misc. key methods
|
||||
|
||||
std::size_t count(key_type const& k) const;
|
||||
iterator_base find(key_type const& k) const;
|
||||
template <class Key, class Hash, class Pred>
|
||||
iterator_base find(Key const& k, Hash const& h, Pred const& eq) const;
|
||||
value_type& at(key_type const& k) const;
|
||||
iterator_pair equal_range(key_type const& k) const;
|
||||
|
||||
// Erase
|
||||
//
|
||||
// no throw
|
||||
|
||||
void clear();
|
||||
std::size_t erase_key(key_type const& k);
|
||||
iterator_base erase_return_iterator(iterator_base r);
|
||||
void erase(iterator_base r);
|
||||
std::size_t erase_group(node_ptr* it, bucket_ptr bucket);
|
||||
iterator_base erase_range(iterator_base r1, iterator_base r2);
|
||||
|
||||
// recompute_begin_bucket
|
||||
|
||||
void init_buckets();
|
||||
|
||||
// After an erase cached_begin_bucket_ might be left pointing to
|
||||
// an empty bucket, so this is called to update it
|
||||
//
|
||||
// no throw
|
||||
|
||||
void recompute_begin_bucket(bucket_ptr b);
|
||||
|
||||
// This is called when a range has been erased
|
||||
//
|
||||
// no throw
|
||||
|
||||
void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2);
|
||||
|
||||
// no throw
|
||||
float load_factor() const;
|
||||
|
||||
iterator_base emplace_empty_impl_with_node(
|
||||
node_constructor&, std::size_t);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Iterators
|
||||
|
||||
// iterator_access is used to access the internal iterator without
|
||||
// making it publicly available.
|
||||
|
||||
class iterator_access
|
||||
{
|
||||
public:
|
||||
template <class Iterator>
|
||||
static BOOST_DEDUCED_TYPENAME Iterator::base const&
|
||||
get(Iterator const& it)
|
||||
{
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G> class hash_iterator;
|
||||
template <class A, class G> class hash_const_iterator;
|
||||
template <class A, class G> class hash_local_iterator;
|
||||
template <class A, class G> class hash_const_local_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <class A, class G>
|
||||
class hash_local_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::reference>
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef hash_const_local_iterator<A, G> const_local_iterator;
|
||||
|
||||
friend class hash_const_local_iterator<A, G>;
|
||||
node_ptr ptr_;
|
||||
|
||||
public:
|
||||
hash_local_iterator() : ptr_() {}
|
||||
explicit hash_local_iterator(node_ptr x) : ptr_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return node::get_value_ptr(ptr_);
|
||||
}
|
||||
hash_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_local_iterator operator++(int) {
|
||||
hash_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp; }
|
||||
bool operator==(hash_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
class hash_const_local_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::const_pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef hash_local_iterator<A, G> local_iterator;
|
||||
friend class hash_local_iterator<A, G>;
|
||||
ptr ptr_;
|
||||
|
||||
public:
|
||||
hash_const_local_iterator() : ptr_() {}
|
||||
explicit hash_const_local_iterator(ptr x) : ptr_(x) {}
|
||||
hash_const_local_iterator(local_iterator x) : ptr_(x.ptr_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference
|
||||
operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return node::get_value_ptr(ptr_);
|
||||
}
|
||||
hash_const_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_const_local_iterator operator++(int) {
|
||||
hash_const_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp;
|
||||
}
|
||||
bool operator==(local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(hash_const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
// Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
|
||||
template <class A, class G>
|
||||
class hash_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
|
||||
typedef hash_const_iterator<A, G> const_iterator;
|
||||
friend class hash_const_iterator<A, G>;
|
||||
base base_;
|
||||
|
||||
public:
|
||||
|
||||
hash_iterator() : base_() {}
|
||||
explicit hash_iterator(base const& x) : base_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_iterator operator++(int) {
|
||||
hash_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(hash_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(hash_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
class hash_const_iterator
|
||||
: public boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
BOOST_DEDUCED_TYPENAME A::value_type,
|
||||
std::ptrdiff_t,
|
||||
BOOST_DEDUCED_TYPENAME A::const_pointer,
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference >
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
|
||||
typedef hash_iterator<A, G> iterator;
|
||||
friend class hash_iterator<A, G>;
|
||||
friend class iterator_access;
|
||||
base base_;
|
||||
|
||||
public:
|
||||
|
||||
hash_const_iterator() : base_() {}
|
||||
explicit hash_const_iterator(base const& x) : base_(x) {}
|
||||
hash_const_iterator(iterator const& x) : base_(x.base_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_const_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_const_iterator operator++(int) {
|
||||
hash_const_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(hash_const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(hash_const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// types
|
||||
//
|
||||
// This is used to convieniently pass around a container's typedefs
|
||||
// without having 7 template parameters.
|
||||
|
||||
template <class K, class V, class H, class P, class A, class E, class G>
|
||||
struct types
|
||||
{
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef V value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef E extractor;
|
||||
typedef G group_type;
|
||||
|
||||
typedef hash_node_constructor<value_allocator, group_type>
|
||||
node_constructor;
|
||||
typedef hash_buckets<value_allocator, group_type> buckets;
|
||||
typedef hash_buffered_functions<hasher, key_equal> buffered_functions;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
|
||||
|
||||
typedef std::pair<iterator_base, iterator_base> iterator_pair;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
|
||||
Use, modification and distribution are subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER
|
||||
#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#if defined(BOOST_NO_SFINAE)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif defined(__GNUC__) && \
|
||||
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
|
||||
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
|
||||
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
|
||||
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
namespace boost {
|
||||
namespace unordered_detail {
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
namespace move_detail {
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
template <typename T>
|
||||
struct class_has_move_assign {
|
||||
class type {
|
||||
typedef T& (T::*E)(T t);
|
||||
typedef char (&no_type)[1];
|
||||
typedef char (&yes_type)[2];
|
||||
template <E e> struct sfinae { typedef yes_type type; };
|
||||
template <class U>
|
||||
static typename sfinae<&U::operator=>::type test(int);
|
||||
template <class U>
|
||||
static no_type test(...);
|
||||
public:
|
||||
enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};
|
||||
};
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
template<typename T>
|
||||
struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
class test_can_convert_anything { };
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*
|
||||
REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where
|
||||
boost::is_convertible<T, T> fails to compile.
|
||||
*/
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_convertible : boost::mpl::or_<
|
||||
boost::is_same<T, U>,
|
||||
boost::is_convertible<T, U>
|
||||
> { };
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
} //namespace move_detail
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief move_from is used for move_ctors.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
struct move_from
|
||||
{
|
||||
explicit move_from(T& x) : source(x) { }
|
||||
T& source;
|
||||
private:
|
||||
move_from& operator=(move_from const&);
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief The is_movable trait can be used to identify movable types.
|
||||
*/
|
||||
template <typename T>
|
||||
struct is_movable : boost::mpl::and_<
|
||||
boost::is_convertible<move_from<T>, T>,
|
||||
move_detail::has_move_assign<T>,
|
||||
boost::mpl::not_<boost::is_convertible<move_detail::test_can_convert_anything, T> >
|
||||
> { };
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
|
||||
|
||||
// On compilers which don't have adequate SFINAE support, treat most types as unmovable,
|
||||
// unless the trait is specialized.
|
||||
|
||||
template <typename T>
|
||||
struct is_movable : boost::mpl::false_ { };
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief copy_sink and move_sink are used to select between overloaded operations according to
|
||||
whether type T is movable and convertible to type U.
|
||||
\sa move
|
||||
*/
|
||||
|
||||
template <typename T,
|
||||
typename U = T,
|
||||
typename R = void*>
|
||||
struct copy_sink : boost::enable_if<
|
||||
boost::mpl::and_<
|
||||
boost::unordered_detail::move_detail::is_convertible<T, U>,
|
||||
boost::mpl::not_<is_movable<T> >
|
||||
>,
|
||||
R
|
||||
>
|
||||
{ };
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief move_sink and copy_sink are used to select between overloaded operations according to
|
||||
whether type T is movable and convertible to type U.
|
||||
\sa move
|
||||
*/
|
||||
|
||||
template <typename T,
|
||||
typename U = T,
|
||||
typename R = void*>
|
||||
struct move_sink : boost::enable_if<
|
||||
boost::mpl::and_<
|
||||
boost::unordered_detail::move_detail::is_convertible<T, U>,
|
||||
is_movable<T>
|
||||
>,
|
||||
R
|
||||
>
|
||||
{ };
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief This version of move is selected when T is_movable . It in turn calls the move
|
||||
constructor. This call, with the help of the return value optimization, will cause x to be moved
|
||||
instead of copied to its destination. See adobe/test/move/main.cpp for examples.
|
||||
|
||||
*/
|
||||
template <typename T>
|
||||
T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*!
|
||||
\ingroup move_related
|
||||
\brief This version of move is selected when T is not movable . The net result will be that
|
||||
x gets copied.
|
||||
*/
|
||||
template <typename T>
|
||||
T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#else // BOOST_NO_SFINAE
|
||||
|
||||
// On compilers without SFINAE, define copy_sink to always use the copy function.
|
||||
|
||||
template <typename T,
|
||||
typename U = T,
|
||||
typename R = void*>
|
||||
struct copy_sink
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
// Always copy the element unless this is overloaded.
|
||||
|
||||
template <typename T>
|
||||
T& move(T& x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_SFINAE
|
||||
|
||||
} // namespace unordered_detail
|
||||
} // namespace boost
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
@@ -0,0 +1,226 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// This contains the basic data structure, apart from the actual values. There's
|
||||
// no construction or deconstruction here. So this only depends on the pointer
|
||||
// type.
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
|
||||
#else
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// ungrouped node implementation
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
|
||||
ungrouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return ptr->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline std::size_t ungrouped_node_base<A>::group_count(node_ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
n->next_ = b.next_;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
|
||||
node_ptr position)
|
||||
{
|
||||
n->next_ = position->next_;
|
||||
position->next_ = position;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &b.next_;
|
||||
while(*pos != begin) pos = &(*pos)->next_;
|
||||
*pos = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
|
||||
{
|
||||
b.next_ = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
|
||||
{
|
||||
unlink_nodes(b, n, n->next_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// grouped node implementation
|
||||
|
||||
// If ptr is the first element in a group, return pointer to next group.
|
||||
// Otherwise returns a pointer to ptr.
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
|
||||
grouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return get(ptr).group_prev_->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::first_in_group(node_ptr ptr)
|
||||
{
|
||||
while(next_group(ptr) == ptr)
|
||||
ptr = get(ptr).group_prev_;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline std::size_t grouped_node_base<A>::group_count(node_ptr ptr)
|
||||
{
|
||||
node_ptr start = ptr;
|
||||
std::size_t size = 0;
|
||||
do {
|
||||
++size;
|
||||
ptr = get(ptr).group_prev_;
|
||||
} while(ptr != start);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
n->next_ = b.next_;
|
||||
get(n).group_prev_ = n;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
|
||||
{
|
||||
n->next_ = next_group(pos);
|
||||
get(n).group_prev_ = get(pos).group_prev_;
|
||||
next_group(pos) = n;
|
||||
get(pos).group_prev_ = n;
|
||||
}
|
||||
|
||||
// Break a ciruclar list into two, with split as the beginning
|
||||
// of the second group (if split is at the beginning then don't
|
||||
// split).
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::split_group(node_ptr split)
|
||||
{
|
||||
node_ptr first = first_in_group(split);
|
||||
if(first == split) return split;
|
||||
|
||||
node_ptr last = get(first).group_prev_;
|
||||
get(first).group_prev_ = get(split).group_prev_;
|
||||
get(split).group_prev_ = last;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
|
||||
{
|
||||
node_ptr next = n->next_;
|
||||
node_ptr* pos = &next_group(n);
|
||||
|
||||
if(*pos != n) {
|
||||
// The node is at the beginning of a group.
|
||||
|
||||
// Find the previous node pointer:
|
||||
pos = &b.next_;
|
||||
while(*pos != n) pos = &next_group(*pos);
|
||||
|
||||
// Remove from group
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == n)
|
||||
{
|
||||
get(next).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
}
|
||||
else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == n)
|
||||
{
|
||||
// The deleted node is not at the end of the group, so
|
||||
// change the link from the next node.
|
||||
get(next).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
else {
|
||||
// The deleted node is at the end of the group, so the
|
||||
// first node in the group is pointing to it.
|
||||
// Find that to change its pointer.
|
||||
node_ptr x = get(n).group_prev_;
|
||||
while(get(x).group_prev_ != n) {
|
||||
x = get(x).group_prev_;
|
||||
}
|
||||
get(x).group_prev_ = get(n).group_prev_;
|
||||
}
|
||||
*pos = next;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &next_group(begin);
|
||||
|
||||
if(*pos != begin) {
|
||||
// The node is at the beginning of a group.
|
||||
|
||||
// Find the previous node pointer:
|
||||
pos = &b.next_;
|
||||
while(*pos != begin) pos = &next_group(*pos);
|
||||
|
||||
// Remove from group
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
|
||||
}
|
||||
else {
|
||||
node_ptr group1 = split_group(begin);
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
|
||||
node_ptr group2 = split_group(end);
|
||||
|
||||
if(begin == group2) {
|
||||
node_ptr end1 = get(group1).group_prev_;
|
||||
node_ptr end2 = get(group2).group_prev_;
|
||||
get(group1).group_prev_ = end2;
|
||||
get(group2).group_prev_ = end1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pos = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
|
||||
{
|
||||
split_group(end);
|
||||
b.next_ = end;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,62 +1,39 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2011 Daniel James
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
||||
|
||||
#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 <cstddef>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
static const float minimum_max_load_factor = 1e-3f;
|
||||
static const std::size_t default_bucket_count = 11;
|
||||
struct move_tag {};
|
||||
struct empty_emplace {};
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// iterator SFINAE
|
||||
// convert double to std::size_t
|
||||
|
||||
template <typename I>
|
||||
struct is_forward :
|
||||
boost::is_convertible<
|
||||
typename boost::iterator_traversal<I>::type,
|
||||
boost::forward_traversal_tag>
|
||||
{};
|
||||
|
||||
template <typename I, typename ReturnType>
|
||||
struct enable_if_forward :
|
||||
boost::enable_if_c<
|
||||
boost::unordered::detail::is_forward<I>::value,
|
||||
ReturnType>
|
||||
{};
|
||||
|
||||
template <typename I, typename ReturnType>
|
||||
struct disable_if_forward :
|
||||
boost::disable_if_c<
|
||||
boost::unordered::detail::is_forward<I>::value,
|
||||
ReturnType>
|
||||
{};
|
||||
inline std::size_t double_to_size_t(double f)
|
||||
{
|
||||
return f >= static_cast<double>(
|
||||
(std::numeric_limits<std::size_t>::max)()) ?
|
||||
(std::numeric_limits<std::size_t>::max)() :
|
||||
static_cast<std::size_t>(f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// primes
|
||||
|
||||
#define BOOST_UNORDERED_PRIMES \
|
||||
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
||||
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
||||
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
|
||||
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
|
||||
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
|
||||
@@ -115,146 +92,240 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return *bound;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// pair_cast - because some libraries don't have the full pair constructors.
|
||||
|
||||
template <class Dst1, class Dst2, class Src1, class Src2>
|
||||
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
|
||||
{
|
||||
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// insert_size/initial_size
|
||||
|
||||
#if !defined(BOOST_NO_STD_DISTANCE)
|
||||
|
||||
using ::std::distance;
|
||||
|
||||
#else
|
||||
|
||||
template <class ForwardIterator>
|
||||
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
|
||||
std::size_t x;
|
||||
std::distance(i, j, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <class I>
|
||||
inline typename
|
||||
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
|
||||
insert_size(I i, I j)
|
||||
inline std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
|
||||
{
|
||||
return std::distance(i, j);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline typename
|
||||
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
|
||||
insert_size(I, I)
|
||||
inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t initial_size(I i, I j,
|
||||
std::size_t num_buckets =
|
||||
boost::unordered::detail::default_bucket_count)
|
||||
inline std::size_t insert_size(I i, I j)
|
||||
{
|
||||
// TODO: Why +1?
|
||||
return (std::max)(
|
||||
boost::unordered::detail::insert_size(i, j) + 1,
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
|
||||
iterator_traversal_tag;
|
||||
return insert_size(i, j, iterator_traversal_tag);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
inline std::size_t initial_size(I i, I j,
|
||||
std::size_t num_buckets = boost::unordered_detail::default_bucket_count)
|
||||
{
|
||||
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
|
||||
num_buckets);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// compressed
|
||||
// Node Constructors
|
||||
|
||||
template <typename T, int Index>
|
||||
struct compressed_base : private T
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class T, class... Args>
|
||||
inline void construct_impl(T*, void* address, Args&&... args)
|
||||
{
|
||||
compressed_base(T const& x) : T(x) {}
|
||||
compressed_base(T& x, move_tag) : T(boost::move(x)) {}
|
||||
new(address) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
T& get() { return *this; }
|
||||
T const& get() const { return *this; }
|
||||
};
|
||||
|
||||
template <typename T, int Index>
|
||||
struct uncompressed_base
|
||||
#if defined(BOOST_UNORDERED_CPP0X_PAIR)
|
||||
template <class First, class Second, class Key, class Arg0, class... Args>
|
||||
inline void construct_impl(std::pair<First, Second>*, void* address,
|
||||
Key&& k, Arg0&& arg0, Args&&... args)
|
||||
)
|
||||
{
|
||||
uncompressed_base(T const& x) : value_(x) {}
|
||||
uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
|
||||
new(address) std::pair<First, Second>(k,
|
||||
Second(arg0, std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
T& get() { return value_; }
|
||||
T const& get() const { return value_; }
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
template <typename T, int Index>
|
||||
struct generate_base
|
||||
: boost::detail::if_true<
|
||||
boost::is_empty<T>::value
|
||||
>:: BOOST_NESTED_TEMPLATE then<
|
||||
boost::unordered::detail::compressed_base<T, Index>,
|
||||
boost::unordered::detail::uncompressed_base<T, Index>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct compressed
|
||||
: private boost::unordered::detail::generate_base<T1, 1>::type,
|
||||
private boost::unordered::detail::generate_base<T2, 2>::type
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
T*, void* address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
} \
|
||||
\
|
||||
template <class First, class Second, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
std::pair<First, Second>*, void* address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
new(address) std::pair<First, Second>(k, \
|
||||
Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
#endif
|
||||
|
||||
// hash_node_constructor
|
||||
//
|
||||
// Used to construct nodes in an exception safe manner.
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
class hash_node_constructor
|
||||
{
|
||||
typedef typename generate_base<T1, 1>::type base1;
|
||||
typedef typename generate_base<T2, 2>::type base2;
|
||||
typedef hash_buckets<Alloc, Grouped> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
|
||||
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
first_type& first() {
|
||||
return static_cast<base1*>(this)->get();
|
||||
}
|
||||
buckets& buckets_;
|
||||
real_node_ptr node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
|
||||
first_type const& first() const {
|
||||
return static_cast<base1 const*>(this)->get();
|
||||
}
|
||||
public:
|
||||
|
||||
second_type& second() {
|
||||
return static_cast<base2*>(this)->get();
|
||||
}
|
||||
|
||||
second_type const& second() const {
|
||||
return static_cast<base2 const*>(this)->get();
|
||||
}
|
||||
|
||||
template <typename First, typename Second>
|
||||
compressed(First const& x1, Second const& x2)
|
||||
: base1(x1), base2(x2) {}
|
||||
|
||||
compressed(compressed const& x)
|
||||
: base1(x.first()), base2(x.second()) {}
|
||||
|
||||
compressed(compressed& x, move_tag m)
|
||||
: base1(x.first(), m), base2(x.second(), m) {}
|
||||
|
||||
void assign(compressed const& x)
|
||||
hash_node_constructor(buckets& m) :
|
||||
buckets_(m),
|
||||
node_(),
|
||||
node_constructed_(false),
|
||||
value_constructed_(false)
|
||||
{
|
||||
first() = x.first();
|
||||
second() = x.second();
|
||||
}
|
||||
|
||||
void move_assign(compressed& x)
|
||||
~hash_node_constructor();
|
||||
void construct_preamble();
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class... Args>
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
first() = boost::move(x.first());
|
||||
second() = boost::move(x.second());
|
||||
construct_preamble();
|
||||
construct_impl((value_type*) 0, node_->address(),
|
||||
std::forward<Args>(args)...);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
void swap(compressed& x)
|
||||
{
|
||||
boost::swap(first(), x.first());
|
||||
boost::swap(second(), x.second());
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
void construct( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
construct_preamble(); \
|
||||
construct_impl( \
|
||||
(value_type*) 0, node_->address(), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
|
||||
); \
|
||||
value_constructed_ = true; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT
|
||||
|
||||
#endif
|
||||
template <class K, class M>
|
||||
void construct_pair(K const& k, M*)
|
||||
{
|
||||
construct_preamble();
|
||||
new(node_->address()) value_type(k, M());
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
value_type& value() const
|
||||
{
|
||||
BOOST_ASSERT(node_);
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
// no throw
|
||||
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
|
||||
{
|
||||
real_node_ptr p = node_;
|
||||
node_ = real_node_ptr();
|
||||
// node_ptr cast
|
||||
return buckets_.bucket_alloc().address(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
// Prevent assignment just to make use of assign or
|
||||
// move_assign explicit.
|
||||
compressed& operator=(compressed const&);
|
||||
hash_node_constructor(hash_node_constructor const&);
|
||||
hash_node_constructor& operator=(hash_node_constructor const&);
|
||||
};
|
||||
}}}
|
||||
|
||||
// hash_node_constructor
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
||||
struct dummy { hash_node<Alloc, Grouped> x; };
|
||||
#endif
|
||||
boost::unordered_detail::destroy(node_->value_ptr());
|
||||
}
|
||||
|
||||
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_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (C) 2008-2011 Daniel James.
|
||||
// Copyright (C) 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -14,52 +14,40 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_map;
|
||||
template <class K,
|
||||
class T,
|
||||
class H = hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_map;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline void swap(unordered_map<K, T, H, P, A>&,
|
||||
unordered_map<K, T, H, P, A>&);
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline void swap(unordered_map<K, T, H, P, A>&,
|
||||
unordered_map<K, T, H, P, A>&);
|
||||
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_multimap;
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline void swap(unordered_multimap<K, T, H, P, A>&,
|
||||
unordered_multimap<K, T, H, P, A>&);
|
||||
}
|
||||
|
||||
using boost::unordered::unordered_map;
|
||||
using boost::unordered::unordered_multimap;
|
||||
using boost::unordered::swap;
|
||||
using boost::unordered::operator==;
|
||||
using boost::unordered::operator!=;
|
||||
template <class K,
|
||||
class T,
|
||||
class H = hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_multimap;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
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>&);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (C) 2008-2011 Daniel James.
|
||||
// Copyright (C) 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -14,50 +14,38 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_set;
|
||||
template <class T,
|
||||
class H = hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_set;
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2);
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2);
|
||||
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_multiset;
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
unordered_multiset<T, H, P, A> &m2);
|
||||
}
|
||||
|
||||
using boost::unordered::unordered_set;
|
||||
using boost::unordered::unordered_multiset;
|
||||
using boost::unordered::swap;
|
||||
using boost::unordered::operator==;
|
||||
using boost::unordered::operator!=;
|
||||
template <class T,
|
||||
class H = hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_multiset;
|
||||
template <class T, class H, class P, class A>
|
||||
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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>msvc:<warnings-as-errors>on
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
@@ -11,7 +13,7 @@
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t initialize_seed(12847);
|
||||
test::seed_t seed(12847);
|
||||
|
||||
template <class T>
|
||||
struct self_assign_base : public test::exception_base
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
test::seed_t initialize_seed(91274);
|
||||
test::seed_t seed(91274);
|
||||
|
||||
struct objects
|
||||
{
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
#include "../objects/exception.hpp"
|
||||
|
||||
typedef boost::unordered_set<
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
test::seed_t initialize_seed(73041);
|
||||
test::seed_t seed(73041);
|
||||
|
||||
template <class T>
|
||||
struct copy_test1 : public test::exception_base
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
test::seed_t initialize_seed(835193);
|
||||
test::seed_t seed(835193);
|
||||
|
||||
template <class T>
|
||||
struct erase_test_base : public test::exception_base
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include <string>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -11,7 +13,7 @@
|
||||
#include <boost/utility.hpp>
|
||||
#include <cmath>
|
||||
|
||||
test::seed_t initialize_seed(747373);
|
||||
test::seed_t seed(747373);
|
||||
|
||||
template <class T>
|
||||
struct insert_test_base : public test::exception_base
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include <string>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -11,7 +13,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
test::seed_t initialize_seed(3298597);
|
||||
test::seed_t seed(3298597);
|
||||
|
||||
template <class T>
|
||||
struct rehash_test_base : public test::exception_base
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
@@ -11,7 +13,7 @@
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t initialize_seed(9387);
|
||||
test::seed_t seed(9387);
|
||||
|
||||
template <class T>
|
||||
struct self_swap_base : public test::exception_base
|
||||
@@ -25,12 +27,13 @@ struct self_swap_base : public test::exception_base
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
|
||||
std::string scope(test::scope);
|
||||
|
||||
// TODO: In C++11 exceptions are only allowed in the swap function.
|
||||
#if BOOST_UNORDERED_SWAP_METHOD != 2
|
||||
BOOST_TEST(
|
||||
scope == "hash::hash(hash)" ||
|
||||
scope == "hash::operator(hash)" ||
|
||||
scope == "hash::operator=(hash)" ||
|
||||
scope == "equal_to::equal_to(equal_to)" ||
|
||||
scope == "equal_to::operator(equal_to)" ||
|
||||
scope == "equal_to::operator=(equal_to)");
|
||||
#endif
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
@@ -79,12 +82,13 @@ struct swap_base : public test::exception_base
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
|
||||
std::string scope(test::scope);
|
||||
|
||||
// TODO: In C++11 exceptions are only allowed in the swap function.
|
||||
#if BOOST_UNORDERED_SWAP_METHOD != 2
|
||||
BOOST_TEST(
|
||||
scope == "hash::hash(hash)" ||
|
||||
scope == "hash::operator(hash)" ||
|
||||
scope == "hash::operator=(hash)" ||
|
||||
scope == "equal_to::equal_to(equal_to)" ||
|
||||
scope == "equal_to::operator(equal_to)" ||
|
||||
scope == "equal_to::operator=(equal_to)");
|
||||
#endif
|
||||
|
||||
test::check_equivalent_keys(d.x);
|
||||
test::check_equivalent_keys(d.y);
|
||||
|
||||
@@ -75,13 +75,6 @@ namespace test {
|
||||
namespace {
|
||||
object_count& global_object_count = globally_counted_object::count_;
|
||||
}
|
||||
|
||||
struct check_instances {
|
||||
int instances;
|
||||
|
||||
check_instances() : instances(global_object_count.instances) {}
|
||||
~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+28
-23
@@ -38,7 +38,7 @@ namespace test
|
||||
it = x1.begin(), end = x1.end();
|
||||
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
|
||||
while(it != end) {
|
||||
// First test that the current key has not occurred before, required
|
||||
// First test that the current key has not occured before, required
|
||||
// to test either that keys are unique or that equivalent keys are
|
||||
// adjacent. (6.3.1/6)
|
||||
key_type key = get_key<X>(*it);
|
||||
@@ -65,32 +65,37 @@ namespace test
|
||||
std::cerr<<x1.count(key)<<","<<count<<"\n";
|
||||
}
|
||||
|
||||
// Check that the keys are in the correct bucket and are
|
||||
// adjacent in the bucket.
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
|
||||
BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
lit = x1.begin(bucket), lend = x1.end(bucket);
|
||||
for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
|
||||
if(lit == lend)
|
||||
BOOST_ERROR("Unable to find element with a local_iterator");
|
||||
unsigned int count2 = 0;
|
||||
for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
|
||||
if(count != count2)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for(; lit != lend; ++lit) {
|
||||
if(eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
"in bucket.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// I'm not bothering with the following test for now, as the
|
||||
// previous test is probably more enough to catch the kind of
|
||||
// errors that this would catch (if an element was in the wrong
|
||||
// bucket it not be found by the call to count, if elements are not
|
||||
// adjacent then they would be caught when checking against
|
||||
// found_.
|
||||
|
||||
// // Check that the keys are in the correct bucket and are
|
||||
// // adjacent in the bucket.
|
||||
// BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
|
||||
// BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
// lit = x1.begin(bucket), lend = x1.end(bucket);
|
||||
// for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
|
||||
// if(lit == lend)
|
||||
// BOOST_ERROR("Unable to find element with a local_iterator");
|
||||
// unsigned int count2 = 0;
|
||||
// for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
|
||||
// if(count != count2)
|
||||
// BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
// for(; lit != lend; ++lit) {
|
||||
// if(eq(get_key<X>(*lit), key)) {
|
||||
// BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
// "in bucket.");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -219,14 +219,14 @@ namespace test
|
||||
data_.last_ptr_ = &data_.first_;
|
||||
}
|
||||
|
||||
void erase(const_iterator i, const_iterator j) {
|
||||
void erase(const_iterator start, const_iterator end) {
|
||||
node** ptr = &data_.first_;
|
||||
|
||||
while(*ptr != i.ptr_) {
|
||||
while(*ptr != start.ptr_) {
|
||||
ptr = &(*ptr)->next_;
|
||||
}
|
||||
|
||||
while(*ptr != j.ptr_) {
|
||||
while(*ptr != end.ptr_) {
|
||||
node* to_delete = *ptr;
|
||||
*ptr = (*ptr)->next_;
|
||||
--data_.size_;
|
||||
|
||||
+3
-39
@@ -70,7 +70,7 @@ namespace test
|
||||
template <class Alloc = std::allocator<int> >
|
||||
struct memory_tracker {
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
::boost::unordered::detail::rebind_wrap<Alloc,
|
||||
boost::unordered_detail::rebind_wrap<Alloc,
|
||||
std::pair<memory_area const, memory_track> >::type
|
||||
allocator_type;
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace test
|
||||
}
|
||||
|
||||
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
|
||||
int tag, bool check_tag_ = true)
|
||||
int tag)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
|
||||
allocated_memory.find(
|
||||
@@ -147,7 +147,7 @@ namespace test
|
||||
} else {
|
||||
BOOST_TEST(pos->first.start == ptr);
|
||||
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
|
||||
if (check_tag_) BOOST_TEST(pos->second.tag_ == tag);
|
||||
BOOST_TEST(pos->second.tag_ == tag);
|
||||
allocated_memory.erase(pos);
|
||||
}
|
||||
BOOST_TEST(count_allocations > 0);
|
||||
@@ -168,42 +168,6 @@ namespace test
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This won't be a problem as I'm only using a single compile unit
|
||||
// in each test (this is actually required by the minimal test
|
||||
// framework).
|
||||
//
|
||||
// boostinspect:nounnamed
|
||||
namespace {
|
||||
test::detail::memory_tracker<std::allocator<int> > tracker;
|
||||
}
|
||||
}
|
||||
|
||||
template <int Value>
|
||||
struct bool_type {
|
||||
enum { value = (Value ? true : false) };
|
||||
};
|
||||
|
||||
struct true_type {
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
struct false_type {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
struct convert_from_anything
|
||||
{
|
||||
template <typename T>
|
||||
convert_from_anything(T const&) {}
|
||||
};
|
||||
|
||||
int selected_count(convert_from_anything)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
// Copyright 2012 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Include this after the boost headers, but before other test headers.
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
@@ -124,8 +124,8 @@ namespace test
|
||||
: base()
|
||||
{}
|
||||
|
||||
explicit ordered(key_compare const& kc)
|
||||
: base(kc)
|
||||
explicit ordered(key_compare const& compare)
|
||||
: base(compare)
|
||||
{}
|
||||
|
||||
void compare(X const& x)
|
||||
@@ -143,10 +143,10 @@ namespace test
|
||||
}
|
||||
|
||||
template <class It>
|
||||
void insert_range(It b, It e) {
|
||||
while(b != e) {
|
||||
this->insert(*b);
|
||||
++b;
|
||||
void insert_range(It begin, It end) {
|
||||
while(begin != end) {
|
||||
this->insert(*begin);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
|
||||
// Copyright 2006-2011 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include "../helpers/memory.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
struct allocator_false
|
||||
{
|
||||
enum {
|
||||
is_select_on_copy = 0,
|
||||
is_propagate_on_swap = 0,
|
||||
is_propagate_on_assign = 0,
|
||||
is_propagate_on_move = 0
|
||||
};
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
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_UNORDERED_VARIADIC_MOVE)
|
||||
template<typename... Args> void construct(T* p, 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_;
|
||||
}
|
||||
|
||||
template <typename T, typename Flags>
|
||||
int selected_count(cxx11_allocator<T, Flags> const& x)
|
||||
{
|
||||
return x.selected_;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -34,16 +34,6 @@ namespace exception
|
||||
template <class T> class allocator;
|
||||
object generate(object const*);
|
||||
|
||||
struct true_type
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
struct false_type
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
class object
|
||||
{
|
||||
public:
|
||||
@@ -350,24 +340,24 @@ namespace exception
|
||||
}
|
||||
|
||||
void construct(pointer p, T const& t) {
|
||||
UNORDERED_SCOPE(allocator::construct(T*, T)) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, T)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
new(p) T(t);
|
||||
}
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
}
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy(T* p) {
|
||||
void destroy(pointer p) {
|
||||
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
|
||||
p->~T();
|
||||
}
|
||||
@@ -378,10 +368,6 @@ namespace exception
|
||||
}
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
typedef true_type propagate_on_container_copy_assignment;
|
||||
typedef true_type propagate_on_container_move_assignment;
|
||||
typedef true_type propagate_on_container_swap;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
||||
+31
-181
@@ -11,8 +11,6 @@
|
||||
#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
@@ -23,7 +21,6 @@ namespace test
|
||||
{
|
||||
namespace minimal
|
||||
{
|
||||
class destructible;
|
||||
class copy_constructible;
|
||||
class copy_constructible_equality_comparable;
|
||||
class default_copy_constructible;
|
||||
@@ -36,27 +33,11 @@ namespace minimal
|
||||
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:
|
||||
copy_constructible(constructor_param const&) {}
|
||||
static copy_constructible create() { return copy_constructible(); }
|
||||
copy_constructible(copy_constructible const&) {}
|
||||
~copy_constructible() {}
|
||||
private:
|
||||
@@ -67,7 +48,9 @@ namespace minimal
|
||||
class copy_constructible_equality_comparable
|
||||
{
|
||||
public:
|
||||
copy_constructible_equality_comparable(constructor_param const&) {}
|
||||
static copy_constructible_equality_comparable create() {
|
||||
return copy_constructible_equality_comparable();
|
||||
}
|
||||
|
||||
copy_constructible_equality_comparable(
|
||||
copy_constructible_equality_comparable const&)
|
||||
@@ -102,7 +85,10 @@ namespace minimal
|
||||
class default_copy_constructible
|
||||
{
|
||||
public:
|
||||
default_copy_constructible(constructor_param const&) {}
|
||||
static default_copy_constructible create()
|
||||
{
|
||||
return default_copy_constructible();
|
||||
}
|
||||
|
||||
default_copy_constructible()
|
||||
{
|
||||
@@ -119,14 +105,13 @@ namespace minimal
|
||||
private:
|
||||
default_copy_constructible& operator=(
|
||||
default_copy_constructible const&);
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
class assignable
|
||||
{
|
||||
public:
|
||||
assignable(constructor_param const&) {}
|
||||
static assignable create() { return assignable(); }
|
||||
assignable(assignable const&) {}
|
||||
assignable& operator=(assignable const&) { return *this; }
|
||||
~assignable() {}
|
||||
@@ -137,43 +122,11 @@ namespace minimal
|
||||
//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:
|
||||
hash(constructor_param const&) {}
|
||||
static hash create() { return hash<T>(); }
|
||||
hash() {}
|
||||
hash(hash const&) {}
|
||||
hash& operator=(hash const&) { return *this; }
|
||||
@@ -188,7 +141,7 @@ namespace minimal
|
||||
class equal_to
|
||||
{
|
||||
public:
|
||||
equal_to(constructor_param const&) {}
|
||||
static equal_to create() { return equal_to<T>(); }
|
||||
equal_to() {}
|
||||
equal_to(equal_to const&) {}
|
||||
equal_to& operator=(equal_to const&) { return *this; }
|
||||
@@ -202,67 +155,17 @@ namespace minimal
|
||||
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_; }
|
||||
@@ -284,6 +187,13 @@ 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(); }
|
||||
@@ -293,7 +203,6 @@ namespace minimal
|
||||
class const_ptr
|
||||
{
|
||||
friend class allocator<T>;
|
||||
friend struct const_void_ptr;
|
||||
|
||||
T const* ptr_;
|
||||
|
||||
@@ -301,7 +210,6 @@ namespace minimal
|
||||
public:
|
||||
const_ptr() : ptr_(0) {}
|
||||
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
|
||||
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
|
||||
|
||||
T const& operator*() const { return *ptr_; }
|
||||
T const* operator->() const { return ptr_; }
|
||||
@@ -315,6 +223,13 @@ 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_; }
|
||||
@@ -332,8 +247,6 @@ namespace minimal
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef void_ptr void_pointer;
|
||||
typedef void_const_ptr const_void_pointer;
|
||||
typedef ptr<T> pointer;
|
||||
typedef const_ptr<T> const_pointer;
|
||||
typedef T& reference;
|
||||
@@ -365,15 +278,15 @@ namespace minimal
|
||||
::operator delete((void*) p.ptr_);
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
new((void*)p.ptr_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy(T* p) { p->~T(); }
|
||||
void destroy(pointer p) { ((T*)p.ptr_)->~T(); }
|
||||
|
||||
size_type max_size() const { return 1000; }
|
||||
|
||||
@@ -403,69 +316,6 @@ namespace minimal
|
||||
void swap(allocator<T>&, allocator<T>&)
|
||||
{
|
||||
}
|
||||
|
||||
// C++11 allocator
|
||||
//
|
||||
// Not a fully minimal C++11 allocator, just what I support. Hopefully will
|
||||
// cut down further in the future.
|
||||
|
||||
template <class T>
|
||||
class cxx11_allocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
|
||||
|
||||
cxx11_allocator() {}
|
||||
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
|
||||
cxx11_allocator(cxx11_allocator const&) {}
|
||||
~cxx11_allocator() {}
|
||||
|
||||
T* address(T& r) { return &r; }
|
||||
T const* address(T const& r) { return &r; }
|
||||
|
||||
T* allocate(std::size_t n) {
|
||||
return static_cast<T*>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
template <class Y>
|
||||
T* allocate(std::size_t n, const_ptr<Y> u) {
|
||||
return static_cast<T*>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t) {
|
||||
::operator delete((void*) p);
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, 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>&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+59
-41
@@ -9,24 +9,24 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include "../helpers/count.hpp"
|
||||
#include "../helpers/memory.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace test
|
||||
{
|
||||
// Note that the default hash function will work for any equal_to (but not
|
||||
// very well).
|
||||
class object;
|
||||
class implicitly_convertible;
|
||||
class hash;
|
||||
class less;
|
||||
class equal_to;
|
||||
template <class T> class allocator;
|
||||
object generate(object const*);
|
||||
implicitly_convertible generate(implicitly_convertible const*);
|
||||
|
||||
class object : private globally_counted_object
|
||||
|
||||
class object : globally_counted_object
|
||||
{
|
||||
friend class hash;
|
||||
friend class equal_to;
|
||||
@@ -64,31 +64,6 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
class implicitly_convertible : private globally_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_;
|
||||
@@ -183,6 +158,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 require by the minimal test
|
||||
// framework).
|
||||
//
|
||||
// boostinspect:nounnamed
|
||||
namespace {
|
||||
test::detail::memory_tracker<std::allocator<int> > tracker;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class allocator
|
||||
{
|
||||
@@ -254,19 +241,19 @@ namespace test
|
||||
::operator delete((void*) p);
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t) {
|
||||
void construct(pointer p, T const& t) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template<class... Args> void construct(pointer p, Args&&... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy(T* p) {
|
||||
void destroy(pointer p) {
|
||||
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
|
||||
p->~T();
|
||||
}
|
||||
@@ -284,13 +271,6 @@ namespace test
|
||||
{
|
||||
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>
|
||||
@@ -299,6 +279,44 @@ namespace test
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3)
|
||||
void swap(test::object& x, test::object& y) {
|
||||
test::object tmp;
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
void swap(test::hash& x, test::hash& y) {
|
||||
test::hash tmp;
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
void swap(test::less& x, test::less& y) {
|
||||
test::less tmp;
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
void swap(test::equal_to& x, test::equal_to& y) {
|
||||
test::equal_to tmp;
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void swap(test::allocator<T>& x, test::allocator<T>& y) {
|
||||
test::allocator<T> tmp;
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,23 +9,19 @@ project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
# Would be nice to define -Wundef, but I'm getting warnings from
|
||||
# Boost.Preprocessor on trunk.
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
|
||||
#<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<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
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
test-suite unordered
|
||||
:
|
||||
[ run fwd_set_test.cpp ]
|
||||
[ run fwd_map_test.cpp ]
|
||||
[ run allocator_traits.cpp ]
|
||||
[ run minimal_allocator.cpp ]
|
||||
[ run compile_set.cpp ]
|
||||
[ run compile_map.cpp ]
|
||||
[ run link_test_1.cpp link_test_2.cpp ]
|
||||
@@ -37,9 +33,6 @@ test-suite unordered
|
||||
[ 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 ]
|
||||
@@ -50,22 +43,5 @@ test-suite unordered
|
||||
[ run load_factor_tests.cpp ]
|
||||
[ run rehash_tests.cpp ]
|
||||
[ run equality_tests.cpp ]
|
||||
[ 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 ]
|
||||
[ run swap_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
;
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
|
||||
// Copyright 2011 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/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_MPL_ASSERT((boost::is_same<traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
|
||||
#endif
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
|
||||
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_MPL_ASSERT((boost::is_same<traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
|
||||
#endif
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
|
||||
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_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
|
||||
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_MPL_ASSERT((boost::is_same<traits::size_type, unsigned short>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, ptr<int> >));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
|
||||
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();
|
||||
}
|
||||
@@ -4,25 +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 "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace assign_tests {
|
||||
|
||||
test::seed_t initialize_seed(96785);
|
||||
test::seed_t seed(96785);
|
||||
|
||||
template <class T>
|
||||
void assign_tests1(T*,
|
||||
@@ -33,8 +28,6 @@ void assign_tests1(T*,
|
||||
|
||||
std::cerr<<"assign_tests1.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x;
|
||||
x = x;
|
||||
BOOST_TEST(x.empty());
|
||||
@@ -44,8 +37,6 @@ 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());
|
||||
|
||||
@@ -57,12 +48,9 @@ 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() == mlf);
|
||||
BOOST_TEST(y.max_load_factor() == mlf);
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +64,9 @@ 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);
|
||||
@@ -94,22 +78,13 @@ 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));
|
||||
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));
|
||||
}
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
test::check_container(x2, v1);
|
||||
}
|
||||
}
|
||||
@@ -127,69 +102,16 @@ boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multimap;
|
||||
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::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;
|
||||
|
||||
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_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
|
||||
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
|
||||
)
|
||||
UNORDERED_TEST(assign_tests1,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(assign_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
|
||||
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
|
||||
)
|
||||
UNORDERED_TEST(assign_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
@@ -208,7 +130,9 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
UNORDERED_AUTO_TEST(assign_initializer_list)
|
||||
{
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
|
||||
@@ -4,9 +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_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <algorithm>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -21,13 +20,11 @@
|
||||
|
||||
namespace bucket_tests {
|
||||
|
||||
test::seed_t initialize_seed(54635);
|
||||
test::seed_t seed(54635);
|
||||
|
||||
template <class X>
|
||||
void tests(X* = 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);
|
||||
|
||||
@@ -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,19 +17,6 @@
|
||||
|
||||
// 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,
|
||||
@@ -45,21 +32,16 @@ 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(x, x);
|
||||
value_type value(
|
||||
test::minimal::assignable::create(),
|
||||
test::minimal::copy_constructible::create());
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<int, int> int_map;
|
||||
|
||||
boost::unordered_map<int, int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<std::pair<int const, int> >
|
||||
> int_map2;
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
@@ -68,18 +50,12 @@ 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,
|
||||
@@ -88,49 +64,35 @@ 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::copy_constructible_equality_comparable const,
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::copy_constructible> value_type;
|
||||
|
||||
boost::unordered_map<int, int> int_map;
|
||||
|
||||
boost::unordered_map<int, int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<std::pair<int const, int> >
|
||||
> int_map2;
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > map;
|
||||
|
||||
equality_test(int_map);
|
||||
equality_test(int_map2);
|
||||
equality_test(map);
|
||||
|
||||
boost::unordered_multimap<int, int> int_multimap;
|
||||
|
||||
boost::unordered_multimap<int, int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<std::pair<int const, int> >
|
||||
> int_multimap2;
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > multimap;
|
||||
|
||||
equality_test(int_multimap);
|
||||
equality_test(int_multimap2);
|
||||
equality_test(multimap);
|
||||
}
|
||||
|
||||
@@ -144,47 +106,30 @@ UNORDERED_AUTO_TEST(test1) {
|
||||
|
||||
boost::unordered_map<int, int> map;
|
||||
|
||||
boost::unordered_map<int, int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<std::pair<int const, int> >
|
||||
> map2;
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, value, value);
|
||||
unordered_copyable_test(map, value, map_value, hash, equal_to);
|
||||
unordered_test(map, value, map_value, hash, equal_to);
|
||||
unordered_map_functions(map, value, value);
|
||||
|
||||
unordered_unique_test(map2, map_value);
|
||||
unordered_map_test(map2, value, value);
|
||||
unordered_copyable_test(map2, value, map_value, hash, equal_to);
|
||||
unordered_map_functions(map2, value, value);
|
||||
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<int, int> multimap;
|
||||
|
||||
boost::unordered_multimap<int, int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<std::pair<int const, int> >
|
||||
> multimap2;
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, value, value);
|
||||
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
|
||||
|
||||
unordered_equivalent_test(multimap2, map_value);
|
||||
unordered_map_test(multimap2, value, value);
|
||||
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
|
||||
unordered_test(multimap, value, map_value, hash, equal_to);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(test2)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::assignable assignable(x);
|
||||
test::minimal::copy_constructible copy_constructible(x);
|
||||
test::minimal::hash<test::minimal::assignable> hash(x);
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
test::minimal::assignable assignable
|
||||
= test::minimal::assignable::create();
|
||||
test::minimal::copy_constructible copy_constructible
|
||||
= test::minimal::copy_constructible::create();
|
||||
test::minimal::hash<test::minimal::assignable> hash
|
||||
= test::minimal::hash<test::minimal::assignable>::create();
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to
|
||||
= test::minimal::equal_to<test::minimal::assignable>::create();
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::copy_constructible> map_value_type;
|
||||
@@ -201,7 +146,8 @@ UNORDERED_AUTO_TEST(test2)
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, assignable, copy_constructible);
|
||||
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
|
||||
unordered_test(map, assignable, map_value, hash, equal_to);
|
||||
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
@@ -225,7 +171,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, assignable, copy_constructible);
|
||||
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
|
||||
unordered_test(multimap, assignable, map_value, hash, equal_to);
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
+23
-173
@@ -7,8 +7,8 @@
|
||||
// requirements. Makes sure everything compiles and is defined correctly.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
@@ -17,17 +17,6 @@
|
||||
|
||||
// Explicit instantiation to catch compile-time errors
|
||||
|
||||
template class boost::unordered_set<
|
||||
int,
|
||||
boost::hash<int>,
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multiset<
|
||||
int,
|
||||
boost::hash<int>,
|
||||
std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
|
||||
template class boost::unordered_set<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@@ -41,19 +30,10 @@ template class boost::unordered_multiset<
|
||||
|
||||
UNORDERED_AUTO_TEST(test0)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::assignable assignable(x);
|
||||
test::minimal::assignable assignable = test::minimal::assignable::create();
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<int> int_set;
|
||||
|
||||
boost::unordered_set<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> int_set2;
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@@ -61,18 +41,10 @@ UNORDERED_AUTO_TEST(test0)
|
||||
test::minimal::allocator<test::minimal::assignable> > set;
|
||||
|
||||
container_test(int_set, 0);
|
||||
container_test(int_set2, 0);
|
||||
container_test(set, assignable);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
boost::unordered_multiset<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> int_multiset2;
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@@ -80,45 +52,32 @@ UNORDERED_AUTO_TEST(test0)
|
||||
test::minimal::allocator<test::minimal::assignable> > multiset;
|
||||
|
||||
container_test(int_multiset, 0);
|
||||
container_test(int_multiset2, 0);
|
||||
container_test(multiset, assignable);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_tests) {
|
||||
typedef test::minimal::copy_constructible_equality_comparable value_type;
|
||||
typedef test::minimal::assignable value_type;
|
||||
|
||||
boost::unordered_set<int> int_set;
|
||||
|
||||
boost::unordered_set<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> int_set2;
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > set;
|
||||
|
||||
equality_test(int_set);
|
||||
equality_test(int_set2);
|
||||
equality_test(set);
|
||||
|
||||
boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
boost::unordered_multiset<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> int_multiset2;
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::copy_constructible_equality_comparable,
|
||||
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > multiset;
|
||||
|
||||
equality_test(int_multiset);
|
||||
equality_test(int_multiset2);
|
||||
equality_test(multiset);
|
||||
}
|
||||
|
||||
@@ -128,49 +87,33 @@ UNORDERED_AUTO_TEST(test1)
|
||||
std::equal_to<int> equal_to;
|
||||
int value = 0;
|
||||
|
||||
std::cout<<"Test unordered_set." << std::endl;
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<int> set;
|
||||
|
||||
boost::unordered_set<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> set2;
|
||||
|
||||
unordered_unique_test(set, value);
|
||||
unordered_set_test(set, value);
|
||||
unordered_copyable_test(set, value, value, hash, equal_to);
|
||||
unordered_test(set, value, value, hash, equal_to);
|
||||
|
||||
unordered_unique_test(set2, value);
|
||||
unordered_set_test(set2, value);
|
||||
unordered_copyable_test(set2, value, value, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset." << std::endl;
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<int> multiset;
|
||||
|
||||
boost::unordered_multiset<int,
|
||||
boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::cxx11_allocator<int>
|
||||
> multiset2;
|
||||
|
||||
unordered_equivalent_test(multiset, value);
|
||||
unordered_set_test(multiset, value);
|
||||
unordered_copyable_test(multiset, value, value, hash, equal_to);
|
||||
|
||||
unordered_equivalent_test(multiset2, value);
|
||||
unordered_set_test(multiset2, value);
|
||||
unordered_copyable_test(multiset2, value, value, hash, equal_to);
|
||||
unordered_test(multiset, value, value, hash, equal_to);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(test2)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::assignable assignable(x);
|
||||
test::minimal::copy_constructible copy_constructible(x);
|
||||
test::minimal::hash<test::minimal::assignable> hash(x);
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
test::minimal::assignable assignable
|
||||
= test::minimal::assignable::create();
|
||||
test::minimal::copy_constructible copy_constructible
|
||||
= test::minimal::copy_constructible::create();
|
||||
test::minimal::hash<test::minimal::assignable> hash
|
||||
= test::minimal::hash<test::minimal::assignable>::create();
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to
|
||||
= test::minimal::equal_to<test::minimal::assignable>::create();
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
@@ -182,7 +125,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
|
||||
unordered_unique_test(set, assignable);
|
||||
unordered_set_test(set, assignable);
|
||||
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
|
||||
unordered_test(set, assignable, assignable, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
@@ -194,100 +137,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
|
||||
unordered_equivalent_test(multiset, assignable);
|
||||
unordered_set_test(multiset, assignable);
|
||||
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(movable1_tests)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::movable1 movable1(x);
|
||||
test::minimal::hash<test::minimal::movable1> hash(x);
|
||||
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::movable1,
|
||||
test::minimal::hash<test::minimal::movable1>,
|
||||
test::minimal::equal_to<test::minimal::movable1>,
|
||||
test::minimal::allocator<test::minimal::movable1> > set;
|
||||
|
||||
//unordered_unique_test(set, movable1);
|
||||
unordered_set_test(set, movable1);
|
||||
unordered_movable_test(set, movable1, movable1, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::movable1,
|
||||
test::minimal::hash<test::minimal::movable1>,
|
||||
test::minimal::equal_to<test::minimal::movable1>,
|
||||
test::minimal::allocator<test::minimal::movable1> > multiset;
|
||||
|
||||
//unordered_equivalent_test(multiset, movable1);
|
||||
unordered_set_test(multiset, movable1);
|
||||
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(movable2_tests)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::movable2 movable2(x);
|
||||
test::minimal::hash<test::minimal::movable2> hash(x);
|
||||
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::movable2,
|
||||
test::minimal::hash<test::minimal::movable2>,
|
||||
test::minimal::equal_to<test::minimal::movable2>,
|
||||
test::minimal::allocator<test::minimal::movable2> > set;
|
||||
|
||||
//unordered_unique_test(set, movable2);
|
||||
unordered_set_test(set, movable2);
|
||||
unordered_movable_test(set, movable2, movable2, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::movable2,
|
||||
test::minimal::hash<test::minimal::movable2>,
|
||||
test::minimal::equal_to<test::minimal::movable2>,
|
||||
test::minimal::allocator<test::minimal::movable2> > multiset;
|
||||
|
||||
//unordered_equivalent_test(multiset, movable2);
|
||||
unordered_set_test(multiset, movable2);
|
||||
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(destructible_tests)
|
||||
{
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
test::minimal::destructible destructible(x);
|
||||
test::minimal::hash<test::minimal::destructible> hash(x);
|
||||
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::destructible,
|
||||
test::minimal::hash<test::minimal::destructible>,
|
||||
test::minimal::equal_to<test::minimal::destructible> > set;
|
||||
|
||||
unordered_destructible_test(set);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::destructible,
|
||||
test::minimal::hash<test::minimal::destructible>,
|
||||
test::minimal::equal_to<test::minimal::destructible> > multiset;
|
||||
|
||||
unordered_destructible_test(multiset);
|
||||
unordered_test(multiset, assignable, assignable, hash, equal_to);
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -22,14 +22,12 @@
|
||||
#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&)
|
||||
@@ -111,50 +109,15 @@ void container_test(X& r, T const&)
|
||||
BOOST_TEST(X().size() == 0);
|
||||
|
||||
X a,b;
|
||||
X a_const;
|
||||
|
||||
sink(X(a));
|
||||
X u2(a);
|
||||
X u3 = a;
|
||||
|
||||
a.swap(b);
|
||||
boost::swap(a, b);
|
||||
test::check_return_type<X>::equals_ref(r = a);
|
||||
|
||||
// Allocator
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
sink(u);
|
||||
sink(u2);
|
||||
sink(u3);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void unordered_destructible_test(X&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
|
||||
|
||||
X x1;
|
||||
|
||||
#if !defined(BOOST_NO_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());
|
||||
@@ -166,8 +129,7 @@ void unordered_destructible_test(X&)
|
||||
test::check_return_type<const_iterator>::equals(a_const.cend());
|
||||
|
||||
a.swap(b);
|
||||
boost::swap(a, b);
|
||||
|
||||
test::check_return_type<X>::equals_ref(r = a);
|
||||
test::check_return_type<size_type>::equals(a.size());
|
||||
test::check_return_type<size_type>::equals(a.max_size());
|
||||
test::check_return_type<bool>::convertible(a.empty());
|
||||
@@ -176,6 +138,12 @@ void unordered_destructible_test(X&)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
sink(u);
|
||||
sink(u2);
|
||||
sink(u3);
|
||||
}
|
||||
|
||||
template <class X, class Key>
|
||||
@@ -192,7 +160,6 @@ 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> >));
|
||||
|
||||
@@ -213,8 +180,6 @@ void equality_test(X& r)
|
||||
|
||||
test::check_return_type<bool>::equals(a == b);
|
||||
test::check_return_type<bool>::equals(a != b);
|
||||
test::check_return_type<bool>::equals(boost::operator==(a, b));
|
||||
test::check_return_type<bool>::equals(boost::operator!=(a, b));
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
@@ -246,11 +211,9 @@ void unordered_map_functions(X&, Key const& k, T const&)
|
||||
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
|
||||
}
|
||||
|
||||
template <class X, class Key, class Hash, class Pred>
|
||||
void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
template <class X, class Key, class T, class Hash, class Pred>
|
||||
void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
{
|
||||
unordered_destructible_test(x);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
|
||||
@@ -314,8 +277,8 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
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::function_requires<boost::CopyConstructibleConcept<key_type> >();
|
||||
boost::function_requires<boost::AssignableConcept<key_type> >();
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
|
||||
test::check_return_type<std::size_t>::equals(hf(k));
|
||||
@@ -353,18 +316,45 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
X();
|
||||
X a4;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
|
||||
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
|
||||
|
||||
X(i, j, 10, hf, eq);
|
||||
X a5(i, j, 10, hf, eq);
|
||||
X(i, j, 10, hf);
|
||||
X a6(i, j, 10, hf);
|
||||
X(i, j, 10);
|
||||
X a7(i, j, 10);
|
||||
X(i, j);
|
||||
X a8(i, j);
|
||||
|
||||
X const b;
|
||||
sink(X(b));
|
||||
X a9(b);
|
||||
a = b;
|
||||
|
||||
test::check_return_type<hasher>::equals(b.hash_function());
|
||||
test::check_return_type<key_equal>::equals(b.key_eq());
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
|
||||
|
||||
a.insert(i, j);
|
||||
test::check_return_type<size_type>::equals(a.erase(k));
|
||||
|
||||
BOOST_TEST(a.empty());
|
||||
if(a.empty()) {
|
||||
a.insert(t);
|
||||
q = a.cbegin();
|
||||
test::check_return_type<iterator>::equals(a.erase(q));
|
||||
}
|
||||
|
||||
const_iterator q1 = a.cbegin(), q2 = a.cend();
|
||||
test::check_return_type<iterator>::equals(a.erase(q1, q2));
|
||||
|
||||
a.clear();
|
||||
|
||||
X const b;
|
||||
|
||||
test::check_return_type<hasher>::equals(b.hash_function());
|
||||
test::check_return_type<key_equal>::equals(b.key_eq());
|
||||
|
||||
test::check_return_type<iterator>::equals(a.find(k));
|
||||
test::check_return_type<const_iterator>::equals(b.find(k));
|
||||
test::check_return_type<size_type>::equals(b.count(k));
|
||||
@@ -398,118 +388,9 @@ void unordered_test(X& x, Key& k, 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);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -16,9 +15,11 @@
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace constructor_tests {
|
||||
|
||||
test::seed_t initialize_seed(356730);
|
||||
test::seed_t seed(356730);
|
||||
|
||||
template <class T>
|
||||
void constructor_tests1(T*,
|
||||
@@ -30,8 +31,6 @@ 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));
|
||||
@@ -42,8 +41,6 @@ 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);
|
||||
@@ -55,8 +52,6 @@ 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);
|
||||
@@ -68,8 +63,6 @@ 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));
|
||||
@@ -80,8 +73,6 @@ 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);
|
||||
@@ -94,8 +85,6 @@ 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);
|
||||
@@ -108,8 +97,6 @@ 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);
|
||||
@@ -122,8 +109,6 @@ 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));
|
||||
@@ -135,8 +120,6 @@ 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));
|
||||
@@ -147,8 +130,6 @@ 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);
|
||||
@@ -161,8 +142,6 @@ 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));
|
||||
@@ -188,7 +167,6 @@ 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));
|
||||
@@ -199,7 +177,6 @@ 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);
|
||||
@@ -211,7 +188,6 @@ 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));
|
||||
@@ -223,7 +199,6 @@ 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);
|
||||
@@ -237,7 +212,6 @@ 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);
|
||||
@@ -249,7 +223,6 @@ 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);
|
||||
@@ -261,7 +234,6 @@ 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);
|
||||
@@ -273,7 +245,6 @@ 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();
|
||||
@@ -291,7 +262,6 @@ void constructor_tests2(T*,
|
||||
|
||||
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);
|
||||
@@ -305,8 +275,6 @@ void constructor_tests2(T*,
|
||||
|
||||
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);
|
||||
@@ -323,8 +291,6 @@ void constructor_tests2(T*,
|
||||
|
||||
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));
|
||||
@@ -334,8 +300,6 @@ 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);
|
||||
@@ -346,8 +310,6 @@ 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);
|
||||
@@ -358,8 +320,6 @@ 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);
|
||||
@@ -370,8 +330,6 @@ 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);
|
||||
@@ -443,7 +401,8 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_initializer_list) {
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
|
||||
@@ -4,19 +4,17 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
test::seed_t initialize_seed(9063);
|
||||
test::seed_t seed(9063);
|
||||
|
||||
namespace copy_tests
|
||||
{
|
||||
@@ -25,15 +23,11 @@ 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());
|
||||
@@ -41,28 +35,20 @@ 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
|
||||
@@ -75,8 +61,6 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -91,12 +75,8 @@ 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());
|
||||
@@ -104,14 +84,10 @@ 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());
|
||||
@@ -119,13 +95,10 @@ 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);
|
||||
@@ -133,14 +106,10 @@ 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);
|
||||
@@ -148,7 +117,6 @@ 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));
|
||||
}
|
||||
}
|
||||
@@ -166,55 +134,15 @@ boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multimap;
|
||||
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::select_copy> >*
|
||||
test_set_select_copy;
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::select_copy> >*
|
||||
test_multiset_select_copy;
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::select_copy> >*
|
||||
test_map_select_copy;
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::select_copy> >*
|
||||
test_multimap_select_copy;
|
||||
|
||||
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)
|
||||
(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_tests1,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(copy_construct_tests2, (
|
||||
(test_set)(test_multiset)(test_map)(test_multimap)
|
||||
(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
|
||||
(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
|
||||
)
|
||||
UNORDERED_TEST(copy_construct_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
|
||||
// Copyright 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#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()
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/preprocessor/seq.hpp>
|
||||
#include <list>
|
||||
#include "../helpers/test.hpp"
|
||||
@@ -137,25 +136,15 @@ namespace equality_tests
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
|
||||
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_predicate_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1), !=, (1001))
|
||||
(1), ==, (1001))
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_multiple_group_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
|
||||
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
|
||||
);
|
||||
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
|
||||
}
|
||||
|
||||
// Test that equality still works when the two containers have
|
||||
@@ -176,6 +165,7 @@ namespace equality_tests
|
||||
set1.insert(20); set2.insert(10);
|
||||
BOOST_TEST(set1 == set2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
// hairy with several tricky edge cases - so explicitly test each one.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/list.hpp"
|
||||
#include <set>
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -21,7 +20,7 @@
|
||||
namespace erase_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(85638);
|
||||
test::seed_t seed(85638);
|
||||
|
||||
template <class Container>
|
||||
void erase_tests1(Container*,
|
||||
@@ -29,8 +28,6 @@ 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
|
||||
@@ -47,8 +44,6 @@ 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();
|
||||
@@ -69,8 +64,6 @@ 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();
|
||||
@@ -103,8 +96,6 @@ 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());
|
||||
|
||||
@@ -127,8 +118,6 @@ 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();
|
||||
@@ -147,8 +136,6 @@ 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();
|
||||
@@ -182,8 +169,6 @@ 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();
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -17,7 +16,7 @@
|
||||
namespace find_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(78937);
|
||||
test::seed_t seed(78937);
|
||||
|
||||
template <class X>
|
||||
void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
@@ -25,8 +24,6 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v(500, generator);
|
||||
X x(v.begin(), v.end());
|
||||
X const& x_const = x;
|
||||
@@ -72,8 +69,6 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v2(5, generator);
|
||||
|
||||
@@ -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_map_fwd.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
template <typename T>
|
||||
void call_swap(boost::unordered_map<T,T>& x,
|
||||
|
||||
@@ -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; };
|
||||
|
||||
@@ -4,11 +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_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace x
|
||||
{
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -21,14 +20,12 @@
|
||||
|
||||
namespace insert_tests {
|
||||
|
||||
test::seed_t initialize_seed(243432);
|
||||
test::seed_t seed(243432);
|
||||
|
||||
template <class X>
|
||||
void unique_insert_tests1(X*,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef test::ordered<X> ordered;
|
||||
|
||||
@@ -68,9 +65,6 @@ 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);
|
||||
|
||||
@@ -108,8 +102,6 @@ void insert_tests2(X*,
|
||||
std::cerr<<"insert(begin(), value) tests.\n";
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
@@ -136,8 +128,6 @@ 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);
|
||||
@@ -165,8 +155,6 @@ 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);
|
||||
@@ -194,8 +182,6 @@ 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);
|
||||
|
||||
@@ -221,8 +207,6 @@ void insert_tests2(X*,
|
||||
std::cerr<<"insert range tests.\n";
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
@@ -235,8 +219,6 @@ 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);
|
||||
@@ -251,8 +233,6 @@ void insert_tests2(X*,
|
||||
std::cerr<<"insert copy iterator range tests.\n";
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
@@ -371,8 +351,6 @@ 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,
|
||||
@@ -393,13 +371,11 @@ 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, test::implicitly_convertible>
|
||||
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, int>
|
||||
> list;
|
||||
test::random_values<
|
||||
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, test::implicitly_convertible>
|
||||
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, int>
|
||||
> v(1000, generator);
|
||||
list l(v.begin(), v.end());
|
||||
|
||||
@@ -466,7 +442,8 @@ UNORDERED_TEST(map_insert_range_test2,
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
{
|
||||
@@ -514,120 +491,6 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
|
||||
|
||||
#endif
|
||||
|
||||
struct overloaded_constructor
|
||||
{
|
||||
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
|
||||
: x1(x1), x2(x2), x3(x3), x4(x4) {}
|
||||
|
||||
int x1, x2, x3, x4;
|
||||
|
||||
bool operator==(overloaded_constructor const& rhs) const
|
||||
{
|
||||
return x1 == rhs.x1 && x2 == rhs.x2 && x3 == rhs.x3 && x4 == rhs.x4;
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(overloaded_constructor const& x)
|
||||
{
|
||||
std::size_t hash = 0;
|
||||
boost::hash_combine(hash, x.x1);
|
||||
boost::hash_combine(hash, x.x2);
|
||||
boost::hash_combine(hash, x.x3);
|
||||
boost::hash_combine(hash, x.x4);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
{
|
||||
boost::unordered_map<int, overloaded_constructor> x;
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(0) != x.end() &&
|
||||
x.find(0)->second == overloaded_constructor());
|
||||
#endif
|
||||
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
|
||||
#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()
|
||||
|
||||
@@ -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>&,
|
||||
|
||||
@@ -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,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/limits.hpp>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -20,7 +19,7 @@
|
||||
namespace load_factor_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(783656);
|
||||
test::seed_t seed(783656);
|
||||
|
||||
template <class X>
|
||||
void set_load_factor_tests(X* = 0)
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
|
||||
// Copyright 2011 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/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_MPL_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >));
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::value_type, T>));
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::pointer, T* >));
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::const_pointer, T const*>));
|
||||
//BOOST_MPL_ASSERT((boost::is_same<typename traits::void_pointer, void* >));
|
||||
//BOOST_MPL_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>));
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>));
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type, std::size_t>));
|
||||
#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();
|
||||
}
|
||||
+12
-226
@@ -4,30 +4,19 @@
|
||||
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace move_tests
|
||||
{
|
||||
test::seed_t initialize_seed(98624);
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#define BOOST_UNORDERED_TEST_MOVING 1
|
||||
#else
|
||||
#define BOOST_UNORDERED_TEST_MOVING 0
|
||||
#endif
|
||||
test::seed_t seed(98624);
|
||||
|
||||
template<class T>
|
||||
T empty(T*) {
|
||||
@@ -65,8 +54,6 @@ 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));
|
||||
@@ -77,8 +64,6 @@ namespace move_tests
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v(1000, generator);
|
||||
test::object_count count;
|
||||
T y(create(v, count));
|
||||
@@ -95,13 +80,11 @@ 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 BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
#endif
|
||||
test::check_container(y, v);
|
||||
@@ -121,8 +104,6 @@ namespace move_tests
|
||||
test::object_count count;
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v(500, generator);
|
||||
T y(create(v, count, hf, eq, al, 0.5));
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
@@ -137,8 +118,6 @@ namespace move_tests
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
// TODO: To do this correctly requires the fancy new allocator
|
||||
// stuff.
|
||||
test::random_values<T> v(500, generator);
|
||||
@@ -151,23 +130,16 @@ namespace move_tests
|
||||
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v(25, generator);
|
||||
T y(create(v, count, hf, eq, al, 1.0), al);
|
||||
#if !defined(BOOST_NO_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_map<T>::value ? 50 : 25));
|
||||
BOOST_TEST(count.instances == test::global_object_count.instances);
|
||||
#else
|
||||
BOOST_TEST(
|
||||
test::global_object_count.constructions - count.constructions <=
|
||||
(test::is_map<T>::value ? 100 : 50));
|
||||
(test::is_map<T>::value ? 50 : 25));
|
||||
BOOST_TEST(count.instances == test::global_object_count.instances);
|
||||
#endif
|
||||
test::check_container(y, v);
|
||||
@@ -177,144 +149,7 @@ 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_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
@@ -329,68 +164,19 @@ namespace move_tests
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multimap;
|
||||
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_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)
|
||||
(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_tests1,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
)
|
||||
UNORDERED_TEST(move_assign_tests1, (
|
||||
(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_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)
|
||||
)
|
||||
UNORDERED_TEST(move_construct_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
((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()
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
@@ -15,7 +14,7 @@
|
||||
namespace rehash_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(2974);
|
||||
test::seed_t seed(2974);
|
||||
|
||||
template <class X>
|
||||
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
|
||||
@@ -100,75 +99,6 @@ 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;
|
||||
@@ -186,12 +116,6 @@ 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))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
// This test checks the runtime requirements of containers.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
+33
-109
@@ -4,28 +4,22 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace swap_tests
|
||||
{
|
||||
|
||||
test::seed_t initialize_seed(783472);
|
||||
test::seed_t seed(783472);
|
||||
|
||||
template <class X>
|
||||
void swap_test_impl(X& x1, X& x2)
|
||||
@@ -43,22 +37,16 @@ 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);
|
||||
@@ -66,8 +54,6 @@ 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);
|
||||
@@ -86,16 +72,12 @@ 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));
|
||||
@@ -103,8 +85,6 @@ 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));
|
||||
@@ -112,113 +92,57 @@ 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));
|
||||
|
||||
if (allocator_type::is_propagate_on_swap ||
|
||||
x.get_allocator() == y.get_allocator())
|
||||
{
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
|
||||
{
|
||||
test::force_equal_allocator force_(
|
||||
!allocator_type::is_propagate_on_swap);
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> vx(100, generator), vy(100, generator);
|
||||
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1),
|
||||
allocator_type(1));
|
||||
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
|
||||
allocator_type(2));
|
||||
|
||||
if (allocator_type::is_propagate_on_swap ||
|
||||
x.get_allocator() == y.get_allocator())
|
||||
{
|
||||
swap_test_impl(x, y);
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
swap_test_impl(x, y);
|
||||
swap_test_impl(x, y);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_set;
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multiset;
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multiset;
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_map;
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_map;
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multimap;
|
||||
test::hash, test::equal_to,
|
||||
test::allocator<test::object> >* test_multimap;
|
||||
|
||||
boost::unordered_set<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_set_prop_swap;
|
||||
boost::unordered_multiset<test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_multiset_prop_swap;
|
||||
boost::unordered_map<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_map_prop_swap;
|
||||
boost::unordered_multimap<test::object, test::object,
|
||||
test::hash, test::equal_to,
|
||||
test::cxx11_allocator<test::object, test::propagate_swap> >*
|
||||
test_multimap_prop_swap;
|
||||
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::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_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)
|
||||
))
|
||||
UNORDERED_TEST(swap_tests2,
|
||||
((test_set)(test_multiset)(test_map)(test_multimap))
|
||||
)
|
||||
|
||||
}
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -4,37 +4,15 @@
|
||||
// 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"
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
|
||||
# elif defined(_LIBCPP_VERSION)
|
||||
# define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
|
||||
# define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
# endif
|
||||
# elif defined(__STL_CONFIG_H)
|
||||
# elif defined(__MSL_CPP__)
|
||||
# elif defined(__IBMCPP__)
|
||||
# elif defined(MSIPL_COMPILE_H)
|
||||
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
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; }
|
||||
@@ -53,25 +31,14 @@ namespace unnecessary_copy_tests
|
||||
: tag_(x.tag_) { ++copies; }
|
||||
|
||||
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
|
||||
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_) {
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
count_copies(count_copies&& x) : tag_(x.tag_) {
|
||||
x.tag_ = -1; ++moves;
|
||||
}
|
||||
|
||||
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_;
|
||||
#endif
|
||||
int tag_;
|
||||
private:
|
||||
count_copies& operator=(count_copies const&);
|
||||
};
|
||||
|
||||
bool operator==(count_copies const& x, count_copies const& y) {
|
||||
@@ -101,37 +68,31 @@ namespace unnecessary_copy_tests
|
||||
}
|
||||
|
||||
#define COPY_COUNT(n) \
|
||||
if(::unnecessary_copy_tests::count_copies::copies != n) { \
|
||||
if(count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< "Number of copies: " << count_copies::copies \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT(n) \
|
||||
if(::unnecessary_copy_tests::count_copies::moves != n) { \
|
||||
if(count_copies::moves != n) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< "Number of moves: " << count_copies::moves \
|
||||
<< " expecting: " <<n << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_RANGE(a, b) \
|
||||
if(::unnecessary_copy_tests::count_copies::copies < a || \
|
||||
::unnecessary_copy_tests::count_copies::copies > b) { \
|
||||
if(count_copies::copies < a || count_copies::copies > b) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< "Number of copies: " << count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT_RANGE(a, b) \
|
||||
if(::unnecessary_copy_tests::count_copies::moves < a || \
|
||||
::unnecessary_copy_tests::count_copies::moves > b) { \
|
||||
if(count_copies::moves < a || count_copies::moves > b) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< "Number of moves: " << count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
|
||||
@@ -175,7 +136,7 @@ namespace unnecessary_copy_tests
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
COPY_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT(2);
|
||||
@@ -187,7 +148,7 @@ namespace unnecessary_copy_tests
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_move_test(T*)
|
||||
{
|
||||
@@ -201,52 +162,11 @@ 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;
|
||||
@@ -257,18 +177,11 @@ namespace unnecessary_copy_tests
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#else
|
||||
COPY_COUNT(1); MOVE_COUNT(1 + source_cost);
|
||||
#endif
|
||||
#endif
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
//
|
||||
// 1 argument
|
||||
@@ -284,9 +197,9 @@ namespace unnecessary_copy_tests
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(std::move(a));
|
||||
@@ -320,19 +233,6 @@ 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.
|
||||
@@ -344,19 +244,10 @@ 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
|
||||
@@ -370,92 +261,45 @@ namespace unnecessary_copy_tests
|
||||
// copied.
|
||||
reset();
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || \
|
||||
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
|
||||
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
x.emplace(a_ref);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
// TODO: This doesn't work on older versions of gcc.
|
||||
//count_copies part;
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
//reset();
|
||||
//std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
//x.emplace(a_ref);
|
||||
//COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#if !defined(BOOST_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
|
||||
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
|
||||
std::pair<count_copies const, count_copies> b;
|
||||
|
||||
reset();
|
||||
x.emplace(b.first, b.second);
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(source<count_copies>(), source<count_copies>());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_cost * 2);
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
// source<count_copies> creates a single copy.
|
||||
reset();
|
||||
x.emplace(b.first, source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(boost::ref(b.first)),
|
||||
boost::make_tuple(boost::ref(b.second)));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#if !defined(BOOST_NO_0X_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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user