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 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. 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]] [[Method] [Description]]
[ [

View File

@ -151,4 +151,7 @@ in some breaking changes:
the allocator has a member structure `propagate_on_container_swap`, the allocator has a member structure `propagate_on_container_swap`,
such that `propagate_on_container_swap::value` is true. 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] [endsect]

View File

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

View File

@ -4,25 +4,42 @@
[section:compliance C++11 Compliance] [section:compliance C++11 Compliance]
/TODO/: Look into C++11's `std::pair`.
[section:allocator_compliance Use of allocators] [section:allocator_compliance Use of allocators]
* Objects are not constructed using the allocator. The node containing them C++11 introduced a new, mostly backwards compatible, allocator system.
is constructed using the allocator's `construct` function, but then the This uses a traits class, `allocator_traits` to handle the allocator
object is constructed in a buffer in that node by calling the constructor adding extra functionality, and making some methods and types optional.
directly. At the time of writing there isn't a stable release of a standard library
* Similarly the object is destructed by calling its destructor directly, and with `allocator_traits` (libc++ has `allocator_traits` but it hasn't been
then the allocator's `destroy` method is used to destruct the node. released yet) so a partial implementation is always used.
* 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 A full implementation of `allocator_traits` requires sophisticated
detection for g++ 4.4 or laster, Visual C++ 2008 or later, Clang and maybe member function detection which requires support for SFINAE expressions,
other compilers which support SFINAE for expressions. or something close. This is available on GCC from version 4.4, Clang and
* `pointer_traits` aren't used. Instead, pointer types are obtained from Visual C++ 2008 (with a little hacking) or later.
rebound allocators.
* /TODO/: Any other defficiences of `allocator_traits` emulation. On these compilers, the `construct`, `destroy` and `max_size` member functions
* Pointers of base types are used to store the location of a derived type. are optional, as per C++11. On other compilers they are still required.
(/TODO/: I'm not sure if that isn't compliant).
`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] [endsect]
@ -35,19 +52,43 @@ use Boost.Move.
* Non-copyable objects can be stored in the containers, but without support * Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable. 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. * Argument forwarding is not perfect.
* /TODO/: Constructor call for pairs.
[endsect] [endsect]
[section:other Other] [section:pairs Pairs]
* When swapping, `Pred` and `Hash` are not currently swapped by calling Since the containers use `std::pair` they're limited to the version
`swap`, their copy constructors are used. from the current standard library. But since C++11 `std::pair`'s
* As a consequence when swapping an exception may be throw from their `piecewise_construct` based constructor is very useful, `emplace`
copy constructor. 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] [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 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 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]] [[Method] [Description]]
[ [

View File

@ -2,15 +2,6 @@
/ Distributed under the Boost Software License, Version 1.0. (See accompanying / 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) ] / 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 [def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
hash table]] hash table]]
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function [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 or isn't practical. In contrast, a hash table only needs an equality function
and a hash function for the key. and a hash function for the key.
With this in mind, the __tr1__ introduced the unordered associative containers, With this in mind, unordered associative containers were added to the C++
which are implemented using hash tables, and they have now been added to the standard. This is an implementation of the containers described in C++11,
__draft__. with some [link unordered.compliance deviations from the standard] in
order to work with non-C++11 compilers and libraries.
This library supplies an almost complete implementation of the specification in
the __draft__.
`unordered_set` and `unordered_multiset` are defined in the header `unordered_set` and `unordered_multiset` are defined in the header
<[headerref boost/unordered_set.hpp]> <[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] [h2 Equality operators]
/TODO/: This is out of date.
`operator==` and `operator!=` are not included in the standard, but I've `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 added them as I think they could be useful and can be implemented
fairly efficiently. They are specified differently to the other standard 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] [h3 C++0x allocators]
/TODO/: This is out of date.
Recent drafts have included an overhaul of the allocators, but this was Recent drafts have included an overhaul of the allocators, but this was
dependent on concepts which are no longer in the standard. dependent on concepts which are no longer in the standard.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946] [@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] [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. It isn't clear how to swap containers when their allocators aren't equal.
This is This is
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#431 [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#431

View File

@ -60,10 +60,6 @@ EOL;
</simpara></purpose> </simpara></purpose>
<description> <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> <para><emphasis role="bold">Template Parameters</emphasis>
<informaltable> <informaltable>
<tgroup cols="2"> <tgroup cols="2">
@ -236,6 +232,9 @@ EOL;
</parameter> </parameter>
<description> <description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para> <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> </description>
<requires> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
@ -249,12 +248,18 @@ EOL;
<para>The move constructor.</para> <para>The move constructor.</para>
</description> </description>
<notes> <notes>
<para>This is emulated on compilers without rvalue references.</para> <para>This is implemented using Boost.Move.</para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <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> </para>
</requires> </requires>
</constructor> </constructor>
@ -289,14 +294,12 @@ EOL;
<type><?php echo $name; ?>&amp;</type> <type><?php echo $name; ?>&amp;</type>
<description> <description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para> <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> </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> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
</requires> </requires>
@ -308,18 +311,21 @@ EOL;
<type><?php echo $name; ?>&amp;</type> <type><?php echo $name; ?>&amp;</type>
<description> <description>
<para>The move assignment operator.</para> <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> </description>
<notes> <notes>
<para> <para>
On compilers without rvalue references, there is a single assignment On compilers without rvalue references, this is emulated using
operator with the signature <code>operator=(<?php echo $name; ?>)</code> Boost.Move.
in order to emulate move semantics.
</para> </para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para> </para>
</requires> </requires>
</method> </method>
@ -406,6 +412,10 @@ EOL;
<para>If the compiler doesn't support variadic template arguments or rvalue <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="emplace_hint"> <method name="emplace_hint">
@ -444,6 +454,10 @@ EOL;
<para>If the compiler doesn't support variadic template arguments or rvalue <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="insert"> <method name="insert">
@ -541,15 +555,13 @@ EOL;
</returns> </returns>
<throws> <throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para> <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> </throws>
<notes> <notes>
<para> <para>
When the number of elements is a lot smaller than the number of buckets In older versions this could be inefficient because it had to search
this function can be very inefficient as it has to search through empty through several buckets to find the position of the returned iterator.
buckets for the next element, in order to return the iterator. The data structure has been changed so that this is no longer the case,
The method <methodname>quick_erase</methodname> is faster, but has yet and the alternative erase methods have been deprecated.
to be standardized.
</para> </para>
</notes> </notes>
</method> </method>
@ -601,13 +613,10 @@ EOL;
</throws> </throws>
<notes> <notes>
<para> <para>
This method is faster than <methodname>erase</methodname> as This method was implemented because returning an iterator to
it doesn't have to find the next element in the container - the next element from <code>erase</code> was expensive, but
a potentially costly operation. the container has been redesigned so that is no longer the
</para> case. So this method is now deprecated.
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
</para> </para>
</notes> </notes>
</method> </method>
@ -625,10 +634,10 @@ EOL;
</throws> </throws>
<notes> <notes>
<para> <para>
This method is now deprecated, use This method was implemented because returning an iterator to
<methodname>quick_return</methodname> instead. Although be the next element from <code>erase</code> was expensive, but
warned that as that isn't standardized yet, it could also the container has been redesigned so that is no longer the
change. case. So this method is now deprecated.
</para> </para>
</notes> </notes>
</method> </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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>
@ -952,6 +962,7 @@ EOL;
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> equivalent equality predicates.</para>
@ -975,6 +986,7 @@ EOL;
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </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. An unordered associative container that stores unique values.
</simpara></purpose> </simpara></purpose>
<description> <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> <para><emphasis role="bold">Template Parameters</emphasis>
<informaltable> <informaltable>
<tgroup cols="2"> <tgroup cols="2">
@ -181,6 +177,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<description> <description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para> <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> </description>
<requires> <requires>
<para><code>value_type</code> is copy constructible</para> <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> <para>The move constructor.</para>
</description> </description>
<notes> <notes>
<para>This is emulated on compilers without rvalue references.</para> <para>This is implemented using Boost.Move.</para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <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> </para>
</requires> </requires>
</constructor> </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> <type>unordered_set&amp;</type>
<description> <description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para> <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> </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> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
</requires> </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> <type>unordered_set&amp;</type>
<description> <description>
<para>The move assignment operator.</para> <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> </description>
<notes> <notes>
<para> <para>
On compilers without rvalue references, there is a single assignment On compilers without rvalue references, this is emulated using
operator with the signature <code>operator=(unordered_set)</code> Boost.Move.
in order to emulate move semantics.
</para> </para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para> </para>
</requires> </requires>
</method> </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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="emplace_hint"> <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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="insert"> <method name="insert">
@ -457,15 +471,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns> </returns>
<throws> <throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para> <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> </throws>
<notes> <notes>
<para> <para>
When the number of elements is a lot smaller than the number of buckets In older versions this could be inefficient because it had to search
this function can be very inefficient as it has to search through empty through several buckets to find the position of the returned iterator.
buckets for the next element, in order to return the iterator. The data structure has been changed so that this is no longer the case,
The method <methodname>quick_erase</methodname> is faster, but has yet and the alternative erase methods have been deprecated.
to be standardized.
</para> </para>
</notes> </notes>
</method> </method>
@ -517,13 +529,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is faster than <methodname>erase</methodname> as This method was implemented because returning an iterator to
it doesn't have to find the next element in the container - the next element from <code>erase</code> was expensive, but
a potentially costly operation. the container has been redesigned so that is no longer the
</para> case. So this method is now deprecated.
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
</para> </para>
</notes> </notes>
</method> </method>
@ -541,10 +550,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is now deprecated, use This method was implemented because returning an iterator to
<methodname>quick_return</methodname> instead. Although be the next element from <code>erase</code> was expensive, but
warned that as that isn't standardized yet, it could also the container has been redesigned so that is no longer the
change. case. So this method is now deprecated.
</para> </para>
</notes> </notes>
</method> </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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>
@ -832,6 +842,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </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. An unordered associative container that stores values. The same key can be stored multiple times.
</simpara></purpose> </simpara></purpose>
<description> <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> <para><emphasis role="bold">Template Parameters</emphasis>
<informaltable> <informaltable>
<tgroup cols="2"> <tgroup cols="2">
@ -1070,6 +1079,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<description> <description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para> <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> </description>
<requires> <requires>
<para><code>value_type</code> is copy constructible</para> <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> <para>The move constructor.</para>
</description> </description>
<notes> <notes>
<para>This is emulated on compilers without rvalue references.</para> <para>This is implemented using Boost.Move.</para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <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> </para>
</requires> </requires>
</constructor> </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> <type>unordered_multiset&amp;</type>
<description> <description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para> <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> </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> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
</requires> </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> <type>unordered_multiset&amp;</type>
<description> <description>
<para>The move assignment operator.</para> <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> </description>
<notes> <notes>
<para> <para>
On compilers without rvalue references, there is a single assignment On compilers without rvalue references, this is emulated using
operator with the signature <code>operator=(unordered_multiset)</code> Boost.Move.
in order to emulate move semantics.
</para> </para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para> </para>
</requires> </requires>
</method> </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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="emplace_hint"> <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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="insert"> <method name="insert">
@ -1344,15 +1371,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns> </returns>
<throws> <throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para> <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> </throws>
<notes> <notes>
<para> <para>
When the number of elements is a lot smaller than the number of buckets In older versions this could be inefficient because it had to search
this function can be very inefficient as it has to search through empty through several buckets to find the position of the returned iterator.
buckets for the next element, in order to return the iterator. The data structure has been changed so that this is no longer the case,
The method <methodname>quick_erase</methodname> is faster, but has yet and the alternative erase methods have been deprecated.
to be standardized.
</para> </para>
</notes> </notes>
</method> </method>
@ -1404,13 +1429,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is faster than <methodname>erase</methodname> as This method was implemented because returning an iterator to
it doesn't have to find the next element in the container - the next element from <code>erase</code> was expensive, but
a potentially costly operation. the container has been redesigned so that is no longer the
</para> case. So this method is now deprecated.
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
</para> </para>
</notes> </notes>
</method> </method>
@ -1428,10 +1450,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is now deprecated, use This method was implemented because returning an iterator to
<methodname>quick_return</methodname> instead. Although be the next element from <code>erase</code> was expensive, but
warned that as that isn't standardized yet, it could also the container has been redesigned so that is no longer the
change. case. So this method is now deprecated.
</para> </para>
</notes> </notes>
</method> </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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>
@ -1719,6 +1742,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </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. An unordered associative container that associates unique keys with another value.
</simpara></purpose> </simpara></purpose>
<description> <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> <para><emphasis role="bold">Template Parameters</emphasis>
<informaltable> <informaltable>
<tgroup cols="2"> <tgroup cols="2">
@ -1969,6 +1991,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<description> <description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para> <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> </description>
<requires> <requires>
<para><code>value_type</code> is copy constructible</para> <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> <para>The move constructor.</para>
</description> </description>
<notes> <notes>
<para>This is emulated on compilers without rvalue references.</para> <para>This is implemented using Boost.Move.</para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <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> </para>
</requires> </requires>
</constructor> </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> <type>unordered_map&amp;</type>
<description> <description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para> <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> </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> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
</requires> </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> <type>unordered_map&amp;</type>
<description> <description>
<para>The move assignment operator.</para> <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> </description>
<notes> <notes>
<para> <para>
On compilers without rvalue references, there is a single assignment On compilers without rvalue references, this is emulated using
operator with the signature <code>operator=(unordered_map)</code> Boost.Move.
in order to emulate move semantics.
</para> </para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para> </para>
</requires> </requires>
</method> </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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="emplace_hint"> <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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="insert"> <method name="insert">
@ -2245,15 +2285,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns> </returns>
<throws> <throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para> <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> </throws>
<notes> <notes>
<para> <para>
When the number of elements is a lot smaller than the number of buckets In older versions this could be inefficient because it had to search
this function can be very inefficient as it has to search through empty through several buckets to find the position of the returned iterator.
buckets for the next element, in order to return the iterator. The data structure has been changed so that this is no longer the case,
The method <methodname>quick_erase</methodname> is faster, but has yet and the alternative erase methods have been deprecated.
to be standardized.
</para> </para>
</notes> </notes>
</method> </method>
@ -2305,13 +2343,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is faster than <methodname>erase</methodname> as This method was implemented because returning an iterator to
it doesn't have to find the next element in the container - the next element from <code>erase</code> was expensive, but
a potentially costly operation. the container has been redesigned so that is no longer the
</para> case. So this method is now deprecated.
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
</para> </para>
</notes> </notes>
</method> </method>
@ -2329,10 +2364,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is now deprecated, use This method was implemented because returning an iterator to
<methodname>quick_return</methodname> instead. Although be the next element from <code>erase</code> was expensive, but
warned that as that isn't standardized yet, it could also the container has been redesigned so that is no longer the
change. case. So this method is now deprecated.
</para> </para>
</notes> </notes>
</method> </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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>
@ -2657,6 +2693,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </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. An unordered associative container that associates keys with another value. The same key can be stored multiple times.
</simpara></purpose> </simpara></purpose>
<description> <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> <para><emphasis role="bold">Template Parameters</emphasis>
<informaltable> <informaltable>
<tgroup cols="2"> <tgroup cols="2">
@ -2907,6 +2942,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<description> <description>
<para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para> <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> </description>
<requires> <requires>
<para><code>value_type</code> is copy constructible</para> <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> <para>The move constructor.</para>
</description> </description>
<notes> <notes>
<para>This is emulated on compilers without rvalue references.</para> <para>This is implemented using Boost.Move.</para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <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> </para>
</requires> </requires>
</constructor> </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> <type>unordered_multimap&amp;</type>
<description> <description>
<para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para> <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> </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> <requires>
<para><code>value_type</code> is copy constructible</para> <para><code>value_type</code> is copy constructible</para>
</requires> </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> <type>unordered_multimap&amp;</type>
<description> <description>
<para>The move assignment operator.</para> <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> </description>
<notes> <notes>
<para> <para>
On compilers without rvalue references, there is a single assignment On compilers without rvalue references, this is emulated using
operator with the signature <code>operator=(unordered_multimap)</code> Boost.Move.
in order to emulate move semantics.
</para> </para>
</notes> </notes>
<requires> <requires>
<para> <para>
<code>value_type</code> is move constructible. <code>value_type</code> is move constructible.
(TODO: This is not actually required in this implementation).
</para> </para>
</requires> </requires>
</method> </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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="emplace_hint"> <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 <para>If the compiler doesn't support variadic template arguments or rvalue
references, this is emulated for up to 10 arguments, with no support references, this is emulated for up to 10 arguments, with no support
for rvalue references or move semantics.</para> 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> </notes>
</method> </method>
<method name="insert"> <method name="insert">
@ -3181,15 +3234,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</returns> </returns>
<throws> <throws>
<para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para> <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> </throws>
<notes> <notes>
<para> <para>
When the number of elements is a lot smaller than the number of buckets In older versions this could be inefficient because it had to search
this function can be very inefficient as it has to search through empty through several buckets to find the position of the returned iterator.
buckets for the next element, in order to return the iterator. The data structure has been changed so that this is no longer the case,
The method <methodname>quick_erase</methodname> is faster, but has yet and the alternative erase methods have been deprecated.
to be standardized.
</para> </para>
</notes> </notes>
</method> </method>
@ -3241,13 +3292,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is faster than <methodname>erase</methodname> as This method was implemented because returning an iterator to
it doesn't have to find the next element in the container - the next element from <code>erase</code> was expensive, but
a potentially costly operation. the container has been redesigned so that is no longer the
</para> case. So this method is now deprecated.
<para>
As it hasn't been standardized, it's likely that this may
change in the future.
</para> </para>
</notes> </notes>
</method> </method>
@ -3265,10 +3313,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</throws> </throws>
<notes> <notes>
<para> <para>
This method is now deprecated, use This method was implemented because returning an iterator to
<methodname>quick_return</methodname> instead. Although be the next element from <code>erase</code> was expensive, but
warned that as that isn't standardized yet, it could also the container has been redesigned so that is no longer the
change. case. So this method is now deprecated.
</para> </para>
</notes> </notes>
</method> </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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>
@ -3558,6 +3607,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</parameter> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> </parameter>
<type>bool</type> <type>bool</type>
<notes> <notes>
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
<para>This is a boost extension.</para> <para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have <para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para> 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> <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> </throws>
<notes> <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 <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> <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
</notes> </notes>

View File

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

View File

@ -19,6 +19,8 @@
#include <boost/detail/select_type.hpp> #include <boost/detail/select_type.hpp>
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/preprocessor/cat.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)) \ #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__) && !defined(__BORLANDC__)
@ -76,13 +78,12 @@ namespace boost { namespace unordered { namespace detail {
template <typename Alloc, typename T> template <typename Alloc, typename T>
struct rebind_wrap struct rebind_wrap
{ {
typedef BOOST_DEDUCED_TYPENAME typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type; type;
}; };
# endif # endif
template <typename T> T& make(); template <typename T> typename boost::add_lvalue_reference<T>::type make();
struct choice9 { typedef char (&type)[9]; }; struct choice9 { typedef char (&type)[9]; };
struct choice8 : choice9 { typedef char (&type)[8]; }; struct choice8 : choice9 { typedef char (&type)[8]; };
struct choice7 : choice8 { typedef char (&type)[7]; }; struct choice7 : choice8 { typedef char (&type)[7]; };
@ -94,13 +95,14 @@ namespace boost { namespace unordered { namespace detail {
struct choice1 : choice2 { typedef char (&type)[1]; }; struct choice1 : choice2 { typedef char (&type)[1]; };
choice1 choose(); 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> \ template <typename Tp, typename Default> \
struct default_type_ ## tname { \ struct default_type_ ## tname { \
\ \
template <typename X> \ template <typename X> \
static choice1::type test(choice1, \ static choice1::type test(choice1, typename X::tname* = 0); \
BOOST_DEDUCED_TYPENAME X::tname* = 0); \
\ \
template <typename X> \ template <typename X> \
static choice2::type test(choice2, void* = 0); \ static choice2::type test(choice2, void* = 0); \
@ -109,24 +111,50 @@ namespace boost { namespace unordered { namespace detail {
\ \
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \ enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\ \
typedef BOOST_DEDUCED_TYPENAME \ typedef typename boost::detail::if_true<value>:: \
boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \ BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \ ::type::tname type; \
} }
#define BOOST_DEFAULT_TYPE(T,tname, arg) \ #else
BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
BOOST_DEFAULT_TYPE_TMPLT(pointer); template <typename T, typename T2>
BOOST_DEFAULT_TYPE_TMPLT(const_pointer); struct sfinae : T2 {};
BOOST_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_DEFAULT_TYPE_TMPLT(const_void_pointer); #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
BOOST_DEFAULT_TYPE_TMPLT(difference_type); template <typename Tp, typename Default> \
BOOST_DEFAULT_TYPE_TMPLT(size_type); struct default_type_ ## tname { \
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment); \
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment); template <typename X> \
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap); 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) #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( \ static BOOST_PP_CAT(choice, result)::type test( \
BOOST_PP_CAT(choice, count)) 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> template <typename T>
struct has_select_on_container_copy_construction BOOST_UNORDERED_HAS_EXPRESSION(
{ select_on_container_copy_construction,
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, make<U const>().select_on_container_copy_construction()); make<U const>().select_on_container_copy_construction()
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); );
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) }; // 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 #else
@ -165,32 +219,43 @@ namespace boost { namespace unordered { namespace detail {
\ \
template <BOOST_PP_CAT(check, count) e> \ template <BOOST_PP_CAT(check, count) e> \
struct BOOST_PP_CAT(test, count) { \ 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 \ template <class U> static typename \
test(BOOST_PP_CAT(choice, count), \ BOOST_PP_CAT(test, count)<&U::name>::type \
typename BOOST_PP_CAT(test, count)< \ test(BOOST_PP_CAT(choice, count))
&U::name>::type = 0)
#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \ #define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
template <class U> static BOOST_PP_CAT(choice, result)::type \ 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> template <typename T>
struct has_select_on_container_copy_construction 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); BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) }; 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 #endif
template <typename Alloc> template <typename Alloc>
inline BOOST_DEDUCED_TYPENAME boost::enable_if< inline typename boost::enable_if<
has_select_on_container_copy_construction<Alloc>, Alloc has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs) >::type call_select_on_container_copy_construction(const Alloc& rhs)
{ {
@ -198,48 +263,62 @@ namespace boost { namespace unordered { namespace detail {
} }
template <typename Alloc> template <typename Alloc>
inline BOOST_DEDUCED_TYPENAME boost::disable_if< inline typename boost::disable_if<
has_select_on_container_copy_construction<Alloc>, Alloc has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs) >::type call_select_on_container_copy_construction(const Alloc& rhs)
{ {
return 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> template <typename Alloc>
struct allocator_traits struct allocator_traits
{ {
typedef Alloc allocator_type; typedef Alloc allocator_type;
typedef typename Alloc::value_type value_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; pointer;
// For now always use the allocator's const_pointer. // For now always use the allocator's const_pointer.
//typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>:: // typename pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const value_type>::other) // BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
// const_pointer; // const_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, value_type const*) typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
const_pointer; value_type const*) const_pointer;
// I'm not using void pointers for now. // 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 pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<void>::other) // BOOST_NESTED_TEMPLATE rebind<void>::other)
// void_pointer; // void_pointer;
//typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer, //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>:: // typename pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const void>::other) // BOOST_NESTED_TEMPLATE rebind<const void>::other)
// const_void_pointer; // const_void_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, difference_type, std::ptrdiff_t) typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
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; size_type;
// TODO: rebind_alloc and rebind_traits // 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. // 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); } // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
static void deallocate(Alloc& a, pointer p, size_type n) static void deallocate(Alloc& a, pointer p, size_type n)
{ a.deallocate(p, n); } { a.deallocate(p, n); }
// Only support the basic copy constructor public:
// template <typename T, typename... Args> // Only supporting the basic copy constructor for now.
// static void construct(Alloc& a, T* p, Args&&... args) {
// DEFAULT_FUNC(construct,void)(a, p, std::forward<Args>(args)...);
// }
template <typename T> 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); a.construct(p, x);
} }
template <typename T> template <typename T>
static void destroy(Alloc& a, T* p) { static void construct(Alloc&, T* p, T const& x, typename
// DEFAULT_FUNC(destroy,void)(a, p); 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); 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) 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 // Allocator propagation on construction
@ -286,13 +382,13 @@ namespace boost { namespace unordered { namespace detail {
// Allocator propagation on assignment and swap. // Allocator propagation on assignment and swap.
// Return true if lhs is modified. // Return true if lhs is modified.
typedef BOOST_DEFAULT_TYPE( typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc, propagate_on_container_copy_assignment, false_type) Alloc, propagate_on_container_copy_assignment, false_type)
propagate_on_container_copy_assignment; propagate_on_container_copy_assignment;
typedef BOOST_DEFAULT_TYPE( typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_move_assignment, false_type) Alloc,propagate_on_container_move_assignment, false_type)
propagate_on_container_move_assignment; propagate_on_container_move_assignment;
typedef BOOST_DEFAULT_TYPE( typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_swap,false_type) Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap; propagate_on_container_swap;
}; };
@ -307,7 +403,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename Allocator> template <typename Allocator>
struct allocator_array_constructor struct allocator_array_constructor
{ {
typedef BOOST_DEDUCED_TYPENAME allocator_traits<Allocator>::pointer typedef typename allocator_traits<Allocator>::pointer
pointer; pointer;
Allocator& alloc_; Allocator& alloc_;

View File

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

View File

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

View File

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

View File

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

View File

@ -15,19 +15,19 @@ namespace boost { namespace unordered { namespace detail {
class unique_table : public T::table_base class unique_table : public T::table_base
{ {
public: public:
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; typedef typename T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; typedef typename T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator; typedef typename T::value_allocator value_allocator;
typedef BOOST_DEDUCED_TYPENAME T::key_type key_type; typedef typename T::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; typedef typename T::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME T::table_base table_base; typedef typename T::table_base table_base;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor; typedef typename T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator; typedef typename T::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME T::node node; typedef typename T::node node;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr; typedef typename T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr; typedef typename T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor; typedef typename T::extractor extractor;
typedef std::pair<node_ptr, bool> emplace_return; typedef std::pair<node_ptr, bool> emplace_return;
@ -60,8 +60,15 @@ namespace boost { namespace unordered { namespace detail {
n1; n1 = n1->next_) n1; n1 = n1->next_)
{ {
node_ptr n2 = other.find_matching_node(n1); node_ptr n2 = other.find_matching_node(n1);
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if(!n2 || node::get_value(n1) != node::get_value(n2)) if(!n2 || node::get_value(n1) != node::get_value(n2))
return false; return false;
#else
if(!n2 || !extractor::compare_mapped(
node::get_value(n1), node::get_value(n2)))
return false;
#endif
} }
return true; return true;
@ -111,7 +118,7 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k) 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 hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_; 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) #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> template<class... Args>
@ -392,10 +407,10 @@ namespace boost { namespace unordered { namespace detail {
template <class H, class P, class A> template <class H, class P, class A>
struct set : public types< struct set : public types<
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, typename allocator_traits<A>::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, typename allocator_traits<A>::value_type,
H, P, A, H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>, set_extractor<typename allocator_traits<A>::value_type>,
true> true>
{ {
typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl; 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> template <class K, class H, class P, class A>
struct map : public types< struct map : public types<
K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, K, typename allocator_traits<A>::value_type,
H, P, A, H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>, map_extractor<K, typename allocator_traits<A>::value_type>,
true> true>
{ {
typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl; 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/alignment_of.hpp>
#include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_empty.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/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/move/move.hpp>
#include <boost/swap.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: // Template parameters:
// //
@ -121,6 +131,36 @@ namespace boost { namespace unordered { namespace detail {
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
#pragma warning(pop) #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 #endif
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -197,22 +237,6 @@ namespace boost { namespace unordered { namespace detail {
return *bound; 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 // insert_size/initial_size
@ -242,9 +266,8 @@ namespace boost { namespace unordered { namespace detail {
template <class I> template <class I>
inline std::size_t insert_size(I i, I j) inline std::size_t insert_size(I i, I j)
{ {
BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type return insert_size(i, j,
iterator_traversal_tag; typename ::boost::iterator_traversal<I>::type());
return insert_size(i, j, iterator_traversal_tag);
} }
template <class I> template <class I>
@ -295,8 +318,8 @@ namespace boost { namespace unordered { namespace detail {
: private generate_base<T1, 1>::type, : private generate_base<T1, 1>::type,
private generate_base<T2, 2>::type private generate_base<T2, 2>::type
{ {
typedef BOOST_DEDUCED_TYPENAME generate_base<T1, 1>::type base1; typedef typename generate_base<T1, 1>::type base1;
typedef BOOST_DEDUCED_TYPENAME generate_base<T2, 2>::type base2; typedef typename generate_base<T2, 2>::type base2;
typedef T1 first_type; typedef T1 first_type;
typedef T2 second_type; typedef T2 second_type;

View File

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

View File

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

View File

@ -23,6 +23,7 @@ test-suite unordered
[ run fwd_set_test.cpp ] [ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ] [ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ] [ run allocator_traits.cpp ]
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ] [ run compile_set.cpp ]
[ run compile_map.cpp ] [ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ] [ run link_test_1.cpp link_test_2.cpp ]
@ -34,6 +35,9 @@ test-suite unordered
[ run move_tests.cpp ] [ run move_tests.cpp ]
[ run assign_tests.cpp ] [ run assign_tests.cpp ]
[ run insert_tests.cpp ] [ run insert_tests.cpp ]
[ run insert_tests.cpp : :
: <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
: insert_deprecated ]
[ run insert_stable_tests.cpp ] [ run insert_stable_tests.cpp ]
[ run unnecessary_copy_tests.cpp ] [ run unnecessary_copy_tests.cpp ]
[ run erase_tests.cpp ] [ run erase_tests.cpp ]
@ -44,5 +48,6 @@ test-suite unordered
[ run load_factor_tests.cpp ] [ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ] [ run rehash_tests.cpp ]
[ run equality_tests.cpp ] [ run equality_tests.cpp ]
[ run equality_deprecated.cpp ]
[ run swap_tests.cpp ] [ run swap_tests.cpp ]
; ;

View File

@ -16,7 +16,7 @@
#include "./compile_tests.hpp" #include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors // Explicit instantiation to catch compile-time errors
/*
template class boost::unordered_set< template class boost::unordered_set<
int, int,
boost::hash<int>, boost::hash<int>,
@ -27,7 +27,7 @@ template class boost::unordered_multiset<
boost::hash<int>, boost::hash<int>,
std::equal_to<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
*/
template class boost::unordered_set< template class boost::unordered_set<
test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<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) UNORDERED_AUTO_TEST(map_emplace_test)
{ {
boost::unordered_map<int, overloaded_constructor> x; boost::unordered_map<int, overloaded_constructor> x;
@ -547,14 +545,15 @@ UNORDERED_AUTO_TEST(map_emplace_test)
BOOST_TEST(x.find(0) != x.end() && BOOST_TEST(x.find(0) != x.end() &&
x.find(0)->second == overloaded_constructor()); 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); x.emplace(2, 3);
BOOST_TEST(x.find(2) != x.end() && BOOST_TEST(x.find(2) != x.end() &&
x.find(2)->second == overloaded_constructor(3)); 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); x.emplace(4, 5, 6);
BOOST_TEST(x.find(4) != x.end() && BOOST_TEST(x.find(4) != x.end() &&
x.find(4)->second == overloaded_constructor(5, 6)); x.find(4)->second == overloaded_constructor(5, 6));
@ -562,6 +561,7 @@ UNORDERED_AUTO_TEST(map_emplace_test)
x.emplace(7, 8, 9, 10); x.emplace(7, 8, 9, 10);
BOOST_TEST(x.find(7) != x.end() && BOOST_TEST(x.find(7) != x.end() &&
x.find(7)->second == overloaded_constructor(8, 9, 10)); x.find(7)->second == overloaded_constructor(8, 9, 10));
#endif
} }
UNORDERED_AUTO_TEST(set_emplace_test) 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); 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() 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. // Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // 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(); x.emplace();
COPY_COUNT(2); MOVE_COUNT(0); 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 // 1 argument
// //
@ -345,19 +352,23 @@ namespace unnecessary_copy_tests
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \ (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \ (defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
(!defined(__GNUC__) && !defined(BOOST_MSVC)) (!defined(__GNUC__) && !defined(BOOST_MSVC))
count_copies part; count_copies part;
reset(); reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part); std::pair<count_copies const&, count_copies const&> a_ref(part, part);
x.emplace(a_ref); x.emplace(a_ref);
COPY_COUNT(2); MOVE_COUNT(0); COPY_COUNT(2); MOVE_COUNT(0);
#endif #endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE) #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
// No move should take place. // No move should take place.
// (since a is already in the container) // (since a is already in the container)
reset(); reset();
x.emplace(std::move(a)); x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0); COPY_COUNT(0); MOVE_COUNT(0);
#endif #endif
// //
@ -382,6 +393,47 @@ namespace unnecessary_copy_tests
reset(); reset();
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_)); x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
COPY_COUNT(2); MOVE_COUNT(0); 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
} }
} }