Unordered: Merge from trunk

- Remove use of BOOST_DEDUCED_TYPENAME and BOOST_UNORDERED_PAIR_CAST, it's
  unlikely that the compilers which require them will be able to cope with the
  new version of unordered.
- Use the old equality algorithm if BOOST_UNORDERED_DEPRECATED_EQUALITY is
  defined.
- Use SFINAE to control which overloads of `construct_impl` are available.
  Fixes problems with differing overload resolution on different compilers.
- Support for piecewise pair construction.
- Only support the old variadic pair construction when
  BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT is defined (also fixed some bugs).
- Avoid instantiating BOOST_RV_REF for non-classes.
- Support optional allocator member functions for compilers with SFINAE
  expressions and Visual C++ 9.0/10.0
- Follow boost macro naming conventions.
- Improved portability for `allocator_traits` emulation.

Current compiler support:

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


[SVN r74234]
This commit is contained in:
Daniel James
2011-09-04 19:37:45 +00:00
parent f6f19aaaaa
commit 5867994b8c
27 changed files with 1465 additions and 719 deletions

View File

@ -112,7 +112,7 @@ load factor is /required/ to be less than the maximum is following a call to
below the max load factor, and set the maximum load factor to be the same as
or close to the hint - unless your hint is unreasonably small or large.
[table Methods for Controlling Bucket Size
[table:bucket_size Methods for Controlling Bucket Size
[[Method] [Description]]
[

View File

@ -151,4 +151,7 @@ in some breaking changes:
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.
[endsect]

View File

@ -4,7 +4,7 @@
[section:comparison Comparison with Associative Containers]
[table Interface differences.
[table:interface_differences Interface differences.
[[Associative Containers] [Unordered Associative Containers]]
[
@ -88,7 +88,7 @@
]
]
[table Complexity Guarantees
[table:complexity_guarantees Complexity Guarantees
[[Operation] [Associative Containers] [Unordered Associative Containers]]
[
[Construction of empty container]

View File

@ -4,25 +4,42 @@
[section:compliance C++11 Compliance]
/TODO/: Look into C++11's `std::pair`.
[section:allocator_compliance Use of allocators]
* Objects are not constructed using the allocator. The node containing them
is constructed using the allocator's `construct` function, but then the
object is constructed in a buffer in that node by calling the constructor
directly.
* Similarly the object is destructed by calling its destructor directly, and
then the allocator's `destroy` method is used to destruct the node.
* For most compilers `select_on_container_copy` is only detected for an
exact signature match in the allocator itself - not in a base. There is full
detection for g++ 4.4 or laster, Visual C++ 2008 or later, Clang and maybe
other compilers which support SFINAE for expressions.
* `pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators.
* /TODO/: Any other defficiences of `allocator_traits` emulation.
* Pointers of base types are used to store the location of a derived type.
(/TODO/: I'm not sure if that isn't compliant).
C++11 introduced a new, mostly backwards compatible, allocator system.
This uses a traits class, `allocator_traits` to handle the allocator
adding extra functionality, and making some methods and types optional.
At the time of writing there isn't a stable release of a standard library
with `allocator_traits` (libc++ has `allocator_traits` but it hasn't been
released yet) so a partial implementation is always used.
A full implementation of `allocator_traits` requires sophisticated
member function detection which requires support for SFINAE expressions,
or something close. This is available on GCC from version 4.4, Clang and
Visual C++ 2008 (with a little hacking) or later.
On these compilers, the `construct`, `destroy` and `max_size` member functions
are optional, as per C++11. On other compilers they are still required.
`propagate_on_container_copy_assignment`,
`propagate_on_container_move_assignment` and
`propagate_on_container_swap` are supported on most compilers
(/TODO/: which ones don't support them?).
`select_on_container_copy_construction` is also supported, but on
compilers without full member function detection it must have exactly
the right function signature, and can't be declared in a base class
in order for it to be detected.
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 objects
contained in the node are stored in aligned space within the node
and constructed and destructed by calling the constructor and destructor
directly. So `construct` and `destroy` are called for the node, but not for
the object.
`pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators.
[endsect]
@ -35,19 +52,43 @@ use Boost.Move.
* Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable.
* The number of arguments used in emplace is limited to /TODO/.
* The number of arguments used in `emplace` is limited to /TODO/.
* Argument forwarding is not perfect.
* /TODO/: Constructor call for pairs.
[endsect]
[section:other Other]
[section:pairs Pairs]
* 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.
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.
For the same example:
x.emplace("key", 1, 2);
This is emulated in Boost.Unordered, but will be deprecated soon.
While it is a lot more compact, it lead to ambiguities so it was
removed.
[endsect]
[section:swap Swapping]
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.
[endsect]

View File

@ -67,9 +67,10 @@ so that the hash function doesn't need to be explicitly given:
See the [link hash.custom Boost.Hash documentation] for more detail on how to
do this. Remember that it relies on extensions to the draft standard - so it
won't work on other implementations of the unordered associative containers.
won't work for other implementations of the unordered associative containers,
you'll need to explicitly use Boost.Hash.
[table Methods for accessing the hash and equality functions.
[table:access_methods Methods for accessing the hash and equality functions.
[[Method] [Description]]
[

View File

@ -2,15 +2,6 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[def __tr1__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
C++ Standard Library Technical Report]]
[def __boost-tr1__
[@http://www.boost.org/doc/html/boost_tr1.html
Boost.TR1]]
[def __draft__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
Working Draft of the C++ Standard]]
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
hash table]]
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function
@ -31,12 +22,10 @@ to order their elements. For some data types this is impossible to implement
or isn't practical. In contrast, a hash table only needs an equality function
and a hash function for the key.
With this in mind, the __tr1__ introduced the unordered associative containers,
which are implemented using hash tables, and they have now been added to the
__draft__.
This library supplies an almost complete implementation of the specification in
the __draft__.
With this in mind, unordered associative containers were added to the C++
standard. This is an implementation of the containers described in C++11,
with some [link unordered.compliance deviations from the standard] in
order to work with non-C++11 compilers and libraries.
`unordered_set` and `unordered_multiset` are defined in the header
<[headerref boost/unordered_set.hpp]>

View File

@ -92,6 +92,8 @@ So, this implementation uses a prime number for the hash table size.
[h2 Equality operators]
/TODO/: This is out of date.
`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
@ -115,6 +117,8 @@ that their order can be considered part of the container's value.
[h3 C++0x allocators]
/TODO/: This is out of date.
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]
@ -124,6 +128,8 @@ a little to accomodate non-C++0x compilers.
[h3 Swapping containers with unequal allocators]
/TODO/: This is out of date.
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-defects.html#431

View File

@ -60,10 +60,6 @@ EOL;
</simpara></purpose>
<description>
<para>Based on chapter 23 of
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
But without the updated rules for allocators.
</para>
<para><emphasis role="bold">Template Parameters</emphasis>
<informaltable>
<tgroup cols="2">
@ -236,6 +232,9 @@ EOL;
</parameter>
<description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
<para>If <code>Allocator::select_on_container_copy_construction</code>
exists and has the right signature, the allocator will be
constructed from its result.</para>
</description>
<requires>
<para><code>value_type</code> is copy constructible</para>
@ -249,12 +248,18 @@ EOL;
<para>The move constructor.</para>
</description>
<notes>
<para>This is emulated on compilers without rvalue references.</para>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
<para>
On compilers without rvalue reference support the
emulation does not support moving without calling
<code>boost::move</code> if <code>value_type</code> is
not copyable. So, for example, you can't return the
container from a function.
</para>
</requires>
</constructor>
@ -289,14 +294,12 @@ EOL;
<type><?php echo $name; ?>&amp;</type>
<description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
<para>If <code>Alloc::propagate_on_container_copy_assignment</code>
exists and <code>Alloc::propagate_on_container_copy_assignment::value
</code> is true, the allocator is overwritten, if not the
copied elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(<?php echo $name; ?>)</code>
in order to emulate move semantics.
</para>
</notes>
<requires>
<para><code>value_type</code> is copy constructible</para>
</requires>
@ -308,18 +311,21 @@ EOL;
<type><?php echo $name; ?>&amp;</type>
<description>
<para>The move assignment operator.</para>
<para>If <code>Alloc::propagate_on_container_move_assignment</code>
exists and <code>Alloc::propagate_on_container_move_assignment::value
</code> is true, the allocator is overwritten, if not the
moved elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(<?php echo $name; ?>)</code>
in order to emulate move semantics.
On compilers without rvalue references, this is emulated using
Boost.Move.
</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
</requires>
</method>
@ -406,6 +412,10 @@ EOL;
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="emplace_hint">
@ -444,6 +454,10 @@ EOL;
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="insert">
@ -541,15 +555,13 @@ EOL;
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
<para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
</throws>
<notes>
<para>
When the number of elements is a lot smaller than the number of buckets
this function can be very inefficient as it has to search through empty
buckets for the next element, in order to return the iterator.
The method <methodname>quick_erase</methodname> is faster, but has yet
to be standardized.
In older versions this could be inefficient because it had to search
through several buckets to find the position of the returned iterator.
The data structure has been changed so that this is no longer the case,
and the alternative erase methods have been deprecated.
</para>
</notes>
</method>
@ -601,13 +613,10 @@ EOL;
</throws>
<notes>
<para>
This method is faster than <methodname>erase</methodname> as
it doesn't have to find the next element in the container -
a potentially costly operation.
</para>
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -625,10 +634,10 @@ EOL;
</throws>
<notes>
<para>
This method is now deprecated, use
<methodname>quick_return</methodname> instead. Although be
warned that as that isn't standardized yet, it could also
change.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -653,6 +662,7 @@ EOL;
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -952,6 +962,7 @@ EOL;
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -975,6 +986,7 @@ EOL;
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -1006,6 +1018,7 @@ EOL;
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>

View File

@ -23,10 +23,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
An unordered associative container that stores unique values.
</simpara></purpose>
<description>
<para>Based on chapter 23 of
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
But without the updated rules for allocators.
</para>
<para><emphasis role="bold">Template Parameters</emphasis>
<informaltable>
<tgroup cols="2">
@ -181,6 +177,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
<para>If <code>Allocator::select_on_container_copy_construction</code>
exists and has the right signature, the allocator will be
constructed from its result.</para>
</description>
<requires>
<para><code>value_type</code> is copy constructible</para>
@ -194,12 +193,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The move constructor.</para>
</description>
<notes>
<para>This is emulated on compilers without rvalue references.</para>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
<para>
On compilers without rvalue reference support the
emulation does not support moving without calling
<code>boost::move</code> if <code>value_type</code> is
not copyable. So, for example, you can't return the
container from a function.
</para>
</requires>
</constructor>
@ -234,14 +239,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_set&amp;</type>
<description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
<para>If <code>Alloc::propagate_on_container_copy_assignment</code>
exists and <code>Alloc::propagate_on_container_copy_assignment::value
</code> is true, the allocator is overwritten, if not the
copied elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_set)</code>
in order to emulate move semantics.
</para>
</notes>
<requires>
<para><code>value_type</code> is copy constructible</para>
</requires>
@ -253,18 +256,21 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_set&amp;</type>
<description>
<para>The move assignment operator.</para>
<para>If <code>Alloc::propagate_on_container_move_assignment</code>
exists and <code>Alloc::propagate_on_container_move_assignment::value
</code> is true, the allocator is overwritten, if not the
moved elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_set)</code>
in order to emulate move semantics.
On compilers without rvalue references, this is emulated using
Boost.Move.
</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
</requires>
</method>
@ -344,6 +350,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="emplace_hint">
@ -375,6 +385,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="insert">
@ -457,15 +471,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
<para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
</throws>
<notes>
<para>
When the number of elements is a lot smaller than the number of buckets
this function can be very inefficient as it has to search through empty
buckets for the next element, in order to return the iterator.
The method <methodname>quick_erase</methodname> is faster, but has yet
to be standardized.
In older versions this could be inefficient because it had to search
through several buckets to find the position of the returned iterator.
The data structure has been changed so that this is no longer the case,
and the alternative erase methods have been deprecated.
</para>
</notes>
</method>
@ -517,13 +529,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is faster than <methodname>erase</methodname> as
it doesn't have to find the next element in the container -
a potentially costly operation.
</para>
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -541,10 +550,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is now deprecated, use
<methodname>quick_return</methodname> instead. Although be
warned that as that isn't standardized yet, it could also
change.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -569,6 +578,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -832,6 +842,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -856,6 +867,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -888,6 +900,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -912,10 +925,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
An unordered associative container that stores values. The same key can be stored multiple times.
</simpara></purpose>
<description>
<para>Based on chapter 23 of
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
But without the updated rules for allocators.
</para>
<para><emphasis role="bold">Template Parameters</emphasis>
<informaltable>
<tgroup cols="2">
@ -1070,6 +1079,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
<para>If <code>Allocator::select_on_container_copy_construction</code>
exists and has the right signature, the allocator will be
constructed from its result.</para>
</description>
<requires>
<para><code>value_type</code> is copy constructible</para>
@ -1083,12 +1095,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The move constructor.</para>
</description>
<notes>
<para>This is emulated on compilers without rvalue references.</para>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
<para>
On compilers without rvalue reference support the
emulation does not support moving without calling
<code>boost::move</code> if <code>value_type</code> is
not copyable. So, for example, you can't return the
container from a function.
</para>
</requires>
</constructor>
@ -1123,14 +1141,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_multiset&amp;</type>
<description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
<para>If <code>Alloc::propagate_on_container_copy_assignment</code>
exists and <code>Alloc::propagate_on_container_copy_assignment::value
</code> is true, the allocator is overwritten, if not the
copied elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_multiset)</code>
in order to emulate move semantics.
</para>
</notes>
<requires>
<para><code>value_type</code> is copy constructible</para>
</requires>
@ -1142,18 +1158,21 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_multiset&amp;</type>
<description>
<para>The move assignment operator.</para>
<para>If <code>Alloc::propagate_on_container_move_assignment</code>
exists and <code>Alloc::propagate_on_container_move_assignment::value
</code> is true, the allocator is overwritten, if not the
moved elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_multiset)</code>
in order to emulate move semantics.
On compilers without rvalue references, this is emulated using
Boost.Move.
</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
</requires>
</method>
@ -1232,6 +1251,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="emplace_hint">
@ -1263,6 +1286,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="insert">
@ -1344,15 +1371,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
<para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
</throws>
<notes>
<para>
When the number of elements is a lot smaller than the number of buckets
this function can be very inefficient as it has to search through empty
buckets for the next element, in order to return the iterator.
The method <methodname>quick_erase</methodname> is faster, but has yet
to be standardized.
In older versions this could be inefficient because it had to search
through several buckets to find the position of the returned iterator.
The data structure has been changed so that this is no longer the case,
and the alternative erase methods have been deprecated.
</para>
</notes>
</method>
@ -1404,13 +1429,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is faster than <methodname>erase</methodname> as
it doesn't have to find the next element in the container -
a potentially costly operation.
</para>
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -1428,10 +1450,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is now deprecated, use
<methodname>quick_return</methodname> instead. Although be
warned that as that isn't standardized yet, it could also
change.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -1456,6 +1478,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -1719,6 +1742,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -1743,6 +1767,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -1775,6 +1800,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -1805,10 +1831,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
An unordered associative container that associates unique keys with another value.
</simpara></purpose>
<description>
<para>Based on chapter 23 of
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
But without the updated rules for allocators.
</para>
<para><emphasis role="bold">Template Parameters</emphasis>
<informaltable>
<tgroup cols="2">
@ -1969,6 +1991,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
<para>If <code>Allocator::select_on_container_copy_construction</code>
exists and has the right signature, the allocator will be
constructed from its result.</para>
</description>
<requires>
<para><code>value_type</code> is copy constructible</para>
@ -1982,12 +2007,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The move constructor.</para>
</description>
<notes>
<para>This is emulated on compilers without rvalue references.</para>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
<para>
On compilers without rvalue reference support the
emulation does not support moving without calling
<code>boost::move</code> if <code>value_type</code> is
not copyable. So, for example, you can't return the
container from a function.
</para>
</requires>
</constructor>
@ -2022,14 +2053,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_map&amp;</type>
<description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
<para>If <code>Alloc::propagate_on_container_copy_assignment</code>
exists and <code>Alloc::propagate_on_container_copy_assignment::value
</code> is true, the allocator is overwritten, if not the
copied elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_map)</code>
in order to emulate move semantics.
</para>
</notes>
<requires>
<para><code>value_type</code> is copy constructible</para>
</requires>
@ -2041,18 +2070,21 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_map&amp;</type>
<description>
<para>The move assignment operator.</para>
<para>If <code>Alloc::propagate_on_container_move_assignment</code>
exists and <code>Alloc::propagate_on_container_move_assignment::value
</code> is true, the allocator is overwritten, if not the
moved elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_map)</code>
in order to emulate move semantics.
On compilers without rvalue references, this is emulated using
Boost.Move.
</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
</requires>
</method>
@ -2132,6 +2164,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="emplace_hint">
@ -2163,6 +2199,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="insert">
@ -2245,15 +2285,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
<para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
</throws>
<notes>
<para>
When the number of elements is a lot smaller than the number of buckets
this function can be very inefficient as it has to search through empty
buckets for the next element, in order to return the iterator.
The method <methodname>quick_erase</methodname> is faster, but has yet
to be standardized.
In older versions this could be inefficient because it had to search
through several buckets to find the position of the returned iterator.
The data structure has been changed so that this is no longer the case,
and the alternative erase methods have been deprecated.
</para>
</notes>
</method>
@ -2305,13 +2343,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is faster than <methodname>erase</methodname> as
it doesn't have to find the next element in the container -
a potentially costly operation.
</para>
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -2329,10 +2364,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is now deprecated, use
<methodname>quick_return</methodname> instead. Although be
warned that as that isn't standardized yet, it could also
change.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -2357,6 +2392,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -2657,6 +2693,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -2683,6 +2720,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -2717,6 +2755,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -2743,10 +2782,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
An unordered associative container that associates keys with another value. The same key can be stored multiple times.
</simpara></purpose>
<description>
<para>Based on chapter 23 of
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
But without the updated rules for allocators.
</para>
<para><emphasis role="bold">Template Parameters</emphasis>
<informaltable>
<tgroup cols="2">
@ -2907,6 +2942,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
<para>If <code>Allocator::select_on_container_copy_construction</code>
exists and has the right signature, the allocator will be
constructed from its result.</para>
</description>
<requires>
<para><code>value_type</code> is copy constructible</para>
@ -2920,12 +2958,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The move constructor.</para>
</description>
<notes>
<para>This is emulated on compilers without rvalue references.</para>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
<para>
On compilers without rvalue reference support the
emulation does not support moving without calling
<code>boost::move</code> if <code>value_type</code> is
not copyable. So, for example, you can't return the
container from a function.
</para>
</requires>
</constructor>
@ -2960,14 +3004,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_multimap&amp;</type>
<description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
<para>If <code>Alloc::propagate_on_container_copy_assignment</code>
exists and <code>Alloc::propagate_on_container_copy_assignment::value
</code> is true, the allocator is overwritten, if not the
copied elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_multimap)</code>
in order to emulate move semantics.
</para>
</notes>
<requires>
<para><code>value_type</code> is copy constructible</para>
</requires>
@ -2979,18 +3021,21 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>unordered_multimap&amp;</type>
<description>
<para>The move assignment operator.</para>
<para>If <code>Alloc::propagate_on_container_move_assignment</code>
exists and <code>Alloc::propagate_on_container_move_assignment::value
</code> is true, the allocator is overwritten, if not the
moved elements are created using the existing
allocator.</para>
</description>
<notes>
<para>
On compilers without rvalue references, there is a single assignment
operator with the signature <code>operator=(unordered_multimap)</code>
in order to emulate move semantics.
On compilers without rvalue references, this is emulated using
Boost.Move.
</para>
</notes>
<requires>
<para>
<code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para>
</requires>
</method>
@ -3069,6 +3114,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="emplace_hint">
@ -3100,6 +3149,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para>
<para>Since existing `std::pair` implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.
</para>
</notes>
</method>
<method name="insert">
@ -3181,15 +3234,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns>
<throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
<para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
</throws>
<notes>
<para>
When the number of elements is a lot smaller than the number of buckets
this function can be very inefficient as it has to search through empty
buckets for the next element, in order to return the iterator.
The method <methodname>quick_erase</methodname> is faster, but has yet
to be standardized.
In older versions this could be inefficient because it had to search
through several buckets to find the position of the returned iterator.
The data structure has been changed so that this is no longer the case,
and the alternative erase methods have been deprecated.
</para>
</notes>
</method>
@ -3241,13 +3292,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is faster than <methodname>erase</methodname> as
it doesn't have to find the next element in the container -
a potentially costly operation.
</para>
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -3265,10 +3313,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws>
<notes>
<para>
This method is now deprecated, use
<methodname>quick_return</methodname> instead. Although be
warned that as that isn't standardized yet, it could also
change.
This method was implemented because returning an iterator to
the next element from <code>erase</code> was expensive, but
the container has been redesigned so that is no longer the
case. So this method is now deprecated.
</para>
</notes>
</method>
@ -3293,6 +3341,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>
@ -3558,6 +3607,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -3584,6 +3634,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter>
<type>bool</type>
<notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
@ -3618,6 +3669,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
</throws>
<notes>
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
<para>For a discussion of the behavior when allocators aren't equal see
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes>

View File

@ -3,7 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[library Boost.Unordered
[quickbook 1.4]
[quickbook 1.5]
[authors [James, Daniel]]
[copyright 2003 2004 Jeremy B. Maitin-Shepard]
[copyright 2005 2006 2007 2008 Daniel James]

View File

@ -19,6 +19,8 @@
#include <boost/detail/select_type.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__)
@ -76,13 +78,12 @@ namespace boost { namespace unordered { namespace detail {
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
# endif
template <typename T> T& make();
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]; };
@ -94,13 +95,14 @@ namespace boost { namespace unordered { namespace detail {
struct choice1 : choice2 { typedef char (&type)[1]; };
choice1 choose();
#define BOOST_DEFAULT_TYPE_TMPLT(tname) \
#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, \
BOOST_DEDUCED_TYPENAME X::tname* = 0); \
static choice1::type test(choice1, typename X::tname* = 0); \
\
template <typename X> \
static choice2::type test(choice2, void* = 0); \
@ -109,24 +111,50 @@ namespace boost { namespace unordered { namespace detail {
\
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\
typedef BOOST_DEDUCED_TYPENAME \
boost::detail::if_true<value>:: \
typedef typename boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#define BOOST_DEFAULT_TYPE(T,tname, arg) \
BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
#else
BOOST_DEFAULT_TYPE_TMPLT(pointer);
BOOST_DEFAULT_TYPE_TMPLT(const_pointer);
BOOST_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_DEFAULT_TYPE_TMPLT(const_void_pointer);
BOOST_DEFAULT_TYPE_TMPLT(difference_type);
BOOST_DEFAULT_TYPE_TMPLT(size_type);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
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 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) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
@ -146,14 +174,40 @@ namespace boost { namespace unordered { namespace detail {
static BOOST_PP_CAT(choice, result)::type test( \
BOOST_PP_CAT(choice, count))
#define BOOST_UNORDERED_HAS_EXPRESSION(name, expression) \
struct BOOST_PP_CAT(has_, name) \
{ \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, expression); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
\
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
}
template <typename T>
struct has_select_on_container_copy_construction
{
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, make<U const>().select_on_container_copy_construction());
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2);
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
};
BOOST_UNORDERED_HAS_EXPRESSION(
select_on_container_copy_construction,
make<U const>().select_on_container_copy_construction()
);
// Only supporting the basic copy constructor for now.
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_EXPRESSION(
construct,
make<U>().construct(make<ValueType*>(), make<ValueType const>())
);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_EXPRESSION(
destroy,
make<U>().destroy(make<ValueType*>())
);
template <typename T>
BOOST_UNORDERED_HAS_EXPRESSION(
max_size,
make<U const>().max_size()
);
#else
@ -165,32 +219,43 @@ namespace boost { namespace unordered { namespace detail {
\
template <BOOST_PP_CAT(check, count) e> \
struct BOOST_PP_CAT(test, count) { \
typedef void* type; \
typedef BOOST_PP_CAT(choice, result) type; \
}; \
\
template <class U> static BOOST_PP_CAT(choice, result)::type \
test(BOOST_PP_CAT(choice, count), \
typename BOOST_PP_CAT(test, count)< \
&U::name>::type = 0)
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), void* = 0)
test(BOOST_PP_CAT(choice, count))
template <typename T>
struct has_select_on_container_copy_construction
{
BOOST_UNORDERED_CHECK_MEMBER(1, 1, select_on_container_copy_construction, T (T::*)() const);
BOOST_UNORDERED_CHECK_MEMBER(1, 1,
select_on_container_copy_construction,
T (T::*)() const);
BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
};
// Detection isn't reliable enough, so just assume that we have these
// functions.
template <typename Alloc, typename value_type>
struct has_construct : true_type {};
template <typename Alloc, typename value_type>
struct has_destroy : true_type {};
template <typename Alloc>
struct has_max_size : true_type {};
#endif
template <typename Alloc>
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
inline typename boost::enable_if<
has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
@ -198,48 +263,62 @@ namespace boost { namespace unordered { namespace detail {
}
template <typename Alloc>
inline BOOST_DEDUCED_TYPENAME boost::disable_if<
inline typename boost::disable_if<
has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs;
}
template <typename SizeType, typename Alloc>
SizeType call_max_size(const Alloc& a,
typename boost::enable_if<has_max_size<Alloc>, void*>::type = 0)
{
return a.max_size();
}
template <typename SizeType, typename Alloc>
SizeType call_max_size(const Alloc&,
typename boost::disable_if<has_max_size<Alloc>, void*>::type = 0)
{
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_DEFAULT_TYPE(Alloc, pointer, value_type*)
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
pointer;
// For now always use the allocator's const_pointer.
//typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
// typename pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
// const_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, value_type const*)
const_pointer;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
value_type const*) const_pointer;
// I'm not using void pointers for now.
//typedef BOOST_DEFAULT_TYPE(Alloc, void_pointer,
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
// BOOST_NESTED_TEMPLATE pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<void>::other)
// void_pointer;
//typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
// typename pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const void>::other)
// const_void_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, difference_type, std::ptrdiff_t)
difference_type;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
std::ptrdiff_t) difference_type;
typedef BOOST_DEFAULT_TYPE(Alloc, size_type, std::size_t)
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
// TODO: rebind_alloc and rebind_traits
@ -249,32 +328,49 @@ namespace boost { namespace unordered { namespace detail {
// 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)
//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); }
// Only support the basic copy constructor
public:
// template <typename T, typename... Args>
// static void construct(Alloc& a, T* p, Args&&... args) {
// DEFAULT_FUNC(construct,void)(a, p, std::forward<Args>(args)...);
// }
// Only supporting the basic copy constructor for now.
template <typename T>
static void construct(Alloc& a, T* p, T const& x) {
static void construct(Alloc& a, T* p, T const& x, typename
boost::enable_if<has_construct<Alloc, T>, void*>::type = 0)
{
a.construct(p, x);
}
template <typename T>
static void destroy(Alloc& a, T* p) {
// DEFAULT_FUNC(destroy,void)(a, p);
static void construct(Alloc&, T* p, T const& x, typename
boost::disable_if<has_construct<Alloc, T>, void*>::type = 0)
{
new ((void*) p) T(x);
}
template <typename T>
static void destroy(Alloc& a, T* p, typename
boost::enable_if<has_destroy<Alloc, T>, void*>::type = 0)
{
a.destroy(p);
}
template <typename T>
static void destroy(Alloc&, T* p, typename
boost::disable_if<has_destroy<Alloc, T>, void*>::type = 0)
{
p->~T();
}
static size_type max_size(const Alloc& a)
{ return a.max_size(); }
{
return boost::unordered::detail::call_max_size<size_type>(a);
}
// Allocator propagation on construction
@ -286,13 +382,13 @@ namespace boost { namespace unordered { namespace detail {
// Allocator propagation on assignment and swap.
// Return true if lhs is modified.
typedef BOOST_DEFAULT_TYPE(
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc, propagate_on_container_copy_assignment, false_type)
propagate_on_container_copy_assignment;
typedef BOOST_DEFAULT_TYPE(
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_move_assignment, false_type)
propagate_on_container_move_assignment;
typedef BOOST_DEFAULT_TYPE(
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
@ -307,7 +403,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename Allocator>
struct allocator_array_constructor
{
typedef BOOST_DEDUCED_TYPENAME allocator_traits<Allocator>::pointer
typedef typename allocator_traits<Allocator>::pointer
pointer;
Allocator& alloc_;

View File

@ -41,7 +41,7 @@ namespace boost { namespace unordered { namespace detail {
public:
// Types
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::if_true<Unique>::
typedef typename ::boost::detail::if_true<Unique>::
BOOST_NESTED_TEMPLATE then<
::boost::unordered::detail::ungrouped_node<A>,
::boost::unordered::detail::grouped_node<A>
@ -49,16 +49,15 @@ namespace boost { namespace unordered { namespace detail {
typedef A value_allocator;
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
typedef typename allocator_traits<A>::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef typename bucket::bucket_allocator bucket_allocator;
typedef typename allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef typename bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
typedef typename rebind_wrap<value_allocator, node>::type
node_allocator;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<node_allocator>::pointer real_node_ptr;
typedef typename allocator_traits<node_allocator>::pointer real_node_ptr;
// Members
@ -423,7 +422,7 @@ namespace boost { namespace unordered { namespace detail {
functions& operator=(functions const&);
typedef compressed_pair<H, P> function_pair;
typedef BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
typedef typename ::boost::aligned_storage<
sizeof(function_pair),
::boost::alignment_of<function_pair>::value>::type aligned_function;
@ -515,28 +514,130 @@ namespace boost { namespace unordered { namespace detail {
};
////////////////////////////////////////////////////////////////////////////
// Node Constructors
//
// Value Construction
template <typename T, typename Arg1 = void>
struct emulated_pair_constructor
{
enum { value = false };
};
template <typename A, typename B>
struct emulated_pair_constructor<std::pair<A, B>, void>
{
enum { value = true };
};
template <typename A, typename B, typename Value>
struct emulated_pair_constructor<std::pair<A, B>, Value>
{
#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_TRAILING_PARAMS_Z(z, n, typename Arg)>\
void construct_from_tuple(T* ptr, \
namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, Arg)> 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)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
#elif defined(BOOST_HAS_TR1_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1)
#endif
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename Arg1>
struct emulation1 {
static choice1::type check(choice1, std::pair<A, B> const&);
static choice2::type check(choice2, A const&);
enum { value = sizeof(check(choose(), make<Value>())) - 1 };
enum { value = sizeof(check(choose(), make<Arg1>())) == sizeof(choice2::type) };
};
#endif
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename Arg1>
struct check3_base {
static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
static choice2::type check(choice2, A const&);
static choice3::type check(choice3, ...);
};
#else
template <typename A, typename B, typename Arg1>
struct check3_base {
static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
static choice3::type check(choice3, ...);
};
#endif
template <typename A, typename B, typename Arg1>
struct piecewise3 {
enum { value =
sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
sizeof(choice1::type) };
};
template <typename A, typename B, typename Arg1>
struct emulation3 {
enum { value =
sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
sizeof(choice2::type) };
};
template <typename A, typename B, typename Arg1>
struct normal3 {
enum { value =
sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
sizeof(choice3::type) };
};
template <typename T, typename Arg1>
struct pair_construct1 {};
template <typename T, typename Arg1>
struct normal_construct1 { typedef void type; };
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename Arg1>
struct pair_construct1<std::pair<A, B>, Arg1>
: enable_if<emulation1<A, B, Arg1>, void> {};
template <typename A, typename B, typename Arg1>
struct normal_construct1<std::pair<A, B>, Arg1>
: disable_if<emulation1<A, B, Arg1>, void> {};
#endif
template <typename T, typename Arg1>
struct piecewise_construct3 {};
template <typename A, typename B, typename Arg1>
struct piecewise_construct3<std::pair<A, B>, Arg1>
: enable_if<piecewise3<A, B, Arg1>, void> {};
template <typename T, typename Arg1>
struct pair_construct3 {};
template <typename A, typename B, typename Arg1>
struct pair_construct3<std::pair<A, B>, Arg1>
: enable_if<emulation3<A, B, Arg1>, void> {};
template <typename T, typename Arg1>
struct normal_construct3 { typedef void type; };
template <typename A, typename B, typename Arg1>
struct normal_construct3<std::pair<A, B>, Arg1>
: enable_if<normal3<A, B, Arg1>, void> {};
template <typename T>
struct pair_construct_n {};
template <typename T>
struct normal_construct_n { typedef void type; };
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B>
struct pair_construct_n<std::pair<A, B> > { typedef void type; };
template <typename A, typename B>
struct normal_construct_n<std::pair<A, B> > {};
#endif
template <class T>
inline void construct_impl(void* address)
@ -544,110 +645,135 @@ namespace boost { namespace unordered { namespace detail {
new(address) T();
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class T, class Arg1>
inline void construct_impl(
typename boost::disable_if<emulated_pair_constructor<T, Arg1>,
void*>::type address,
Arg1&& a1)
inline typename normal_construct1<T, Arg1>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
{
new(address) T(std::forward<Arg1>(a1));
new(address) T(
boost::forward<Arg1>(arg1)
);
}
template <class T, class Arg1>
inline void construct_impl(
typename boost::enable_if<emulated_pair_constructor<T, Arg1>,
void*>::type address,
Arg1&& a1)
inline typename pair_construct1<T, Arg1>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
{
new(address) T(std::forward<Arg1>(a1), typename T::second_type());
}
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<Arg1>(arg1));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type();
}
template <class T, class Arg1, class Arg2>
inline void construct_impl(void* address, Arg1&& a1, Arg2&& a2)
inline void construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
BOOST_FWD_REF(Arg2) arg2)
{
new(address) T(std::forward<Arg1>(a1), std::forward<Arg2>(a2));
new(address) T(
boost::forward<Arg1>(arg1),
boost::forward<Arg2>(arg2));
}
template <class T, class Arg1, class Arg2, class... Args>
inline typename boost::disable_if<emulated_pair_constructor<T>, void>::type
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
template <class T, class Arg1, class Arg2, class Arg3>
inline typename piecewise_construct3<T, Arg1>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1),
BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
{
new(address) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
construct_from_tuple(&static_cast<T*>(address)->first, arg2);
construct_from_tuple(&static_cast<T*>(address)->second, arg3);
}
template <class T, class Arg1, class Arg2, class Arg3>
inline typename pair_construct3<T, Arg1>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<Arg1>(arg1));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type(
boost::forward<Arg2>(arg2),
boost::forward<Arg3>(arg3));
}
template <class T, class Arg1, class Arg2, class Arg3>
inline typename normal_construct3<T, Arg1>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
{
new(address) T(
boost::forward<Arg1>(arg1),
boost::forward<Arg2>(arg2),
boost::forward<Arg3>(arg3));
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class... Args>
inline typename normal_construct_n<T>::type
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3,
Arg4&& arg4, Args&&... args)
{
new(address) T(
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4),
std::forward<Args>(args)...);
}
template <class T, class Arg1, class Arg2, class... Args>
inline typename boost::enable_if<emulated_pair_constructor<T>, void>::type
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class... Args>
inline typename pair_construct_n<T>::type
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3,
Arg4&& arg4, Args&&... args)
{
new(address) T(std::forward<Arg1>(arg1),
typename T::second_type(
std::forward<Arg2>(arg2), std::forward<Args>(args)...));
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
std::forward<Arg1>(arg1));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type(
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4),
std::forward<Args>(args)...);
}
#else
template <class T, class Arg1>
inline BOOST_DEDUCED_TYPENAME boost::disable_if<emulated_pair_constructor<T, Arg1>, void>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
{
new(address) T(boost::forward<Arg1>(a1));
}
template <class T, class Arg1>
inline BOOST_DEDUCED_TYPENAME boost::enable_if<emulated_pair_constructor<T, Arg1>, void>::type
construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
{
new(address) T(
boost::forward<Arg1>(a1),
BOOST_DEDUCED_TYPENAME T::second_type()
);
}
template <class T, class Arg1, class Arg2>
inline void construct_impl(void* address,
BOOST_FWD_REF(Arg1) a1, BOOST_FWD_REF(Arg2) a2)
{
new(address) T(boost::forward<Arg1>(a1), boost::forward<Arg2>(a2));
}
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
class T, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
BOOST_DEDUCED_TYPENAME \
boost::disable_if<emulated_pair_constructor<T>, void*>::type \
address, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
) \
inline typename normal_construct_n<T>::type \
construct_impl(void* address, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
new(address) T( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
}
BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
template <class T, class Key, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
BOOST_DEDUCED_TYPENAME \
boost::enable_if<emulated_pair_constructor<T>, void*>::type \
address, \
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
inline typename pair_construct_n<T>::type \
construct_impl(void* address, BOOST_FWD_REF(Key) key, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
new(address) T(k, \
BOOST_DEDUCED_TYPENAME \
T::second_type(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
new((void*)(&static_cast<T*>(address)->first)) \
typename T::first_type( \
boost::forward<Key>(key)); \
new((void*)(&static_cast<T*>(address)->second)) \
typename T::second_type( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
}
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
@ -661,10 +787,10 @@ namespace boost { namespace unordered { namespace detail {
class node_constructor
{
typedef ::boost::unordered::detail::buckets<Alloc, Unique> 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 BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
typedef typename buckets::node node;
typedef typename buckets::real_node_ptr real_node_ptr;
typedef typename buckets::value_type value_type;
typedef typename buckets::node_allocator node_allocator;
buckets& buckets_;
real_node_ptr node_;
@ -731,7 +857,7 @@ namespace boost { namespace unordered { namespace detail {
}
// no throw
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
typename buckets::node_ptr release()
{
real_node_ptr p = node_;
node_ = real_node_ptr();

View File

@ -15,19 +15,19 @@ namespace boost { namespace unordered { namespace detail {
class equivalent_table : public T::table_base
{
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::table_base table_base;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::value_allocator value_allocator;
typedef typename T::key_type key_type;
typedef typename T::value_type value_type;
typedef typename T::table_base table_base;
typedef typename T::node_constructor node_constructor;
typedef typename T::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME T::node node;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
typedef typename T::node node;
typedef typename T::node_ptr node_ptr;
typedef typename T::bucket_ptr bucket_ptr;
typedef typename T::extractor extractor;
// Constructors
@ -67,7 +67,9 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
static bool group_equals(node_ptr n1, node_ptr end1,
node_ptr n2, node_ptr end2)
{
@ -108,7 +110,28 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
#else
static bool group_equals(node_ptr n1, node_ptr end1,
node_ptr n2, node_ptr end2)
{
for(;;)
{
if(!extractor::compare_mapped(
node::get_value(n1), node::get_value(n2)))
return false;
n1 = n1->next_;
n2 = n2->next_;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
}
#endif
static bool find(node_ptr n, node_ptr end, value_type const& v)
{
for(;n != end; n = n->next_)
@ -203,6 +226,14 @@ namespace boost { namespace unordered { namespace detail {
this->find_node(bucket_index, hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
node_ptr emplace(please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return this->begin();
}
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
@ -273,19 +304,18 @@ namespace boost { namespace unordered { namespace detail {
template <class I>
void insert_range(I i, I j)
{
BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type
iterator_traversal_tag;
insert_for_range(i, j, iterator_traversal_tag);
insert_for_range(i, j,
BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type());
}
};
template <class H, class P, class A>
struct multiset : public types<
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
typename allocator_traits<A>::value_type,
typename allocator_traits<A>::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
set_extractor<typename allocator_traits<A>::value_type>,
false>
{
typedef equivalent_table<multiset<H, P, A> > impl;
@ -294,9 +324,9 @@ namespace boost { namespace unordered { namespace detail {
template <class K, class H, class P, class A>
struct multimap : public types<
K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
K, typename allocator_traits<A>::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
map_extractor<K, typename allocator_traits<A>::value_type>,
false>
{
typedef equivalent_table<multimap<K, H, P, A> > impl;

View File

@ -27,6 +27,18 @@ 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(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
{
@ -64,8 +76,8 @@ namespace detail {
return no_key();
}
template <class Arg>
static no_key extract(Arg const&, Arg const&)
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
@ -81,7 +93,7 @@ namespace detail {
struct map_extractor
{
typedef ValueType value_type;
typedef BOOST_DEDUCED_TYPENAME ::boost::remove_const<Key>::type key_type;
typedef typename ::boost::remove_const<Key>::type key_type;
static key_type const& extract(value_type const& v)
{
@ -127,6 +139,7 @@ namespace detail {
return no_key();
}
#else
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
@ -151,6 +164,54 @@ namespace detail {
}
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_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)
#elif defined(BOOST_HAS_TR1_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::tr1)
#endif
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;

View File

@ -44,6 +44,9 @@ namespace unordered
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
struct piecewise_construct_t {};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
}
}

View File

@ -59,11 +59,9 @@ namespace boost { namespace unordered { namespace detail {
{
bucket& operator=(bucket const&);
public:
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<A, bucket>::type
typedef typename ::boost::unordered::detail::rebind_wrap<A, bucket>::type
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef typename allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef bucket_ptr node_ptr;
node_ptr next_;
@ -77,7 +75,7 @@ namespace boost { namespace unordered { namespace detail {
struct value_base
{
typedef ValueType value_type;
BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
typename ::boost::aligned_storage<
sizeof(value_type),
::boost::alignment_of<value_type>::value>::type data_;
@ -107,12 +105,12 @@ namespace boost { namespace unordered { namespace detail {
template <class A>
struct ungrouped_node
: ::boost::unordered::detail::bucket<A>,
value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
value_base<typename allocator_traits<A>::value_type>
{
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
typedef typename bucket::bucket_ptr bucket_ptr;
typedef typename bucket::node_ptr node_ptr;
typedef typename allocator_traits<A>::value_type value_type;
std::size_t hash_;
@ -182,12 +180,12 @@ namespace boost { namespace unordered { namespace detail {
template <class A>
struct grouped_node
: ::boost::unordered::detail::bucket<A>,
value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
value_base<typename allocator_traits<A>::value_type>
{
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
typedef typename bucket::bucket_ptr bucket_ptr;
typedef typename bucket::node_ptr node_ptr;
typedef typename allocator_traits<A>::value_type value_type;
std::size_t hash_;
node_ptr group_prev_;

View File

@ -23,22 +23,22 @@ namespace boost { namespace unordered { namespace detail {
table(table const&);
table& operator=(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::functions functions;
typedef BOOST_DEDUCED_TYPENAME T::buckets buckets;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::value_allocator value_allocator;
typedef typename T::key_type key_type;
typedef typename T::value_type value_type;
typedef typename T::functions functions;
typedef typename T::buckets buckets;
typedef typename T::extractor extractor;
typedef 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::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair;
typedef typename T::node node;
typedef typename T::bucket bucket;
typedef typename T::node_ptr node_ptr;
typedef typename T::bucket_ptr bucket_ptr;
typedef typename T::node_allocator node_allocator;
typedef typename T::iterator_pair iterator_pair;
// Members
@ -485,11 +485,11 @@ namespace boost { namespace unordered { namespace detail {
typedef ::boost::unordered::detail::buckets<value_allocator, Unique> buckets;
typedef ::boost::unordered::detail::functions<hasher, key_equal> 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::node_allocator node_allocator;
typedef typename buckets::node node;
typedef typename buckets::bucket bucket;
typedef typename buckets::node_ptr node_ptr;
typedef typename buckets::bucket_ptr bucket_ptr;
typedef typename buckets::node_allocator node_allocator;
typedef std::pair<node_ptr, node_ptr> iterator_pair;
};
@ -514,18 +514,18 @@ namespace boost { namespace unordered { namespace iterator_detail {
class l_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
typename boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type&>
typename boost::unordered::detail::allocator_traits<A>::pointer,
typename boost::unordered::detail::allocator_traits<A>::value_type&>
{
public:
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef typename buckets::node_ptr node_ptr;
typedef typename buckets::node node;
typedef cl_iterator<A, Unique> const_local_iterator;
friend class cl_iterator<A, Unique>;
@ -538,7 +538,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() : ptr_() {}
l_iterator(node_ptr x, std::size_t b, std::size_t c)
: ptr_(x), bucket_(b), bucket_count_(c) {}
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
return node::get_value(ptr_);
}
value_type* operator->() const {
@ -575,18 +575,18 @@ namespace boost { namespace unordered { namespace iterator_detail {
class cl_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
typename boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
typename boost::unordered::detail::allocator_traits<A>::const_pointer,
typename boost::unordered::detail::allocator_traits<A>::value_type const& >
{
public:
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef typename buckets::node_ptr node_ptr;
typedef typename buckets::node node;
typedef l_iterator<A, Unique> local_iterator;
friend class l_iterator<A, Unique>;
@ -602,7 +602,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator(local_iterator x)
: ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const&
typename boost::unordered::detail::allocator_traits<A>::value_type const&
operator*() const {
return node::get_value(ptr_);
}
@ -640,18 +640,18 @@ namespace boost { namespace unordered { namespace iterator_detail {
class iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
typename boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& >
typename boost::unordered::detail::allocator_traits<A>::pointer,
typename boost::unordered::detail::allocator_traits<A>::value_type& >
{
public:
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef typename buckets::node node;
typedef typename buckets::node_ptr node_ptr;
typedef c_iterator<A, Unique> const_iterator;
friend class c_iterator<A, Unique>;
node_ptr node_;
@ -660,7 +660,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
iterator() : node_() {}
explicit iterator(node_ptr const& x) : node_(x) {}
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
return node::get_value(node_);
}
value_type* operator->() const {
@ -690,18 +690,18 @@ namespace boost { namespace unordered { namespace iterator_detail {
class c_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
typename boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
typename boost::unordered::detail::allocator_traits<A>::const_pointer,
typename boost::unordered::detail::allocator_traits<A>::value_type const& >
{
public:
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef typename buckets::node node;
typedef typename buckets::node_ptr node_ptr;
typedef ::boost::unordered::iterator_detail::iterator<A, Unique>
iterator;
friend class ::boost::unordered::iterator_detail::iterator<A, Unique>;
@ -726,7 +726,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
c_iterator() : node_() {}
explicit c_iterator(node_ptr const& x) : node_(x) {}
c_iterator(iterator const& x) : node_(x.node_) {}
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
typename boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
return node::get_value(node_);
}
value_type const* operator->() const {

View File

@ -15,19 +15,19 @@ namespace boost { namespace unordered { namespace detail {
class unique_table : public T::table_base
{
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::table_base table_base;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::value_allocator value_allocator;
typedef typename T::key_type key_type;
typedef typename T::value_type value_type;
typedef typename T::table_base table_base;
typedef typename T::node_constructor node_constructor;
typedef typename T::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME T::node node;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
typedef typename T::node node;
typedef typename T::node_ptr node_ptr;
typedef typename T::bucket_ptr bucket_ptr;
typedef typename T::extractor extractor;
typedef std::pair<node_ptr, bool> emplace_return;
@ -60,8 +60,15 @@ namespace boost { namespace unordered { namespace detail {
n1; n1 = n1->next_)
{
node_ptr n2 = other.find_matching_node(n1);
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if(!n2 || node::get_value(n1) != node::get_value(n2))
return false;
#else
if(!n2 || !extractor::compare_mapped(
node::get_value(n1), node::get_value(n2)))
return false;
#endif
}
return true;
@ -111,7 +118,7 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k)
{
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
typedef typename value_type::second_type mapped_type;
std::size_t hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_;
@ -189,6 +196,14 @@ namespace boost { namespace unordered { namespace detail {
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
emplace_return emplace(please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args>
@ -392,10 +407,10 @@ namespace boost { namespace unordered { namespace detail {
template <class H, class P, class A>
struct set : public types<
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
typename allocator_traits<A>::value_type,
typename allocator_traits<A>::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
set_extractor<typename allocator_traits<A>::value_type>,
true>
{
typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl;
@ -404,9 +419,9 @@ namespace boost { namespace unordered { namespace detail {
template <class K, class H, class P, class A>
struct map : public types<
K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
K, typename allocator_traits<A>::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
map_extractor<K, typename allocator_traits<A>::value_type>,
true>
{
typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl;

View File

@ -23,13 +23,23 @@
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_empty.hpp>
#if defined(BOOST_NO_RVALUE_REFERENCES)
#include <boost/type_traits/is_class.hpp>
#endif
#include <boost/throw_exception.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/move/move.hpp>
#include <boost/swap.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/tuple/tuple.hpp>
#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
#include <tuple>
#endif
#include <boost/unordered/detail/allocator_helpers.hpp>
// Template parameters:
//
@ -121,6 +131,36 @@ namespace boost { namespace unordered { namespace detail {
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#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 <
rv_ref_impl<T>,
please_ignore_this_overload
>::type
{};
#define BOOST_UNORDERED_RV_REF(T) \
typename ::boost::unordered::detail::rv_ref<T>::type
#endif
////////////////////////////////////////////////////////////////////////////
@ -197,22 +237,6 @@ namespace boost { namespace unordered { namespace detail {
return *bound;
}
////////////////////////////////////////////////////////////////////////////
// pair_cast - because some libraries don't have the full pair constructors.
#if 0
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));
}
#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
::boost::unordered::detail::pair_cast<First, Last>(Argument)
#else
#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
Argument
#endif
////////////////////////////////////////////////////////////////////////////
// insert_size/initial_size
@ -242,9 +266,8 @@ namespace boost { namespace unordered { namespace detail {
template <class I>
inline std::size_t insert_size(I i, I j)
{
BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type
iterator_traversal_tag;
return insert_size(i, j, iterator_traversal_tag);
return insert_size(i, j,
typename ::boost::iterator_traversal<I>::type());
}
template <class I>
@ -295,8 +318,8 @@ namespace boost { namespace unordered { namespace detail {
: private generate_base<T1, 1>::type,
private generate_base<T2, 2>::type
{
typedef BOOST_DEDUCED_TYPENAME generate_base<T1, 1>::type base1;
typedef BOOST_DEDUCED_TYPENAME generate_base<T2, 2>::type base2;
typedef typename generate_base<T1, 1>::type base1;
typedef typename generate_base<T2, 2>::type base2;
typedef T1 first_type;
typedef T2 second_type;

View File

@ -52,24 +52,21 @@ namespace unordered
private:
#endif
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<
typedef typename ::boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef ::boost::unordered::detail::allocator_traits<value_allocator> allocator_traits;
typedef ::boost::unordered::detail::map<K, H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
typedef typename types::impl table;
typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
typedef typename types::node_ptr node_ptr;
public:
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::const_pointer const_pointer;
typedef typename allocator_traits::pointer pointer;
typedef typename allocator_traits::const_pointer const_pointer;
typedef value_type& reference;
typedef value_type const& const_reference;
@ -135,9 +132,7 @@ namespace unordered
unordered_map(unordered_map const&);
#if BOOST_UNORDERED_USE_RV_REF
unordered_map& operator=(
BOOST_RV_REF(unordered_map) x)
unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
{
table_.move_assign(x.table_);
return *this;
@ -147,7 +142,6 @@ namespace unordered
: table_(other.table_, ::boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
@ -260,11 +254,10 @@ namespace unordered
#endif
std::pair<iterator, bool> insert(value_type const&);
iterator insert(const_iterator, value_type const&);
#if BOOST_UNORDERED_USE_RV_REF
std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
iterator insert(const_iterator, value_type const&);
iterator insert(const_iterator, BOOST_RV_REF(value_type));
#endif
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@ -403,8 +396,7 @@ namespace unordered
private:
#endif
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<
typedef typename ::boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@ -412,16 +404,14 @@ namespace unordered
typedef ::boost::unordered::detail::multimap<K, H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
typedef typename types::impl table;
typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
typedef typename types::node_ptr node_ptr;
public:
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::const_pointer const_pointer;
typedef typename allocator_traits::pointer pointer;
typedef typename allocator_traits::const_pointer const_pointer;
typedef value_type& reference;
typedef value_type const& const_reference;
@ -487,9 +477,7 @@ namespace unordered
unordered_multimap(unordered_multimap const&);
#if BOOST_UNORDERED_USE_RV_REF
unordered_multimap& operator=(
BOOST_RV_REF(unordered_multimap) x)
unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
{
table_.move_assign(x.table_);
return *this;
@ -499,7 +487,6 @@ namespace unordered
: table_(other.table_, ::boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
@ -612,11 +599,10 @@ namespace unordered
#endif
iterator insert(value_type const&);
iterator insert(const_iterator, value_type const&);
#if BOOST_UNORDERED_USE_RV_REF
iterator insert(BOOST_RV_REF(value_type));
iterator insert(const_iterator, value_type const&);
iterator insert(const_iterator, BOOST_RV_REF(value_type));
#endif
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@ -851,16 +837,15 @@ namespace unordered
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class K, class T, class H, class P, class A>
template <class... Args>
std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
unordered_map<K,T,H,P,A>::emplace(Args&&... args)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(std::forward<Args>(args)...));
return table_.emplace(std::forward<Args>(args)...);
}
template <class K, class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...).first);
@ -869,18 +854,17 @@ namespace unordered
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
template <class K, class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
unordered_map<K,T,H,P,A>::emplace(
boost::unordered::detail::empty_emplace,
value_type v
)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(boost::move(v)));
return table_.emplace(boost::move(v));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::emplace_hint(const_iterator,
boost::unordered::detail::empty_emplace,
value_type v
@ -895,23 +879,18 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
std::pair< \
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, \
bool> \
std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool> \
unordered_map<K,T,H,P,A>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
{ \
return \
BOOST_UNORDERED_PAIR_CAST(iterator, bool, \
table_.emplace( \
BOOST_UNORDERED_CALL_PARAMS(z, n))); \
return table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
} \
\
template <class K, class T, class H, class P, class A> \
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator \
typename unordered_map<K,T,H,P,A>::iterator \
unordered_map<K,T,H,P,A>::emplace_hint( \
const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
@ -929,38 +908,34 @@ namespace unordered
#endif
template <class K, class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
unordered_map<K,T,H,P,A>::insert(value_type const& obj)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(obj));
return table_.emplace(obj);
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::insert(const_iterator,
value_type const& obj)
{
return iterator(table_.emplace(obj).first);
}
#if BOOST_UNORDERED_USE_RV_REF
template <class K, class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
unordered_map<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(boost::move(obj)));
return table_.emplace(boost::move(obj));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::insert(const_iterator,
BOOST_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)).first);
}
#endif
template <class K, class T, class H, class P, class A>
template <class InputIt>
@ -979,21 +954,21 @@ namespace unordered
#endif
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
typename unordered_map<K,T,H,P,A>::size_type
unordered_map<K,T,H,P,A>::erase(const key_type& k)
{
return table_.erase_key(k);
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
@ -1015,35 +990,35 @@ namespace unordered
// observers
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::hasher
typename unordered_map<K,T,H,P,A>::hasher
unordered_map<K,T,H,P,A>::hash_function() const
{
return table_.hash_function();
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::key_equal
typename unordered_map<K,T,H,P,A>::key_equal
unordered_map<K,T,H,P,A>::key_eq() const
{
return table_.key_eq();
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
typename unordered_map<K,T,H,P,A>::mapped_type&
unordered_map<K,T,H,P,A>::operator[](const key_type &k)
{
return table_[k].second;
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
typename unordered_map<K,T,H,P,A>::mapped_type&
unordered_map<K,T,H,P,A>::at(const key_type& k)
{
return table_.at(k).second;
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type const&
typename unordered_map<K,T,H,P,A>::mapped_type const&
unordered_map<K,T,H,P,A>::at(const key_type& k) const
{
return table_.at(k).second;
@ -1052,14 +1027,14 @@ namespace unordered
// lookup
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
@ -1068,7 +1043,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1080,7 +1055,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1090,7 +1065,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
typename unordered_map<K,T,H,P,A>::size_type
unordered_map<K,T,H,P,A>::count(const key_type& k) const
{
return table_.count(k);
@ -1098,26 +1073,24 @@ namespace unordered
template <class K, class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator,
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator>
typename unordered_map<K,T,H,P,A>::iterator,
typename unordered_map<K,T,H,P,A>::iterator>
unordered_map<K,T,H,P,A>::equal_range(const key_type& k)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class K, class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator,
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator>
typename unordered_map<K,T,H,P,A>::const_iterator,
typename unordered_map<K,T,H,P,A>::const_iterator>
unordered_map<K,T,H,P,A>::equal_range(const key_type& k) const
{
return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
typename unordered_map<K,T,H,P,A>::size_type
unordered_map<K,T,H,P,A>::bucket_size(size_type n) const
{
return table_.bucket_size(n);
@ -1293,7 +1266,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::emplace(Args&&... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
@ -1301,7 +1274,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::emplace_hint(
const_iterator, Args&&... args)
{
@ -1312,7 +1285,7 @@ namespace unordered
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::emplace(
boost::unordered::detail::empty_emplace,
value_type v
@ -1322,7 +1295,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::emplace_hint(const_iterator,
boost::unordered::detail::empty_emplace,
value_type v
@ -1337,7 +1310,7 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator \
typename unordered_multimap<K,T,H,P,A>::iterator \
unordered_multimap<K,T,H,P,A>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
{ \
@ -1349,7 +1322,7 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator \
typename unordered_multimap<K,T,H,P,A>::iterator \
unordered_multimap<K,T,H,P,A>::emplace_hint( \
const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
@ -1366,36 +1339,34 @@ namespace unordered
#endif
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::insert(value_type const& obj)
{
return iterator(table_.emplace(obj));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::insert(
const_iterator, value_type const& obj)
{
return iterator(table_.emplace(obj));
}
#if BOOST_UNORDERED_USE_RV_REF
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::insert(
const_iterator, BOOST_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)));
}
#endif
template <class K, class T, class H, class P, class A>
template <class InputIt>
@ -1414,21 +1385,21 @@ namespace unordered
#endif
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
typename unordered_multimap<K,T,H,P,A>::size_type
unordered_multimap<K,T,H,P,A>::erase(const key_type& k)
{
return table_.erase_key(k);
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
@ -1450,14 +1421,14 @@ namespace unordered
// observers
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::hasher
typename unordered_multimap<K,T,H,P,A>::hasher
unordered_multimap<K,T,H,P,A>::hash_function() const
{
return table_.hash_function();
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::key_equal
typename unordered_multimap<K,T,H,P,A>::key_equal
unordered_multimap<K,T,H,P,A>::key_eq() const
{
return table_.key_eq();
@ -1466,14 +1437,14 @@ namespace unordered
// lookup
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
@ -1482,7 +1453,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1494,7 +1465,7 @@ namespace unordered
template <class K, class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1504,7 +1475,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
typename unordered_multimap<K,T,H,P,A>::size_type
unordered_multimap<K,T,H,P,A>::count(const key_type& k) const
{
return table_.count(k);
@ -1512,26 +1483,24 @@ namespace unordered
template <class K, class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator,
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator>
typename unordered_multimap<K,T,H,P,A>::iterator,
typename unordered_multimap<K,T,H,P,A>::iterator>
unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class K, class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator,
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator>
typename unordered_multimap<K,T,H,P,A>::const_iterator,
typename unordered_multimap<K,T,H,P,A>::const_iterator>
unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k) const
{
return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class K, class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
typename unordered_multimap<K,T,H,P,A>::size_type
unordered_multimap<K,T,H,P,A>::bucket_size(size_type n) const
{
return table_.bucket_size(n);

View File

@ -52,8 +52,7 @@ namespace unordered
private:
#endif
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<
typedef typename ::boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@ -61,16 +60,14 @@ namespace unordered
typedef ::boost::unordered::detail::set<H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
typedef typename types::impl table;
typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
typedef typename types::node_ptr node_ptr;
public:
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::const_pointer const_pointer;
typedef typename allocator_traits::pointer pointer;
typedef typename allocator_traits::const_pointer const_pointer;
typedef value_type& reference;
typedef value_type const& const_reference;
@ -134,9 +131,7 @@ namespace unordered
unordered_set(unordered_set const&);
#if BOOST_UNORDERED_USE_RV_REF
unordered_set& operator=(
BOOST_RV_REF(unordered_set) x)
unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
{
table_.move_assign(x.table_);
return *this;
@ -146,7 +141,6 @@ namespace unordered
: table_(other.table_, ::boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
@ -257,11 +251,9 @@ namespace unordered
#endif
std::pair<iterator, bool> insert(value_type const&);
std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type));
iterator insert(const_iterator, value_type const&);
#if BOOST_UNORDERED_USE_RV_REF
std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
iterator insert(const_iterator, BOOST_RV_REF(value_type));
#endif
iterator insert(const_iterator, BOOST_UNORDERED_RV_REF(value_type));
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@ -384,8 +376,7 @@ namespace unordered
private:
#endif
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<
typedef typename ::boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@ -393,16 +384,14 @@ namespace unordered
typedef ::boost::unordered::detail::multiset<H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
typedef typename types::impl table;
typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
typedef typename types::node_ptr node_ptr;
public:
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits::const_pointer const_pointer;
typedef typename allocator_traits::pointer pointer;
typedef typename allocator_traits::const_pointer const_pointer;
typedef value_type& reference;
typedef value_type const& const_reference;
@ -466,9 +455,7 @@ namespace unordered
unordered_multiset(unordered_multiset const&);
#if BOOST_UNORDERED_USE_RV_REF
unordered_multiset& operator=(
BOOST_RV_REF(unordered_multiset) x)
unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
{
table_.move_assign(x.table_);
return *this;
@ -478,7 +465,6 @@ namespace unordered
: table_(other.table_, ::boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
@ -589,11 +575,10 @@ namespace unordered
#endif
iterator insert(value_type const&);
iterator insert(BOOST_UNORDERED_RV_REF(value_type));
iterator insert(const_iterator, value_type const&);
#if BOOST_UNORDERED_USE_RV_REF
iterator insert(BOOST_RV_REF(value_type));
iterator insert(const_iterator, BOOST_RV_REF(value_type));
#endif
iterator insert(const_iterator, BOOST_UNORDERED_RV_REF(value_type));
template <class InputIt>
void insert(InputIt, InputIt);
@ -818,16 +803,15 @@ namespace unordered
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class T, class H, class P, class A>
template <class... Args>
std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
unordered_set<T,H,P,A>::emplace(Args&&... args)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(std::forward<Args>(args)...));
return table_.emplace(std::forward<Args>(args)...);
}
template <class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...).first);
@ -835,18 +819,17 @@ namespace unordered
#else
template <class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
unordered_set<T,H,P,A>::emplace(
boost::unordered::detail::empty_emplace,
value_type v
)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(boost::move(v)));
return table_.emplace(boost::move(v));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::emplace_hint(const_iterator,
boost::unordered::detail::empty_emplace,
value_type v
@ -860,23 +843,18 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
std::pair< \
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, \
bool> \
std::pair<typename unordered_set<T,H,P,A>::iterator, bool> \
unordered_set<T,H,P,A>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
{ \
return \
BOOST_UNORDERED_PAIR_CAST(iterator, bool, \
table_.emplace( \
BOOST_UNORDERED_CALL_PARAMS(z, n))); \
return table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
} \
\
template <class T, class H, class P, class A> \
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator \
typename unordered_set<T,H,P,A>::iterator \
unordered_set<T,H,P,A>::emplace_hint( \
const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
@ -894,38 +872,34 @@ namespace unordered
#endif
template <class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
unordered_set<T,H,P,A>::insert(value_type const& obj)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(obj));
return table_.emplace(obj);
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::insert(const_iterator,
value_type const& obj)
{
return iterator(table_.emplace(obj).first);
}
#if BOOST_UNORDERED_USE_RV_REF
template <class T, class H, class P, class A>
std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
unordered_set<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
unordered_set<T,H,P,A>::insert(BOOST_UNORDERED_RV_REF(value_type) obj)
{
return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
table_.emplace(boost::move(obj)));
return table_.emplace(boost::move(obj));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::insert(const_iterator,
BOOST_RV_REF(value_type) obj)
BOOST_UNORDERED_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)).first);
}
#endif
template <class T, class H, class P, class A>
template <class InputIt>
@ -943,21 +917,21 @@ namespace unordered
#endif
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
typename unordered_set<T,H,P,A>::size_type
unordered_set<T,H,P,A>::erase(const key_type& k)
{
return table_.erase_key(k);
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::erase(const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
@ -978,14 +952,14 @@ namespace unordered
// observers
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::hasher
typename unordered_set<T,H,P,A>::hasher
unordered_set<T,H,P,A>::hash_function() const
{
return table_.hash_function();
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::key_equal
typename unordered_set<T,H,P,A>::key_equal
unordered_set<T,H,P,A>::key_eq() const
{
return table_.key_eq();
@ -994,7 +968,7 @@ namespace unordered
// lookup
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
@ -1003,7 +977,7 @@ namespace unordered
template <class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1013,7 +987,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
typename unordered_set<T,H,P,A>::size_type
unordered_set<T,H,P,A>::count(const key_type& k) const
{
return table_.count(k);
@ -1021,16 +995,15 @@ namespace unordered
template <class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator,
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator>
typename unordered_set<T,H,P,A>::const_iterator,
typename unordered_set<T,H,P,A>::const_iterator>
unordered_set<T,H,P,A>::equal_range(const key_type& k) const
{
return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
typename unordered_set<T,H,P,A>::size_type
unordered_set<T,H,P,A>::bucket_size(size_type n) const
{
return table_.bucket_size(n);
@ -1206,7 +1179,7 @@ namespace unordered
template <class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::emplace(Args&&... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
@ -1214,7 +1187,7 @@ namespace unordered
template <class T, class H, class P, class A>
template <class... Args>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::emplace_hint(
const_iterator, Args&&... args)
{
@ -1224,7 +1197,7 @@ namespace unordered
#else
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::emplace(
boost::unordered::detail::empty_emplace,
value_type v
@ -1234,7 +1207,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::emplace_hint(const_iterator,
boost::unordered::detail::empty_emplace,
value_type v
@ -1248,7 +1221,7 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator \
typename unordered_multiset<T,H,P,A>::iterator \
unordered_multiset<T,H,P,A>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
{ \
@ -1260,7 +1233,7 @@ namespace unordered
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator \
typename unordered_multiset<T,H,P,A>::iterator \
unordered_multiset<T,H,P,A>::emplace_hint( \
const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
@ -1277,36 +1250,34 @@ namespace unordered
#endif
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::insert(value_type const& obj)
{
return iterator(table_.emplace(obj));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::insert(const_iterator,
value_type const& obj)
{
return iterator(table_.emplace(obj));
}
#if BOOST_UNORDERED_USE_RV_REF
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::insert(BOOST_UNORDERED_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::insert(const_iterator,
BOOST_RV_REF(value_type) obj)
BOOST_UNORDERED_RV_REF(value_type) obj)
{
return iterator(table_.emplace(boost::move(obj)));
}
#endif
template <class T, class H, class P, class A>
template <class InputIt>
@ -1324,21 +1295,21 @@ namespace unordered
#endif
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
typename unordered_multiset<T,H,P,A>::size_type
unordered_multiset<T,H,P,A>::erase(const key_type& k)
{
return table_.erase_key(k);
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::erase(const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
@ -1359,14 +1330,14 @@ namespace unordered
// observers
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::hasher
typename unordered_multiset<T,H,P,A>::hasher
unordered_multiset<T,H,P,A>::hash_function() const
{
return table_.hash_function();
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::key_equal
typename unordered_multiset<T,H,P,A>::key_equal
unordered_multiset<T,H,P,A>::key_eq() const
{
return table_.key_eq();
@ -1375,7 +1346,7 @@ namespace unordered
// lookup
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
@ -1384,7 +1355,7 @@ namespace unordered
template <class T, class H, class P, class A>
template <class CompatibleKey, class CompatibleHash,
class CompatiblePredicate>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(
CompatibleKey const& k,
CompatibleHash const& hash,
@ -1394,7 +1365,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
typename unordered_multiset<T,H,P,A>::size_type
unordered_multiset<T,H,P,A>::count(const key_type& k) const
{
return table_.count(k);
@ -1402,16 +1373,15 @@ namespace unordered
template <class T, class H, class P, class A>
std::pair<
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator,
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator>
typename unordered_multiset<T,H,P,A>::const_iterator,
typename unordered_multiset<T,H,P,A>::const_iterator>
unordered_multiset<T,H,P,A>::equal_range(const key_type& k) const
{
return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
table_.equal_range(k));
return table_.equal_range(k);
}
template <class T, class H, class P, class A>
BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
typename unordered_multiset<T,H,P,A>::size_type
unordered_multiset<T,H,P,A>::bucket_size(size_type n) const
{
return table_.bucket_size(n);

View File

@ -23,6 +23,7 @@ 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 ]
@ -34,6 +35,9 @@ 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 ]
@ -44,5 +48,6 @@ test-suite unordered
[ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ]
[ run equality_tests.cpp ]
[ run equality_deprecated.cpp ]
[ run swap_tests.cpp ]
;

View File

@ -16,7 +16,7 @@
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
/*
template class boost::unordered_set<
int,
boost::hash<int>,
@ -27,7 +27,7 @@ template class boost::unordered_multiset<
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>,

View File

@ -0,0 +1,173 @@
// 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 <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()

View File

@ -537,8 +537,6 @@ struct overloaded_constructor
}
};
// This will actually be deprecated pretty soon.
UNORDERED_AUTO_TEST(map_emplace_test)
{
boost::unordered_map<int, overloaded_constructor> x;
@ -547,14 +545,15 @@ UNORDERED_AUTO_TEST(map_emplace_test)
BOOST_TEST(x.find(0) != x.end() &&
x.find(0)->second == overloaded_constructor());
x.emplace(1);
BOOST_TEST(x.find(1) != x.end() &&
x.find(1)->second == overloaded_constructor());
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));
@ -562,6 +561,7 @@ UNORDERED_AUTO_TEST(map_emplace_test)
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)
@ -593,6 +593,37 @@ UNORDERED_AUTO_TEST(set_emplace_test)
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()

View File

@ -0,0 +1,89 @@
// 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>));
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type, std::size_t>));
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();
}

View File

@ -1,4 +1,4 @@
#include <iostream>
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -327,6 +327,13 @@ namespace unnecessary_copy_tests
x.emplace();
COPY_COUNT(2); MOVE_COUNT(0);
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(),
boost::make_tuple());
COPY_COUNT(2); MOVE_COUNT(0);
//
// 1 argument
//
@ -345,19 +352,23 @@ namespace unnecessary_copy_tests
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
(!defined(__GNUC__) && !defined(BOOST_MSVC))
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)
// 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
//
@ -382,6 +393,47 @@ namespace unnecessary_copy_tests
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
}
}