forked from boostorg/unordered
Compare commits
11 Commits
boost-1.52
...
svn-releas
Author | SHA1 | Date | |
---|---|---|---|
bea92e8842 | |||
6ca8d5e0d9 | |||
9b9a1d21a6 | |||
a7c0ddb5b3 | |||
c88126e1d2 | |||
0c7c7cc6ad | |||
bd10a8b5aa | |||
0221f1a9bd | |||
34b69e67ee | |||
654fed166a | |||
981f1e2acb |
@ -220,4 +220,24 @@ C++11 support has resulted in some breaking changes:
|
||||
for C++11 allocators.
|
||||
* Simplified the implementation a bit. Hopefully more robust.
|
||||
|
||||
[h2 Boost 1.53.0]
|
||||
|
||||
* Remove support for the old pre-standard variadic pair constructors, and
|
||||
equality implementation. Both have been deprecated since Boost 1.48.
|
||||
* Remove use of deprecated config macros.
|
||||
* More internal implementation changes, including a much simpler
|
||||
implementation of `erase`.
|
||||
|
||||
[h2 Boost 1.54.0]
|
||||
|
||||
* Mark methods specified in standard as `noexpect`. More to come in the next
|
||||
release.
|
||||
* If the hash function and equality predicate are known to both have nothrow
|
||||
move assignment or construction then use them.
|
||||
|
||||
[h2 Boost 1.55.0]
|
||||
|
||||
* Avoid some warnings ([ticket 8851], [ticket 8874]).
|
||||
* Avoid exposing some detail functions via. ADL on the iterators.
|
||||
|
||||
[endsect]
|
||||
|
@ -8,11 +8,12 @@
|
||||
|
||||
Support for move semantics is implemented using Boost.Move. If rvalue
|
||||
references are available it will use them, but if not it uses a close,
|
||||
but imperfect emulation. On such compilers you'll need to use Boost.Move
|
||||
to take advantage of using movable container elements, also note that:
|
||||
but imperfect emulation. On such compilers:
|
||||
|
||||
* Non-copyable objects can be stored in the containers, but without support
|
||||
for rvalue references the container will not be movable.
|
||||
* Non-copyable objects can be stored in the containers.
|
||||
They can be constructed in place using `emplace`, or if they support
|
||||
Boost.Move, moved into place.
|
||||
* The containers themselves are not movable.
|
||||
* Argument forwarding is not perfect.
|
||||
|
||||
[endsect]
|
||||
|
@ -3,7 +3,7 @@
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[def __wang__
|
||||
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
Thomas Wang's article on integer hash functions]]
|
||||
|
||||
[section:rationale Implementation Rationale]
|
||||
@ -85,7 +85,8 @@ of 2.
|
||||
|
||||
Using a prime number of buckets, and choosing a bucket by using the modulus
|
||||
of the hash function's result will usually give a good result. The downside
|
||||
is that the required modulus operation is fairly expensive.
|
||||
is that the required modulus operation is fairly expensive. This is what the
|
||||
containers do in most cases.
|
||||
|
||||
Using a power of 2 allows for much quicker selection of the bucket
|
||||
to use, but at the expense of loosing the upper bits of the hash value.
|
||||
@ -95,12 +96,16 @@ functions this can't be relied on.
|
||||
|
||||
To avoid this a transformation could be applied to the hash function, for an
|
||||
example see __wang__. Unfortunately, a transformation like Wang's requires
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough.
|
||||
This leaves more expensive methods, such as Knuth's Multiplicative Method
|
||||
(mentioned in Wang's article). These don't tend to work as well as taking the
|
||||
modulus of a prime, and the extra computation required might negate
|
||||
efficiency advantage of power of 2 hash tables.
|
||||
knowledge of the number of bits in the hash value, so it isn't portable enough
|
||||
to use as a default. It can applicable in certain cases so the containers
|
||||
have a policy based implementation that can use this alternative technique.
|
||||
|
||||
So, this implementation uses a prime number for the hash table size.
|
||||
Currently this is only done on 64 bit architecures, where prime number
|
||||
modulus can be expensive. Although this varies depending on the architecture,
|
||||
so I probably should revisit it.
|
||||
|
||||
I'm also thinking of introducing a mechanism whereby a hash function can
|
||||
indicate that it's safe to be used directly with power of 2 buckets, in
|
||||
which case a faster plain power of 2 implementation can be used.
|
||||
|
||||
[endsect]
|
||||
|
16
doc/ref.php
16
doc/ref.php
@ -449,10 +449,6 @@ EOL;
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -499,10 +495,6 @@ EOL;
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -1114,9 +1106,7 @@ EOL;
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1157,9 +1147,7 @@ EOL;
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
|
64
doc/ref.xml
64
doc/ref.xml
@ -383,10 +383,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -426,10 +422,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -970,9 +962,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1005,9 +995,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1429,10 +1417,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -1472,10 +1456,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -2014,9 +1994,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -2049,9 +2027,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -2488,10 +2464,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -2531,10 +2503,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -3108,9 +3076,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -3145,9 +3111,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -3581,10 +3545,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -3624,10 +3584,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
|
||||
</notes>
|
||||
</method>
|
||||
<method name="insert">
|
||||
@ -4168,9 +4124,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -4205,9 +4159,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</description>
|
||||
<notes>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
the C++11 standard in Boost 1.48.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
|
@ -85,7 +85,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Either forwarding variadic arguments, or storing the arguments in
|
||||
// emplace_args##n
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
|
||||
@ -136,7 +136,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
|
||||
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
|
||||
@ -234,9 +234,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
namespace func {
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
@ -257,13 +259,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename T, unsigned int> struct expr_test;
|
||||
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
||||
template <typename U> static char for_expr_test(U const&);
|
||||
|
||||
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
|
||||
template <typename U> \
|
||||
static typename boost::unordered::detail::expr_test< \
|
||||
BOOST_PP_CAT(choice, result), \
|
||||
sizeof(boost::unordered::detail::for_expr_test(( \
|
||||
sizeof(for_expr_test(( \
|
||||
(expression), \
|
||||
0)))>::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
@ -276,6 +277,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
|
||||
struct BOOST_PP_CAT(has_, name) \
|
||||
{ \
|
||||
template <typename U> static char for_expr_test(U const&); \
|
||||
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
|
||||
boost::unordered::detail::make< thing >().name args); \
|
||||
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
|
||||
@ -342,7 +344,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# endif
|
||||
|
||||
# if !defined(BOOST_NO_VARIADIC_TEMPLATES) && \
|
||||
# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
!defined(BOOST_NO_SFINAE_EXPR)
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||
# else
|
||||
@ -432,7 +434,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
max_size, U const, (), 0
|
||||
);
|
||||
|
||||
# if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename T, typename ValueType, typename... Args>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
@ -473,6 +475,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
# endif
|
||||
|
||||
namespace func
|
||||
{
|
||||
|
||||
template <typename Alloc>
|
||||
inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
|
||||
typename boost::enable_if_c<
|
||||
@ -510,6 +515,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return (std::numeric_limits<SizeType>::max)();
|
||||
}
|
||||
|
||||
} // namespace func.
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits
|
||||
{
|
||||
@ -589,7 +596,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
boost::unordered::detail::func::destroy(p);
|
||||
}
|
||||
|
||||
# elif !defined(BOOST_NO_SFINAE_EXPR)
|
||||
@ -623,7 +630,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
boost::unordered::detail::func::destroy(p);
|
||||
}
|
||||
|
||||
# else
|
||||
@ -669,21 +676,22 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::is_same<T, value_type>::value,
|
||||
void*>::type = 0)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
boost::unordered::detail::func::destroy(p);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
static size_type max_size(const Alloc& a)
|
||||
{
|
||||
return boost::unordered::detail::call_max_size<size_type>(a);
|
||||
return boost::unordered::detail::func::
|
||||
call_max_size<size_type>(a);
|
||||
}
|
||||
|
||||
// Allocator propagation on construction
|
||||
|
||||
static Alloc select_on_container_copy_construction(Alloc const& rhs)
|
||||
{
|
||||
return boost::unordered::detail::
|
||||
return boost::unordered::detail::func::
|
||||
call_select_on_container_copy_construction(rhs);
|
||||
}
|
||||
|
||||
@ -758,12 +766,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
namespace boost { namespace unordered { namespace detail { namespace func {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// call_construct
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
|
||||
@ -792,7 +800,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_value_impl(Alloc&, T* x) {
|
||||
boost::unordered::detail::destroy(x);
|
||||
boost::unordered::detail::func::destroy(x);
|
||||
}
|
||||
|
||||
|
||||
@ -802,7 +810,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_value_impl(Alloc&, T* x) {
|
||||
boost::unordered::detail::destroy(x);
|
||||
boost::unordered::detail::func::destroy(x);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -812,13 +820,13 @@ namespace boost { namespace unordered { namespace detail {
|
||||
//
|
||||
// Used for piecewise construction.
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
template<typename Alloc, typename T> \
|
||||
void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
|
||||
{ \
|
||||
boost::unordered::detail::call_construct(alloc, ptr); \
|
||||
boost::unordered::detail::func::call_construct(alloc, ptr); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT_FROM_TO(1, n, \
|
||||
@ -830,7 +838,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void construct_from_tuple(Alloc& alloc, T* ptr, \
|
||||
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
{ \
|
||||
boost::unordered::detail::call_construct(alloc, ptr, \
|
||||
boost::unordered::detail::func::call_construct(alloc, ptr, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
|
||||
); \
|
||||
}
|
||||
@ -921,146 +929,58 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SFINAE traits for construction.
|
||||
// Trait to check for piecewise construction.
|
||||
|
||||
// Decide which construction method to use for a three argument
|
||||
// call. Note that this is difficult to do using overloads because
|
||||
// the arguments are packed into 'emplace_args3'.
|
||||
//
|
||||
// The decision is made on the first argument.
|
||||
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
template <typename A, typename B, typename A0>
|
||||
struct emulation1 {
|
||||
static choice1::type test(choice1, std::pair<A, B> const&);
|
||||
static choice2::type test(choice2, A const&);
|
||||
static choice3::type test(choice3, convert_from_anything const&);
|
||||
|
||||
enum { value =
|
||||
sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
|
||||
sizeof(choice2::type) };
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
struct check3_base {
|
||||
template <typename A0>
|
||||
struct use_piecewise {
|
||||
static choice1::type test(choice1,
|
||||
boost::unordered::piecewise_construct_t);
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
static choice2::type test(choice2, A const&);
|
||||
#endif
|
||||
static choice2::type test(choice2, ...);
|
||||
|
||||
static choice3::type test(choice3, ...);
|
||||
|
||||
enum { value =
|
||||
enum { value = sizeof(choice1::type) ==
|
||||
sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename A0>
|
||||
struct piecewise3 {
|
||||
enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
|
||||
};
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
template <typename A, typename B, typename A0>
|
||||
struct emulation3 {
|
||||
enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: Full construct?
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from variadic parameters
|
||||
|
||||
// For the standard pair constructor.
|
||||
|
||||
template <typename Alloc, typename T, typename... Args>
|
||||
inline void construct_value_impl(Alloc& alloc, T* address,
|
||||
BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::unordered::detail::func::call_construct(alloc,
|
||||
address, boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Special case for piece_construct
|
||||
//
|
||||
// TODO: When possible, it might be better to use std::pair's
|
||||
// constructor for std::piece_construct with std::tuple.
|
||||
|
||||
template <typename Alloc, typename A, typename B,
|
||||
typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<piecewise3<A, B, A0>, void>::type
|
||||
inline typename enable_if<use_piecewise<A0>, void>::type
|
||||
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
|
||||
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
boost::unordered::detail::construct_from_tuple(alloc,
|
||||
boost::unordered::detail::func::construct_from_tuple(alloc,
|
||||
boost::addressof(address->first), boost::forward<A1>(a1));
|
||||
boost::unordered::detail::construct_from_tuple(alloc,
|
||||
boost::unordered::detail::func::construct_from_tuple(alloc,
|
||||
boost::addressof(address->second), boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
|
||||
template <typename Alloc, typename A, typename B, typename A0>
|
||||
inline typename enable_if<emulation1<A, B, A0>, void>::type
|
||||
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
|
||||
BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->first),boost::forward<A0>(a0));
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->second));
|
||||
}
|
||||
|
||||
template <typename Alloc, typename A, typename B,
|
||||
typename A0, typename A1, typename A2>
|
||||
inline typename enable_if<emulation3<A, B, A0>, void>::type
|
||||
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
|
||||
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->first),boost::forward<A0>(a0));
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->second),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
template <typename Alloc, typename A, typename B,
|
||||
typename A0, typename A1, typename A2, typename A3,
|
||||
typename... Args>
|
||||
inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
|
||||
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2,
|
||||
BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->first),boost::forward<A0>(a0));
|
||||
boost::unordered::detail::call_construct(alloc,
|
||||
boost::addressof(address->second),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2),
|
||||
boost::forward<A3>(a3),
|
||||
boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#else // BOOST_NO_VARIADIC_TEMPLATES
|
||||
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from emplace_args
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
typename Alloc, typename T, \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
|
||||
> \
|
||||
inline void construct_value_impl(Alloc&, T* address, \
|
||||
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
|
||||
> const& args) \
|
||||
{ \
|
||||
new((void*) address) T( \
|
||||
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
args.a)); \
|
||||
}
|
||||
// Explicitly write out first three overloads for the sake of sane
|
||||
// error messages.
|
||||
|
||||
template <typename Alloc, typename T, typename A0>
|
||||
inline void construct_value_impl(Alloc&, T* address,
|
||||
@ -1090,82 +1010,45 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
);
|
||||
}
|
||||
|
||||
// Use a macro for the rest.
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
typename Alloc, typename T, \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
|
||||
> \
|
||||
inline void construct_value_impl(Alloc&, T* address, \
|
||||
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
|
||||
> const& args) \
|
||||
{ \
|
||||
new((void*) address) T( \
|
||||
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
args.a)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
|
||||
// Construct with piece_construct
|
||||
|
||||
template <typename Alloc, typename A, typename B,
|
||||
typename A0, typename A1, typename A2>
|
||||
inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
|
||||
typename enable_if<piecewise3<A, B, A0>, void*>::type = 0)
|
||||
typename enable_if<use_piecewise<A0>, void*>::type = 0)
|
||||
{
|
||||
boost::unordered::detail::construct_from_tuple(alloc,
|
||||
boost::unordered::detail::func::construct_from_tuple(alloc,
|
||||
boost::addressof(address->first), args.a1);
|
||||
boost::unordered::detail::construct_from_tuple(alloc,
|
||||
boost::unordered::detail::func::construct_from_tuple(alloc,
|
||||
boost::addressof(address->second), args.a2);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
template <typename Alloc, typename A, typename B, typename A0>
|
||||
inline void construct_value_impl(Alloc&, std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args1<A0> const& args,
|
||||
typename enable_if<emulation1<A, B, A0>, void*>::type = 0)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(
|
||||
boost::forward<A0>(args.a0));
|
||||
new((void*) boost::addressof(address->second)) B();
|
||||
}
|
||||
|
||||
template <typename Alloc, typename A, typename B,
|
||||
typename A0, typename A1, typename A2>
|
||||
inline void construct_value_impl(Alloc&, std::pair<A, B>* address,
|
||||
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
|
||||
typename enable_if<emulation3<A, B, A0>, void*>::type = 0)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(
|
||||
boost::forward<A0>(args.a0));
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
boost::forward<A1>(args.a1),
|
||||
boost::forward<A2>(args.a2));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
|
||||
template <typename Alloc, typename A, typename B, \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
|
||||
> \
|
||||
inline void construct_value_impl(Alloc&, std::pair<A, B>* address, \
|
||||
boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
|
||||
> const& args) \
|
||||
{ \
|
||||
new((void*) boost::addressof(address->first)) A( \
|
||||
boost::forward<A0>(args.a0)); \
|
||||
new((void*) boost::addressof(address->second)) B( \
|
||||
BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params), \
|
||||
BOOST_UNORDERED_CALL_FORWARD2, args.a)); \
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
|
||||
BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
|
||||
|
||||
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
|
||||
#undef BOOST_UNORDERED_CALL_FORWARD2
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#endif // BOOST_NO_VARIADIC_TEMPLATES
|
||||
|
||||
}}}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some helper functions for allocating & constructing
|
||||
}}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <boost/unordered/detail/allocate.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
@ -30,6 +32,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
}}}
|
||||
|
||||
// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
|
||||
// in the detail namespace. It didn't work because the template parameters
|
||||
// were in detail. I'm not changing it at the moment to be safe. I might
|
||||
// do in the future if I change the iterator types.
|
||||
namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -37,49 +43,50 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename NodePointer, typename Value> struct iterator;
|
||||
template <typename ConstNodePointer, typename NodePointer,
|
||||
typename Value> struct c_iterator;
|
||||
template <typename NodePointer, typename Value, typename Policy>
|
||||
struct l_iterator;
|
||||
template <typename ConstNodePointer, typename NodePointer,
|
||||
typename Value, typename Policy> struct cl_iterator;
|
||||
template <typename Node> struct iterator;
|
||||
template <typename Node, typename ConstNodePointer> struct c_iterator;
|
||||
template <typename Node, typename Policy> struct l_iterator;
|
||||
template <typename Node, typename ConstNodePointer, typename Policy>
|
||||
struct cl_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename NodePointer, typename Value, typename Policy>
|
||||
template <typename Node, typename Policy>
|
||||
struct l_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
typename Node::node_pointer,
|
||||
typename Node::value_type&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename ConstNodePointer, typename NodePointer2,
|
||||
typename Value2, typename Policy2>
|
||||
template <typename Node2, typename ConstNodePointer, typename Policy2>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
private:
|
||||
#endif
|
||||
typedef NodePointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
|
||||
iterator;
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
l_iterator() : ptr_() {}
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
l_iterator(iterator x, std::size_t b, std::size_t c)
|
||||
l_iterator() BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
|
||||
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
Value& operator*() const {
|
||||
value_type& operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
value_type* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
@ -97,51 +104,53 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(l_iterator x) const {
|
||||
bool operator==(l_iterator x) const BOOST_NOEXCEPT {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
|
||||
bool operator!=(l_iterator x) const {
|
||||
bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value,
|
||||
typename Policy>
|
||||
template <typename Node, typename ConstNodePointer, typename Policy>
|
||||
struct cl_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
ConstNodePointer,
|
||||
typename Node::value_type const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::l_iterator
|
||||
<NodePointer, Value, Policy>;
|
||||
<Node, Policy>;
|
||||
private:
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
|
||||
iterator;
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
cl_iterator() : ptr_() {}
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
cl_iterator(iterator x, std::size_t b, std::size_t c) :
|
||||
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
|
||||
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
cl_iterator(boost::unordered::iterator_detail::l_iterator<
|
||||
NodePointer, Value, Policy> const& x) :
|
||||
Node, Policy> const& x) BOOST_NOEXCEPT :
|
||||
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
|
||||
{}
|
||||
|
||||
Value const&
|
||||
operator*() const {
|
||||
value_type const& operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
value_type const* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
@ -159,27 +168,34 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
|
||||
friend bool operator==(cl_iterator const& x, cl_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.ptr_ == y.ptr_;
|
||||
}
|
||||
|
||||
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
|
||||
friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.ptr_ != y.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodePointer, typename Value>
|
||||
template <typename Node>
|
||||
struct iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
typename Node::node_pointer,
|
||||
typename Node::value_type&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename, typename, typename>
|
||||
template <typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::c_iterator;
|
||||
template <typename, typename, typename>
|
||||
template <typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::l_iterator;
|
||||
template <typename, typename, typename, typename>
|
||||
template <typename, typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::table;
|
||||
@ -189,20 +205,23 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
friend struct boost::unordered::detail::grouped_table_impl;
|
||||
private:
|
||||
#endif
|
||||
typedef NodePointer node_pointer;
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
iterator() : node_() {}
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
explicit iterator(node_pointer const& x) : node_(x) {}
|
||||
iterator() BOOST_NOEXCEPT : node_() {}
|
||||
|
||||
Value& operator*() const {
|
||||
explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
|
||||
node_(static_cast<node_pointer>(x)) {}
|
||||
|
||||
value_type& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
value_type* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
@ -217,23 +236,25 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(iterator const& x) const {
|
||||
bool operator==(iterator const& x) const BOOST_NOEXCEPT {
|
||||
return node_ == x.node_;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const& x) const {
|
||||
bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
|
||||
return node_ != x.node_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value>
|
||||
template <typename Node, typename ConstNodePointer>
|
||||
struct c_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
std::forward_iterator_tag,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
ConstNodePointer,
|
||||
typename Node::value_type const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value>;
|
||||
friend struct boost::unordered::iterator_detail::iterator<Node>;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename>
|
||||
@ -245,26 +266,26 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
private:
|
||||
#endif
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
|
||||
iterator;
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
c_iterator() : node_() {}
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
explicit c_iterator(node_pointer const& x) : node_(x) {}
|
||||
c_iterator() BOOST_NOEXCEPT : node_() {}
|
||||
|
||||
c_iterator(boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value> const& x) : node_(x.node_) {}
|
||||
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
|
||||
node_(static_cast<node_pointer>(x)) {}
|
||||
|
||||
Value const& operator*() const {
|
||||
c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
|
||||
|
||||
value_type const& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
value_type const* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
@ -279,11 +300,15 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(c_iterator const& x, c_iterator const& y) {
|
||||
friend bool operator==(c_iterator const& x, c_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.node_ == y.node_;
|
||||
}
|
||||
|
||||
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
|
||||
friend bool operator!=(c_iterator const& x, c_iterator const& y)
|
||||
BOOST_NOEXCEPT
|
||||
{
|
||||
return x.node_ != y.node_;
|
||||
}
|
||||
};
|
||||
@ -310,9 +335,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
protected:
|
||||
|
||||
node_allocator& alloc_;
|
||||
|
||||
private:
|
||||
|
||||
node_pointer node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
@ -335,7 +357,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::construct_value_impl(
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
@ -344,7 +366,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void construct_with_value2(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::construct_value_impl(
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(),
|
||||
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
|
||||
value_constructed_ = true;
|
||||
@ -374,7 +396,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
boost::unordered::detail::destroy_value_impl(alloc_,
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
}
|
||||
|
||||
@ -398,7 +420,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_allocator_traits::construct(alloc_,
|
||||
boost::addressof(*node_), node());
|
||||
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||
node_->init(node_);
|
||||
node_constructed_ = true;
|
||||
}
|
||||
else {
|
||||
@ -406,7 +428,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
if (value_constructed_)
|
||||
{
|
||||
boost::unordered::detail::destroy_value_impl(alloc_,
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
@ -432,8 +454,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
typedef typename node::value_type value_type;
|
||||
typedef typename node::link_pointer link_pointer;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node_pointer, value_type> iterator;
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
|
||||
node_pointer nodes_;
|
||||
|
||||
@ -445,7 +466,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
nodes_()
|
||||
{
|
||||
if (b.size_) {
|
||||
typename Table::previous_pointer prev = b.get_previous_start();
|
||||
typename Table::link_pointer prev = b.get_previous_start();
|
||||
nodes_ = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = link_pointer();
|
||||
b.size_ = 0;
|
||||
@ -454,60 +475,61 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
~node_holder();
|
||||
|
||||
void node_for_assignment()
|
||||
{
|
||||
if (!this->node_ && nodes_) {
|
||||
this->node_ = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
this->node_->init(this->node_);
|
||||
this->node_->next_ = link_pointer();
|
||||
|
||||
this->node_constructed_ = true;
|
||||
this->value_constructed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void assign_impl(T const& v) {
|
||||
nodes_->value() = v;
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = v;
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void assign_impl(std::pair<T1 const, T2> const& v) {
|
||||
const_cast<T1&>(nodes_->value().first) = v.first;
|
||||
nodes_->value().second = v.second;
|
||||
this->construct_with_value2(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_assign_impl(T& v) {
|
||||
nodes_->value() = boost::move(v);
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = boost::move(v);
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
|
||||
// TODO: Move key as well?
|
||||
const_cast<T1&>(nodes_->value().first) =
|
||||
boost::move(const_cast<T1&>(v.first));
|
||||
nodes_->value().second = boost::move(v.second);
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
|
||||
node_pointer copy_of(value_type const& v)
|
||||
{
|
||||
if (nodes_) {
|
||||
assign_impl(v);
|
||||
node_pointer p = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(p->next_);
|
||||
p->init(static_cast<typename node::link_pointer>(p));
|
||||
p->next_ = link_pointer();
|
||||
return p;
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(v);
|
||||
return base::release();
|
||||
}
|
||||
node_for_assignment();
|
||||
assign_impl(v);
|
||||
return base::release();
|
||||
}
|
||||
|
||||
node_pointer move_copy_of(value_type& v)
|
||||
{
|
||||
if (nodes_) {
|
||||
move_assign_impl(v);
|
||||
node_pointer p = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(p->next_);
|
||||
p->init(static_cast<typename node::link_pointer>(p));
|
||||
p->next_ = link_pointer();
|
||||
return p;
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
return base::release();
|
||||
}
|
||||
node_for_assignment();
|
||||
move_assign_impl(v);
|
||||
return base::release();
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
@ -523,7 +545,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer p = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(p->next_);
|
||||
|
||||
boost::unordered::detail::destroy_value_impl(this->alloc_,
|
||||
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
|
||||
p->value_ptr());
|
||||
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
|
||||
node_allocator_traits::deallocate(this->alloc_, p, 1);
|
||||
@ -537,12 +559,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename NodePointer>
|
||||
struct bucket
|
||||
{
|
||||
typedef NodePointer previous_pointer;
|
||||
previous_pointer next_;
|
||||
typedef NodePointer link_pointer;
|
||||
link_pointer next_;
|
||||
|
||||
bucket() : next_() {}
|
||||
|
||||
previous_pointer first_from_start()
|
||||
link_pointer first_from_start()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
@ -552,12 +574,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
struct ptr_bucket
|
||||
{
|
||||
typedef ptr_bucket* previous_pointer;
|
||||
previous_pointer next_;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
link_pointer next_;
|
||||
|
||||
ptr_bucket() : next_(0) {}
|
||||
|
||||
previous_pointer first_from_start()
|
||||
link_pointer first_from_start()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@ -568,8 +590,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hash Policy
|
||||
//
|
||||
// Don't really want table to derive from this, but will for now.
|
||||
|
||||
template <typename SizeT>
|
||||
struct prime_policy
|
||||
@ -664,12 +684,23 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// atomically assigns the new function objects in a strongly
|
||||
// exception safe manner.
|
||||
|
||||
template <class H, class P> class set_hash_functions;
|
||||
template <class H, class P, bool NoThrowMoveAssign>
|
||||
class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
class functions
|
||||
{
|
||||
friend class boost::unordered::detail::set_hash_functions<H, P>;
|
||||
public:
|
||||
static const bool nothrow_move_assignable =
|
||||
boost::is_nothrow_move_assignable<H>::value &&
|
||||
boost::is_nothrow_move_assignable<P>::value;
|
||||
static const bool nothrow_move_constructible =
|
||||
boost::is_nothrow_move_constructible<H>::value &&
|
||||
boost::is_nothrow_move_constructible<P>::value;
|
||||
|
||||
private:
|
||||
friend class boost::unordered::detail::set_hash_functions<H, P,
|
||||
nothrow_move_assignable>;
|
||||
functions& operator=(functions const&);
|
||||
|
||||
typedef compressed<H, P> function_pair;
|
||||
@ -686,23 +717,40 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static_cast<void const*>(&funcs_[current_]));
|
||||
}
|
||||
|
||||
function_pair& current() {
|
||||
return *static_cast<function_pair*>(
|
||||
static_cast<void*>(&funcs_[current_]));
|
||||
}
|
||||
|
||||
void construct(bool which, H const& hf, P const& eq)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(hf, eq);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair const& f)
|
||||
void construct(bool which, function_pair const& f,
|
||||
boost::unordered::detail::false_type =
|
||||
boost::unordered::detail::false_type())
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair& f,
|
||||
boost::unordered::detail::true_type)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f,
|
||||
boost::unordered::detail::move_tag());
|
||||
}
|
||||
|
||||
void destroy(bool which)
|
||||
{
|
||||
boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
|
||||
boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef boost::unordered::detail::set_hash_functions<H, P,
|
||||
nothrow_move_assignable> set_hash_functions;
|
||||
|
||||
functions(H const& hf, P const& eq)
|
||||
: current_(false)
|
||||
{
|
||||
@ -715,6 +763,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
construct(current_, bf.current());
|
||||
}
|
||||
|
||||
functions(functions& bf, boost::unordered::detail::move_tag)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current(),
|
||||
boost::unordered::detail::integral_constant<bool,
|
||||
nothrow_move_constructible>());
|
||||
}
|
||||
|
||||
~functions() {
|
||||
this->destroy(current_);
|
||||
}
|
||||
@ -727,26 +783,28 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return current().second();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions
|
||||
class set_hash_functions<H, P, false>
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef functions<H, P> functions_type;
|
||||
|
||||
functions<H,P>& functions_;
|
||||
functions_type& functions_;
|
||||
bool tmp_functions_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(functions<H,P>& f, H const& h, P const& p)
|
||||
set_hash_functions(functions_type& f, H const& h, P const& p)
|
||||
: functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, h, p);
|
||||
}
|
||||
|
||||
set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
|
||||
set_hash_functions(functions_type& f, functions_type const& other)
|
||||
: functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
@ -765,11 +823,42 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions<H, P, true>
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef functions<H, P> functions_type;
|
||||
|
||||
functions_type& functions_;
|
||||
H hash_;
|
||||
P pred_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(functions_type& f, H const& h, P const& p) :
|
||||
functions_(f),
|
||||
hash_(h),
|
||||
pred_(p) {}
|
||||
|
||||
set_hash_functions(functions_type& f, functions_type const& other) :
|
||||
functions_(f),
|
||||
hash_(other.hash_function()),
|
||||
pred_(other.key_eq()) {}
|
||||
|
||||
void commit()
|
||||
{
|
||||
functions_.current().first() = boost::move(hash_);
|
||||
functions_.current().second() = boost::move(pred_);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
|
||||
// e.g. for int
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
|
||||
#else
|
||||
struct please_ignore_this_overload {
|
||||
|
@ -25,10 +25,13 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::value_base<T>
|
||||
{
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, grouped_node<A, T> >::type::pointer link_pointer;
|
||||
A, grouped_node<A, T> >::type allocator;
|
||||
typedef typename ::boost::unordered::detail::
|
||||
allocator_traits<allocator>::pointer node_pointer;
|
||||
typedef node_pointer link_pointer;
|
||||
|
||||
link_pointer next_;
|
||||
link_pointer group_prev_;
|
||||
node_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
grouped_node() :
|
||||
@ -37,7 +40,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(link_pointer self)
|
||||
void init(node_pointer self)
|
||||
{
|
||||
group_prev_ = self;
|
||||
}
|
||||
@ -52,9 +55,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::ptr_bucket
|
||||
{
|
||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||
typedef grouped_ptr_node<T>* node_pointer;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
link_pointer group_prev_;
|
||||
node_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
grouped_ptr_node() :
|
||||
@ -63,7 +67,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(link_pointer self)
|
||||
void init(node_pointer self)
|
||||
{
|
||||
group_prev_ = self;
|
||||
}
|
||||
@ -181,7 +185,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::node_allocator_traits node_allocator_traits;
|
||||
typedef typename table::bucket_pointer bucket_pointer;
|
||||
typedef typename table::link_pointer link_pointer;
|
||||
typedef typename table::previous_pointer previous_pointer;
|
||||
typedef typename table::hasher hasher;
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
@ -234,8 +237,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
iterator n = this->begin(bucket_index);
|
||||
|
||||
for (;;)
|
||||
@ -250,13 +252,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
n = iterator(static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_));
|
||||
n = iterator(n.node_->group_prev_->next_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +268,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::size_t x = 0;
|
||||
node_pointer it = n.node_;
|
||||
do {
|
||||
it = static_cast<node_pointer>(it->group_prev_);
|
||||
it = it->group_prev_;
|
||||
++x;
|
||||
} while(it != n.node_);
|
||||
|
||||
@ -280,10 +280,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
iterator n = this->find_node(k);
|
||||
return std::make_pair(
|
||||
n, n.node_ ? iterator(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
)) : n);
|
||||
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
|
||||
}
|
||||
|
||||
// Equality
|
||||
@ -296,10 +293,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
iterator n2 = other.find_matching_node(n1);
|
||||
if (!n2.node_) return false;
|
||||
iterator end1(static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n1.node_->group_prev_)->next_));
|
||||
iterator end2(static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n2.node_->group_prev_)->next_));
|
||||
iterator end1(n1.node_->group_prev_->next_);
|
||||
iterator end2(n2.node_->group_prev_->next_);
|
||||
if (!group_equals(n1, end1, n2, end2)) return false;
|
||||
n1 = end1;
|
||||
}
|
||||
@ -307,8 +302,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
|
||||
static bool group_equals(iterator n1, iterator end1,
|
||||
iterator n2, iterator end2)
|
||||
{
|
||||
@ -369,37 +362,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return count;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool group_equals(iterator n1, iterator end1,
|
||||
iterator n2, iterator end2)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(!extractor::compare_mapped(*n1, *n2))
|
||||
return false;
|
||||
|
||||
++n1;
|
||||
++n2;
|
||||
|
||||
if (n1 == end1) return n2 == end2;
|
||||
if (n2 == end2) return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Emplace/Insert
|
||||
|
||||
static inline void add_after_node(
|
||||
node_pointer n,
|
||||
node_pointer pos)
|
||||
{
|
||||
n->next_ = static_cast<node_pointer>(pos->group_prev_)->next_;
|
||||
n->next_ = pos->group_prev_->next_;
|
||||
n->group_prev_ = pos->group_prev_;
|
||||
static_cast<node_pointer>(pos->group_prev_)->next_ =
|
||||
static_cast<link_pointer>(n);
|
||||
pos->group_prev_ = static_cast<link_pointer>(n);
|
||||
pos->group_prev_->next_ = n;
|
||||
pos->group_prev_ = n;
|
||||
}
|
||||
|
||||
inline iterator add_node(
|
||||
@ -412,37 +384,35 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (pos.node_) {
|
||||
this->add_after_node(n, pos.node_);
|
||||
if (n->next_) {
|
||||
std::size_t next_bucket = policy::to_bucket(
|
||||
this->bucket_count_,
|
||||
std::size_t next_bucket = this->hash_to_bucket(
|
||||
static_cast<node_pointer>(n->next_)->hash_);
|
||||
if (next_bucket !=
|
||||
policy::to_bucket(this->bucket_count_, key_hash)) {
|
||||
if (next_bucket != this->hash_to_bucket(key_hash)) {
|
||||
this->get_bucket(next_bucket)->next_ = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bucket_pointer b = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, key_hash));
|
||||
this->hash_to_bucket(key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
link_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(policy::to_bucket(this->bucket_count_,
|
||||
this->get_bucket(this->hash_to_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_
|
||||
))->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
n->next_ = start_node->next_;
|
||||
start_node->next_ = static_cast<link_pointer>(n);
|
||||
start_node->next_ = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = static_cast<link_pointer>(n);
|
||||
b->next_->next_ = n;
|
||||
}
|
||||
}
|
||||
++this->size_;
|
||||
@ -468,8 +438,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
this->add_node(a, key_hash, this->find_node(key_hash, k));
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
iterator emplace(boost::unordered::detail::emplace_args1<
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
@ -545,11 +515,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t key_hash = this->hash(k);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
bucket_pointer this_bucket = this->get_bucket(bucket_index);
|
||||
|
||||
previous_pointer prev = this_bucket->next_;
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
@ -557,24 +524,21 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
static_cast<node_pointer>(prev->next_)->value())))
|
||||
break;
|
||||
prev = static_cast<previous_pointer>(
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_);
|
||||
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
|
||||
}
|
||||
|
||||
node_pointer pos = static_cast<node_pointer>(prev->next_);
|
||||
link_pointer end1 =
|
||||
static_cast<node_pointer>(pos->group_prev_)->next_;
|
||||
node_pointer end = static_cast<node_pointer>(end1);
|
||||
prev->next_ = end1;
|
||||
this->fix_buckets(this_bucket, prev, end);
|
||||
return this->delete_nodes(c_iterator(pos), c_iterator(end));
|
||||
node_pointer first_node = static_cast<node_pointer>(prev->next_);
|
||||
link_pointer end = first_node->group_prev_->next_;
|
||||
|
||||
std::size_t count = this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return count;
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
@ -582,130 +546,70 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
|
||||
bucket_pointer this_bucket = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, r.node_->hash_));
|
||||
previous_pointer prev = unlink_node(*this_bucket, r.node_);
|
||||
|
||||
this->fix_buckets(this_bucket, prev, next.node_);
|
||||
|
||||
this->delete_node(r);
|
||||
|
||||
erase_nodes(r.node_, next.node_);
|
||||
return next;
|
||||
}
|
||||
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
|
||||
previous_pointer prev = unlink_nodes(
|
||||
*this->get_bucket(bucket_index), r1.node_, r2.node_);
|
||||
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
|
||||
this->delete_nodes(r1, r2);
|
||||
|
||||
erase_nodes(r1.node_, r2.node_);
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
static previous_pointer unlink_node(bucket& b, node_pointer n)
|
||||
link_pointer erase_nodes(node_pointer begin, node_pointer end)
|
||||
{
|
||||
node_pointer next = static_cast<node_pointer>(n->next_);
|
||||
previous_pointer prev =
|
||||
static_cast<previous_pointer>(n->group_prev_);
|
||||
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
|
||||
|
||||
if(prev->next_ != n) {
|
||||
// The node is at the beginning of a group.
|
||||
// Split the groups containing 'begin' and 'end'.
|
||||
// And get the pointer to the node before begin while
|
||||
// we're at it.
|
||||
link_pointer prev = split_groups(begin, end);
|
||||
|
||||
// Find the previous node pointer:
|
||||
prev = b.next_;
|
||||
while(prev->next_ != n) {
|
||||
prev = static_cast<previous_pointer>(
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_);
|
||||
}
|
||||
|
||||
// Remove from group
|
||||
if (next && next->group_prev_ == static_cast<link_pointer>(n))
|
||||
{
|
||||
next->group_prev_ = n->group_prev_;
|
||||
}
|
||||
}
|
||||
else if (next && next->group_prev_ == static_cast<link_pointer>(n))
|
||||
{
|
||||
// The deleted node is not at the end of the group, so
|
||||
// change the link from the next node.
|
||||
next->group_prev_ = n->group_prev_;
|
||||
}
|
||||
else {
|
||||
// The deleted node is at the end of the group, so the
|
||||
// first node in the group is pointing to it.
|
||||
// Find that to change its pointer.
|
||||
node_pointer x = static_cast<node_pointer>(n->group_prev_);
|
||||
while(x->group_prev_ != static_cast<link_pointer>(n)) {
|
||||
x = static_cast<node_pointer>(x->group_prev_);
|
||||
}
|
||||
x->group_prev_ = n->group_prev_;
|
||||
// If we don't have a 'prev' it means that begin is at the
|
||||
// beginning of a block, so search through the blocks in the
|
||||
// same bucket.
|
||||
if (!prev) {
|
||||
prev = this->get_previous_start(bucket_index);
|
||||
while (prev->next_ != begin)
|
||||
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
|
||||
}
|
||||
|
||||
prev->next_ = static_cast<link_pointer>(next);
|
||||
return prev;
|
||||
}
|
||||
|
||||
static previous_pointer unlink_nodes(bucket& b,
|
||||
node_pointer begin, node_pointer end)
|
||||
{
|
||||
previous_pointer prev = static_cast<previous_pointer>(
|
||||
begin->group_prev_);
|
||||
|
||||
if(prev->next_ != static_cast<link_pointer>(begin)) {
|
||||
// The node is at the beginning of a group.
|
||||
|
||||
// Find the previous node pointer:
|
||||
prev = b.next_;
|
||||
while(prev->next_ != static_cast<link_pointer>(begin))
|
||||
prev = static_cast<previous_pointer>(
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_);
|
||||
|
||||
if (end) split_group(end);
|
||||
}
|
||||
else {
|
||||
node_pointer group1 = split_group(begin);
|
||||
|
||||
if (end) {
|
||||
node_pointer group2 = split_group(end);
|
||||
|
||||
if(begin == group2) {
|
||||
link_pointer end1 = group1->group_prev_;
|
||||
link_pointer end2 = end->group_prev_;
|
||||
group1->group_prev_ = end2;
|
||||
end->group_prev_ = end1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev->next_ = static_cast<link_pointer>(end);
|
||||
// Delete the nodes.
|
||||
do {
|
||||
link_pointer group_end =
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
|
||||
this->delete_nodes(prev, group_end);
|
||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||
} while(prev->next_ != end);
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
// Break a ciruclar list into two, with split as the beginning
|
||||
// of the second group (if split is at the beginning then don't
|
||||
// split).
|
||||
static node_pointer split_group(node_pointer split)
|
||||
static link_pointer split_groups(node_pointer begin, node_pointer end)
|
||||
{
|
||||
// Find first node in group.
|
||||
node_pointer first = split;
|
||||
while (static_cast<node_pointer>(first->group_prev_)->next_ ==
|
||||
static_cast<link_pointer>(first))
|
||||
first = static_cast<node_pointer>(first->group_prev_);
|
||||
node_pointer prev = begin->group_prev_;
|
||||
if (prev->next_ != begin) prev = node_pointer();
|
||||
|
||||
if(first == split) return split;
|
||||
if (end) {
|
||||
node_pointer first = end;
|
||||
while (first != begin && first->group_prev_->next_ == first) {
|
||||
first = first->group_prev_;
|
||||
}
|
||||
|
||||
link_pointer last = first->group_prev_;
|
||||
first->group_prev_ = split->group_prev_;
|
||||
split->group_prev_ = last;
|
||||
boost::swap(first->group_prev_, end->group_prev_);
|
||||
if (first == begin) return prev;
|
||||
}
|
||||
|
||||
return first;
|
||||
if (prev) {
|
||||
node_pointer first = prev;
|
||||
while (first->group_prev_->next_ == first) {
|
||||
first = first->group_prev_;
|
||||
}
|
||||
boost::swap(first->group_prev_, begin->group_prev_);
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -715,19 +619,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static void fill_buckets(iterator n, table& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
link_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
));
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
|
||||
node_pointer first_node = creator.create(*n);
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = static_cast<link_pointer>(first_node);
|
||||
prev->next_ = first_node;
|
||||
++dst.size_;
|
||||
|
||||
for (++n; n != group_end; ++n)
|
||||
@ -748,24 +649,22 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_ASSERT(this->buckets_);
|
||||
|
||||
this->create_buckets(num_buckets);
|
||||
previous_pointer prev = this->get_previous_start();
|
||||
link_pointer prev = this->get_previous_start();
|
||||
while (prev->next_)
|
||||
prev = place_in_bucket(*this, prev,
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_));
|
||||
static_cast<node_pointer>(prev->next_)->group_prev_);
|
||||
}
|
||||
|
||||
// Iterate through the nodes placing them in the correct buckets.
|
||||
// pre: prev->next_ is not null.
|
||||
static previous_pointer place_in_bucket(table& dst,
|
||||
previous_pointer prev, node_pointer end)
|
||||
static link_pointer place_in_bucket(table& dst,
|
||||
link_pointer prev, node_pointer end)
|
||||
{
|
||||
bucket_pointer b = dst.get_bucket(policy::to_bucket(
|
||||
dst.bucket_count_, end->hash_));
|
||||
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = static_cast<node_pointer>(prev);
|
||||
return static_cast<previous_pointer>(end);
|
||||
b->next_ = prev;
|
||||
return end;
|
||||
}
|
||||
else {
|
||||
link_pointer next = end->next_;
|
||||
|
@ -56,30 +56,25 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const&, value_type const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Key, class ValueType>
|
||||
@ -93,11 +88,6 @@ namespace detail {
|
||||
return v.first;
|
||||
}
|
||||
|
||||
static key_type const& extract(key_type const& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type, Second> const& v)
|
||||
{
|
||||
@ -111,21 +101,6 @@ namespace detail {
|
||||
return v.first;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class... Args>
|
||||
static key_type const& extract(key_type const& k,
|
||||
Arg1 const&, Args const&...)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#else
|
||||
|
||||
template <class Arg1>
|
||||
static key_type const& extract(key_type const& k, Arg1 const&)
|
||||
{
|
||||
@ -143,19 +118,27 @@ namespace detail {
|
||||
return no_key();
|
||||
}
|
||||
|
||||
template <class Arg, class Arg1>
|
||||
static no_key extract(Arg const&, Arg1 const&)
|
||||
template <class Arg1, class Arg2>
|
||||
static no_key extract(Arg1 const&, Arg2 const&)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class Arg1, class Arg2, class Arg3, class... Args>
|
||||
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
|
||||
Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
template <typename T2> \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_::tuple<> const&, BOOST_FWD_REF(T2)) \
|
||||
namespace_ tuple<> const&, T2 const&) \
|
||||
{ \
|
||||
return no_key(); \
|
||||
} \
|
||||
@ -163,17 +146,17 @@ namespace detail {
|
||||
template <typename T, typename T2> \
|
||||
static typename is_key<key_type, T>::type \
|
||||
extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
|
||||
namespace_ tuple<T> const& k, T2 const&) \
|
||||
{ \
|
||||
return typename is_key<key_type, T>::type( \
|
||||
namespace_::get<0>(k)); \
|
||||
namespace_ get<0>(k)); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
static no_key extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_::tuple<> const&) \
|
||||
namespace_ tuple<> const&) \
|
||||
{ \
|
||||
return no_key(); \
|
||||
} \
|
||||
@ -181,25 +164,19 @@ namespace detail {
|
||||
template <typename T> \
|
||||
static typename is_key<key_type, T>::type \
|
||||
extract(boost::unordered::piecewise_construct_t, \
|
||||
namespace_::tuple<T> const& k) \
|
||||
namespace_ tuple<T> const& k) \
|
||||
{ \
|
||||
return typename is_key<key_type, T>::type( \
|
||||
namespace_::get<0>(k)); \
|
||||
namespace_ get<0>(k)); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
|
||||
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
|
||||
#endif
|
||||
|
||||
|
||||
static bool compare_mapped(value_type const& x, value_type const& y)
|
||||
{
|
||||
return x.second == y.second;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
|
@ -18,6 +18,18 @@
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
|
||||
#if defined(__EDG__)
|
||||
#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
|
||||
#pragma message("Warning: BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported.")
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || \
|
||||
defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#warning "BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported."
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -125,7 +137,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Types>
|
||||
struct table :
|
||||
Types::policy,
|
||||
boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal>
|
||||
@ -148,6 +159,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal> functions;
|
||||
typedef typename functions::set_hash_functions set_hash_functions;
|
||||
|
||||
typedef typename Types::allocator allocator;
|
||||
typedef typename boost::unordered::detail::
|
||||
@ -164,20 +176,17 @@ namespace boost { namespace unordered { namespace detail {
|
||||
const_node_pointer;
|
||||
typedef typename bucket_allocator_traits::pointer
|
||||
bucket_pointer;
|
||||
typedef typename bucket::previous_pointer
|
||||
previous_pointer;
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node_pointer, value_type> iterator;
|
||||
iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
|
||||
c_iterator<node, const_node_pointer> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node_pointer, value_type, policy> l_iterator;
|
||||
l_iterator<node, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<const_node_pointer, node_pointer, value_type, policy>
|
||||
cl_iterator;
|
||||
cl_iterator<node, const_node_pointer, policy> cl_iterator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Members
|
||||
@ -226,28 +235,31 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
|
||||
}
|
||||
|
||||
previous_pointer get_previous_start() const
|
||||
link_pointer get_previous_start() const
|
||||
{
|
||||
return get_bucket(bucket_count_)->first_from_start();
|
||||
}
|
||||
|
||||
previous_pointer get_previous_start(std::size_t bucket_index) const
|
||||
link_pointer get_previous_start(std::size_t bucket_index) const
|
||||
{
|
||||
return get_bucket(bucket_index)->next_;
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return size_ ? iterator(static_cast<node_pointer>(
|
||||
get_previous_start()->next_)) : iterator();
|
||||
return size_ ? iterator(get_previous_start()->next_) : iterator();
|
||||
}
|
||||
|
||||
iterator begin(std::size_t bucket_index) const
|
||||
{
|
||||
if (!size_) return iterator();
|
||||
previous_pointer prev = get_previous_start(bucket_index);
|
||||
return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
|
||||
iterator();
|
||||
link_pointer prev = get_previous_start(bucket_index);
|
||||
return prev ? iterator(prev->next_) : iterator();
|
||||
}
|
||||
|
||||
std::size_t hash_to_bucket(std::size_t hash) const
|
||||
{
|
||||
return policy::to_bucket(bucket_count_, hash);
|
||||
}
|
||||
|
||||
float load_factor() const
|
||||
@ -263,8 +275,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!it.node_) return 0;
|
||||
|
||||
std::size_t count = 0;
|
||||
while(it.node_ && policy::to_bucket(
|
||||
bucket_count_, it.node_->hash_) == index)
|
||||
while(it.node_ && hash_to_bucket(it.node_->hash_) == index)
|
||||
{
|
||||
++count;
|
||||
++it;
|
||||
@ -353,7 +364,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{}
|
||||
|
||||
table(table& x, boost::unordered::detail::move_tag m) :
|
||||
functions(x),
|
||||
functions(x, m),
|
||||
allocators_(x.allocators_, m),
|
||||
bucket_count_(x.bucket_count_),
|
||||
size_(x.size_),
|
||||
@ -367,8 +378,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
table(table& x, node_allocator const& a,
|
||||
boost::unordered::detail::move_tag) :
|
||||
functions(x),
|
||||
boost::unordered::detail::move_tag m) :
|
||||
functions(x, m),
|
||||
allocators_(a, a),
|
||||
bucket_count_(x.bucket_count_),
|
||||
size_(0),
|
||||
@ -445,6 +456,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
void swap_allocators(table& other, false_type)
|
||||
{
|
||||
boost::unordered::detail::func::ignore_unused_variable_warning(other);
|
||||
|
||||
// According to 23.2.1.8, if propagate_on_container_swap is
|
||||
// false the behaviour is undefined unless the allocators
|
||||
// are equal.
|
||||
@ -459,10 +472,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Only swaps the allocators if propagate_on_container_swap
|
||||
void swap(table& x)
|
||||
{
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
op1(*this, x);
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
op2(x, *this);
|
||||
set_hash_functions op1(*this, x);
|
||||
set_hash_functions op2(x, *this);
|
||||
|
||||
// I think swap can throw if Propagate::value,
|
||||
// since the allocators' swap can throw. Not sure though.
|
||||
@ -500,26 +511,29 @@ namespace boost { namespace unordered { namespace detail {
|
||||
delete_buckets();
|
||||
}
|
||||
|
||||
void delete_node(c_iterator n)
|
||||
void delete_node(link_pointer prev)
|
||||
{
|
||||
boost::unordered::detail::destroy_value_impl(node_alloc(),
|
||||
n.node_->value_ptr());
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = n->next_;
|
||||
|
||||
boost::unordered::detail::func::destroy_value_impl(node_alloc(),
|
||||
n->value_ptr());
|
||||
node_allocator_traits::destroy(node_alloc(),
|
||||
boost::addressof(*n.node_));
|
||||
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
|
||||
boost::addressof(*n));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
--size_;
|
||||
}
|
||||
|
||||
std::size_t delete_nodes(c_iterator begin, c_iterator end)
|
||||
std::size_t delete_nodes(link_pointer prev, link_pointer end)
|
||||
{
|
||||
BOOST_ASSERT(prev->next_ != end);
|
||||
|
||||
std::size_t count = 0;
|
||||
|
||||
while(begin != end) {
|
||||
c_iterator n = begin;
|
||||
++begin;
|
||||
delete_node(n);
|
||||
do {
|
||||
delete_node(prev);
|
||||
++count;
|
||||
}
|
||||
} while (prev->next_ != end);
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -527,7 +541,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void delete_buckets()
|
||||
{
|
||||
if(buckets_) {
|
||||
delete_nodes(begin(), iterator());
|
||||
if (size_) delete_nodes(get_previous_start(), link_pointer());
|
||||
|
||||
if (bucket::extra_node) {
|
||||
node_pointer n = static_cast<node_pointer>(
|
||||
@ -547,10 +561,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
void clear()
|
||||
{
|
||||
if(!size_) return;
|
||||
if (!size_) return;
|
||||
|
||||
delete_nodes(begin(), iterator());
|
||||
get_previous_start()->next_ = link_pointer();
|
||||
delete_nodes(get_previous_start(), link_pointer());
|
||||
clear_buckets();
|
||||
|
||||
BOOST_ASSERT(!size_);
|
||||
@ -579,86 +592,33 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Fix buckets after erase
|
||||
// Fix buckets after delete
|
||||
//
|
||||
|
||||
// This is called after erasing a node or group of nodes to fix up
|
||||
// the bucket pointers.
|
||||
void fix_buckets(bucket_pointer this_bucket,
|
||||
previous_pointer prev, node_pointer next)
|
||||
std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
|
||||
{
|
||||
if (!next)
|
||||
link_pointer end = prev->next_;
|
||||
std::size_t bucket_index2 = bucket_index;
|
||||
|
||||
if (end)
|
||||
{
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = node_pointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
bucket_pointer next_bucket = get_bucket(
|
||||
policy::to_bucket(bucket_count_, next->hash_));
|
||||
bucket_index2 = hash_to_bucket(
|
||||
static_cast<node_pointer>(end)->hash_);
|
||||
|
||||
if (next_bucket != this_bucket)
|
||||
{
|
||||
next_bucket->next_ = prev;
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = node_pointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
// If begin and end are in the same bucket, then
|
||||
// there's nothing to do.
|
||||
if (bucket_index == bucket_index2) return bucket_index2;
|
||||
|
||||
// This is called after erasing a range of nodes to fix any bucket
|
||||
// pointers into that range.
|
||||
void fix_buckets_range(std::size_t bucket_index,
|
||||
previous_pointer prev, node_pointer begin, node_pointer end)
|
||||
{
|
||||
node_pointer n = begin;
|
||||
|
||||
// If we're not at the start of the current bucket, then
|
||||
// go to the start of the next bucket.
|
||||
if (get_bucket(bucket_index)->next_ != prev)
|
||||
{
|
||||
for(;;) {
|
||||
n = static_cast<node_pointer>(n->next_);
|
||||
if (n == end) {
|
||||
if (n) {
|
||||
std::size_t new_bucket_index =
|
||||
policy::to_bucket(bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
get_bucket(new_bucket_index)->next_ = prev;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
policy::to_bucket(bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Update the bucket containing end.
|
||||
get_bucket(bucket_index2)->next_ = prev;
|
||||
}
|
||||
|
||||
// Iterate through the remaining nodes, clearing out the bucket
|
||||
// pointers.
|
||||
get_bucket(bucket_index)->next_ = previous_pointer();
|
||||
for(;;) {
|
||||
n = static_cast<node_pointer>(n->next_);
|
||||
if (n == end) break;
|
||||
// Check if this bucket is now empty.
|
||||
bucket_pointer this_bucket = get_bucket(bucket_index);
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = link_pointer();
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
policy::to_bucket(bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
get_bucket(bucket_index)->next_ = previous_pointer();
|
||||
}
|
||||
};
|
||||
|
||||
// Finally fix the bucket containing the trailing node.
|
||||
if (n) {
|
||||
get_bucket(
|
||||
policy::to_bucket(bucket_count_, n->hash_))->next_
|
||||
= prev;
|
||||
}
|
||||
return bucket_index2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -678,8 +638,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void assign(table const& x, false_type)
|
||||
{
|
||||
// Strong exception safety.
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
new_func_this.commit();
|
||||
mlf_ = x.mlf_;
|
||||
recalculate_max_load();
|
||||
@ -707,8 +666,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
assign(x, false_type());
|
||||
}
|
||||
else {
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
|
||||
// Delete everything with current allocators before assigning
|
||||
// the new ones.
|
||||
@ -755,8 +713,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
move_assign_no_alloc(x);
|
||||
}
|
||||
else {
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
new_func_this.commit();
|
||||
mlf_ = x.mlf_;
|
||||
recalculate_max_load();
|
||||
@ -781,8 +738,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
void move_assign_no_alloc(table& x)
|
||||
{
|
||||
boost::unordered::detail::set_hash_functions<hasher, key_equal>
|
||||
new_func_this(*this, x);
|
||||
set_hash_functions new_func_this(*this, x);
|
||||
// No throw from here.
|
||||
mlf_ = x.mlf_;
|
||||
max_load_ = x.max_load_;
|
||||
|
@ -27,7 +27,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::value_base<T>
|
||||
{
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, unique_node<A, T> >::type::pointer link_pointer;
|
||||
A, unique_node<A, T> >::type::pointer node_pointer;
|
||||
typedef node_pointer link_pointer;
|
||||
|
||||
link_pointer next_;
|
||||
std::size_t hash_;
|
||||
@ -37,7 +38,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(link_pointer)
|
||||
void init(node_pointer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,6 +52,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::ptr_bucket
|
||||
{
|
||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||
typedef ptr_node<T>* node_pointer;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
std::size_t hash_;
|
||||
@ -60,7 +62,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hash_(0)
|
||||
{}
|
||||
|
||||
void init(link_pointer)
|
||||
void init(node_pointer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -176,7 +178,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::node_allocator_traits node_allocator_traits;
|
||||
typedef typename table::bucket_pointer bucket_pointer;
|
||||
typedef typename table::link_pointer link_pointer;
|
||||
typedef typename table::previous_pointer previous_pointer;
|
||||
typedef typename table::hasher hasher;
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
@ -231,8 +232,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
iterator n = this->begin(bucket_index);
|
||||
|
||||
for (;;)
|
||||
@ -247,8 +247,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
@ -291,13 +290,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
iterator n2 = other.find_matching_node(n1);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
if (!n2.node_ || *n1 != *n2)
|
||||
return false;
|
||||
#else
|
||||
if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -312,27 +306,26 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer n = a.release();
|
||||
n->hash_ = key_hash;
|
||||
|
||||
bucket_pointer b = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, key_hash));
|
||||
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
link_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(policy::to_bucket(this->bucket_count_,
|
||||
this->get_bucket(this->hash_to_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_)
|
||||
)->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
n->next_ = start_node->next_;
|
||||
start_node->next_ = static_cast<link_pointer>(n);
|
||||
start_node->next_ = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = static_cast<link_pointer>(n);
|
||||
b->next_->next_ = n;
|
||||
}
|
||||
|
||||
++this->size_;
|
||||
@ -341,8 +334,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
value_type& operator[](key_type const& k)
|
||||
{
|
||||
typedef typename value_type::second_type mapped_type;
|
||||
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
@ -360,8 +351,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return *add_node(a, key_hash);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
emplace_return emplace(boost::unordered::detail::emplace_args1<
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
@ -381,7 +372,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
return emplace_impl(
|
||||
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
@ -392,7 +383,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <typename A0>
|
||||
emplace_return emplace(
|
||||
boost::unordered::detail::emplace_args1<A0> const& args)
|
||||
@ -518,11 +509,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t key_hash = this->hash(k);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
bucket_pointer this_bucket = this->get_bucket(bucket_index);
|
||||
|
||||
previous_pointer prev = this_bucket->next_;
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
@ -530,21 +518,20 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
static_cast<node_pointer>(prev->next_)->value())))
|
||||
break;
|
||||
prev = static_cast<previous_pointer>(prev->next_);
|
||||
prev = prev->next_;
|
||||
}
|
||||
|
||||
node_pointer pos = static_cast<node_pointer>(prev->next_);
|
||||
node_pointer end = static_cast<node_pointer>(pos->next_);
|
||||
prev->next_ = pos->next_;
|
||||
this->fix_buckets(this_bucket, prev, end);
|
||||
return this->delete_nodes(c_iterator(pos), c_iterator(end));
|
||||
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
|
||||
|
||||
std::size_t count = this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return count;
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
@ -552,46 +539,30 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
|
||||
bucket_pointer this_bucket = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, r.node_->hash_));
|
||||
previous_pointer prev = unlink_node(*this_bucket, r.node_);
|
||||
|
||||
this->fix_buckets(this_bucket, prev, next.node_);
|
||||
|
||||
this->delete_node(r);
|
||||
|
||||
erase_nodes(r.node_, next.node_);
|
||||
return next;
|
||||
}
|
||||
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
|
||||
previous_pointer prev = unlink_nodes(
|
||||
*this->get_bucket(bucket_index), r1.node_, r2.node_);
|
||||
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
|
||||
this->delete_nodes(r1, r2);
|
||||
|
||||
erase_nodes(r1.node_, r2.node_);
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
static previous_pointer unlink_node(bucket& b, node_pointer n)
|
||||
void erase_nodes(node_pointer begin, node_pointer end)
|
||||
{
|
||||
return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
|
||||
}
|
||||
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
|
||||
|
||||
static previous_pointer unlink_nodes(bucket& b,
|
||||
node_pointer begin, node_pointer end)
|
||||
{
|
||||
previous_pointer prev = b.next_;
|
||||
link_pointer begin_void = static_cast<link_pointer>(begin);
|
||||
while(prev->next_ != begin_void)
|
||||
prev = static_cast<previous_pointer>(prev->next_);
|
||||
prev->next_ = static_cast<link_pointer>(end);
|
||||
return prev;
|
||||
// Find the node before begin.
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
while(prev->next_ != begin) prev = prev->next_;
|
||||
|
||||
// Delete the nodes.
|
||||
do {
|
||||
this->delete_node(prev);
|
||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||
} while (prev->next_ != end);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -601,12 +572,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static void fill_buckets(iterator n, table& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
link_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
node_pointer node = creator.create(*n);
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
prev->next_ = node;
|
||||
++dst.size_;
|
||||
++n;
|
||||
|
||||
@ -620,28 +591,26 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_ASSERT(this->buckets_);
|
||||
|
||||
this->create_buckets(num_buckets);
|
||||
previous_pointer prev = this->get_previous_start();
|
||||
link_pointer prev = this->get_previous_start();
|
||||
while (prev->next_)
|
||||
prev = place_in_bucket(*this, prev);
|
||||
}
|
||||
|
||||
// Iterate through the nodes placing them in the correct buckets.
|
||||
// pre: prev->next_ is not null.
|
||||
static previous_pointer place_in_bucket(table& dst,
|
||||
previous_pointer prev)
|
||||
static link_pointer place_in_bucket(table& dst, link_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
bucket_pointer b = dst.get_bucket(
|
||||
table::to_bucket(dst.bucket_count_, n->hash_));
|
||||
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
return static_cast<previous_pointer>(n);
|
||||
return n;
|
||||
}
|
||||
else {
|
||||
prev->next_ = n->next_;
|
||||
n->next_ = b->next_->next_;
|
||||
b->next_->next_ = static_cast<link_pointer>(n);
|
||||
b->next_->next_ = n;
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
struct move_tag {};
|
||||
struct empty_emplace {};
|
||||
|
||||
namespace func {
|
||||
template <class T>
|
||||
inline void ignore_unused_variable_warning(T const&) {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// iterator SFINAE
|
||||
|
||||
|
@ -117,17 +117,19 @@ namespace unordered
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_map(BOOST_RV_REF(unordered_map) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
@ -142,7 +144,7 @@ namespace unordered
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_map();
|
||||
~unordered_map() BOOST_NOEXCEPT;
|
||||
|
||||
// Assign
|
||||
|
||||
@ -165,7 +167,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_map& operator=(unordered_map&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@ -178,60 +180,60 @@ namespace unordered
|
||||
unordered_map& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const;
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@ -449,12 +451,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@ -463,8 +465,7 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -502,13 +503,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@ -599,17 +600,19 @@ namespace unordered
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
@ -624,7 +627,7 @@ namespace unordered
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_multimap();
|
||||
~unordered_multimap() BOOST_NOEXCEPT;
|
||||
|
||||
// Assign
|
||||
|
||||
@ -648,7 +651,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multimap& operator=(unordered_multimap&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@ -661,60 +664,60 @@ namespace unordered
|
||||
unordered_multimap& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const;
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
iterator emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@ -928,12 +931,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@ -942,8 +945,7 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -981,13 +983,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@ -1059,7 +1061,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::~unordered_map() {}
|
||||
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
@ -1068,7 +1070,7 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K,T,H,P,A>::unordered_map(
|
||||
@ -1107,7 +1109,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
std::size_t unordered_map<K,T,H,P,A>::max_size() const
|
||||
std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@ -1276,13 +1278,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
float unordered_map<K,T,H,P,A>::load_factor() const
|
||||
float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_map<K,T,H,P,A>::max_load_factor(float m)
|
||||
void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
@ -1392,7 +1394,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
|
||||
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
@ -1401,7 +1403,7 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K,T,H,P,A>::unordered_multimap(
|
||||
@ -1440,7 +1442,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
|
||||
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@ -1588,13 +1590,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
float unordered_multimap<K,T,H,P,A>::load_factor() const
|
||||
float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
|
||||
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
@ -115,17 +115,19 @@ namespace unordered
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_set(BOOST_RV_REF(unordered_set) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
@ -140,7 +142,7 @@ namespace unordered
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_set();
|
||||
~unordered_set() BOOST_NOEXCEPT;
|
||||
|
||||
// Assign
|
||||
|
||||
@ -163,7 +165,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_set& operator=(unordered_set&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@ -176,60 +178,60 @@ namespace unordered
|
||||
unordered_set& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const;
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@ -434,12 +436,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@ -448,8 +450,7 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -487,13 +488,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@ -583,17 +584,19 @@ namespace unordered
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&&, allocator_type const&);
|
||||
#endif
|
||||
|
||||
@ -608,7 +611,7 @@ namespace unordered
|
||||
|
||||
// Destructor
|
||||
|
||||
~unordered_multiset();
|
||||
~unordered_multiset() BOOST_NOEXCEPT;
|
||||
|
||||
// Assign
|
||||
|
||||
@ -632,7 +635,7 @@ namespace unordered
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
unordered_multiset& operator=(unordered_multiset&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
@ -645,60 +648,60 @@ namespace unordered
|
||||
unordered_multiset& operator=(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
allocator_type get_allocator() const
|
||||
allocator_type get_allocator() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.node_alloc();
|
||||
}
|
||||
|
||||
// size and capacity
|
||||
|
||||
bool empty() const
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.size_;
|
||||
}
|
||||
|
||||
size_type max_size() const;
|
||||
size_type max_size() const BOOST_NOEXCEPT;
|
||||
|
||||
// iterators
|
||||
|
||||
iterator begin()
|
||||
iterator begin() BOOST_NOEXCEPT
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
iterator end() BOOST_NOEXCEPT
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
const_iterator cend() const BOOST_NOEXCEPT
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
iterator emplace(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@ -903,12 +906,12 @@ namespace unordered
|
||||
|
||||
// bucket interface
|
||||
|
||||
size_type bucket_count() const
|
||||
size_type bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
size_type max_bucket_count() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_bucket_count();
|
||||
}
|
||||
@ -917,8 +920,7 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
return table_.hash_to_bucket(table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@ -956,13 +958,13 @@ namespace unordered
|
||||
|
||||
// hash policy
|
||||
|
||||
float max_load_factor() const
|
||||
float max_load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.mlf_;
|
||||
}
|
||||
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
float load_factor() const BOOST_NOEXCEPT;
|
||||
void max_load_factor(float) BOOST_NOEXCEPT;
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
@ -1034,7 +1036,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::~unordered_set() {}
|
||||
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
@ -1043,7 +1045,7 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T,H,P,A>::unordered_set(
|
||||
@ -1082,7 +1084,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
std::size_t unordered_set<T,H,P,A>::max_size() const
|
||||
std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@ -1202,13 +1204,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
float unordered_set<T,H,P,A>::load_factor() const
|
||||
float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_set<T,H,P,A>::max_load_factor(float m)
|
||||
void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
@ -1318,7 +1320,7 @@ namespace unordered
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
|
||||
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
@ -1327,7 +1329,7 @@ namespace unordered
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T,H,P,A>::unordered_multiset(
|
||||
@ -1366,7 +1368,7 @@ namespace unordered
|
||||
// size and capacity
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
std::size_t unordered_multiset<T,H,P,A>::max_size() const
|
||||
std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.max_size();
|
||||
}
|
||||
@ -1486,13 +1488,13 @@ namespace unordered
|
||||
// hash policy
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
float unordered_multiset<T,H,P,A>::load_factor() const
|
||||
float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
|
||||
{
|
||||
return table_.load_factor();
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
|
||||
void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
|
||||
{
|
||||
table_.max_load_factor(m);
|
||||
}
|
||||
|
@ -105,7 +105,8 @@ struct assign_test5 : assign_base<T>
|
||||
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(self_assign_test1)(self_assign_test2)
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -159,7 +159,7 @@ struct copy_range_construct_test : public range<T>, objects
|
||||
}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(construct_test1)
|
||||
(construct_test2)
|
||||
(construct_test3)
|
||||
@ -174,3 +174,4 @@ RUN_EXCEPTION_TESTS(
|
||||
(input_range_construct_test)
|
||||
(copy_range_construct_test),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -64,6 +64,7 @@ struct copy_with_allocator_test : public test::exception_base
|
||||
}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -49,6 +49,7 @@ struct erase_by_key_test1 : public erase_test_base<T>
|
||||
}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(erase_by_key_test1),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -37,7 +37,7 @@ struct insert_test_base : public test::exception_base
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T>
|
||||
struct emplace_test1 : public insert_test_base<T>
|
||||
@ -236,11 +236,12 @@ struct insert_test_rehash3 : public insert_test_base<T>
|
||||
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
|
||||
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define ALL_TESTS (emplace_test1)BASIC_TESTS
|
||||
#else
|
||||
#define ALL_TESTS BASIC_TESTS
|
||||
#endif
|
||||
|
||||
|
||||
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -79,7 +79,7 @@ struct rehash_test4 : rehash_test_base<T>
|
||||
void run(T& x) const { x.rehash(0); }
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
|
||||
CONTAINER_SEQ)
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -118,7 +118,8 @@ struct swap_test4 : swap_base<T>
|
||||
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
EXCEPTION_TESTS(
|
||||
(self_swap_test1)(self_swap_test2)
|
||||
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -20,22 +20,37 @@
|
||||
fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
} \
|
||||
|
||||
# define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
|
||||
UNORDERED_AUTO_TEST(name) \
|
||||
{ \
|
||||
for (unsigned i = 0; i < n; ++i) { \
|
||||
test_func< type > fixture; \
|
||||
::test::lightweight::exception_safety( \
|
||||
fixture, BOOST_STRINGIZE(test_func<type>)); \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
|
||||
|
||||
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
|
||||
|
||||
#define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
|
||||
(test_seq)(param_seq)) \
|
||||
RUN_TESTS() \
|
||||
#define EXCEPTION_TESTS(test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((1))(param_seq))
|
||||
|
||||
#define RUN_EXCEPTION_TESTS_OP(r, product) \
|
||||
UNORDERED_EXCEPTION_TEST_CASE( \
|
||||
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
|
||||
(test_seq)((n))(param_seq))
|
||||
|
||||
#define EXCEPTION_TESTS_OP(r, product) \
|
||||
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
|
||||
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
|
||||
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product)) \
|
||||
), \
|
||||
BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_SEQ_ELEM(1, product) \
|
||||
BOOST_PP_SEQ_ELEM(1, product), \
|
||||
BOOST_PP_SEQ_ELEM(2, product) \
|
||||
) \
|
||||
|
||||
#define UNORDERED_SCOPE(scope_name) \
|
||||
|
@ -170,7 +170,7 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<typename... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
|
@ -348,7 +348,7 @@ namespace exception
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
@ -528,7 +528,7 @@ namespace exception
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 construct function.");
|
||||
|
@ -155,7 +155,7 @@ namespace minimal
|
||||
~movable1() {}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
class movable2
|
||||
{
|
||||
public:
|
||||
@ -371,7 +371,7 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
@ -443,7 +443,7 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
@ -591,7 +591,7 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
|
@ -25,6 +25,7 @@ test-suite unordered
|
||||
[ run minimal_allocator.cpp ]
|
||||
[ run compile_set.cpp ]
|
||||
[ run compile_map.cpp ]
|
||||
[ run noexcept_tests.cpp ]
|
||||
[ run link_test_1.cpp link_test_2.cpp ]
|
||||
[ run incomplete_test.cpp ]
|
||||
[ run simple_tests.cpp ]
|
||||
@ -34,9 +35,6 @@ test-suite unordered
|
||||
[ run move_tests.cpp ]
|
||||
[ run assign_tests.cpp ]
|
||||
[ run insert_tests.cpp ]
|
||||
[ run insert_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
: insert_deprecated ]
|
||||
[ run insert_stable_tests.cpp ]
|
||||
[ run unnecessary_copy_tests.cpp ]
|
||||
[ run erase_tests.cpp ]
|
||||
@ -47,7 +45,6 @@ test-suite unordered
|
||||
[ run load_factor_tests.cpp ]
|
||||
[ run rehash_tests.cpp ]
|
||||
[ run equality_tests.cpp ]
|
||||
[ run equality_deprecated.cpp ]
|
||||
[ run swap_tests.cpp ]
|
||||
|
||||
[ run compile_set.cpp : :
|
||||
|
@ -137,7 +137,7 @@ void unordered_destructible_test(X&)
|
||||
|
||||
X x1;
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
X x2(rvalue_default<X>());
|
||||
X x3 = rvalue_default<X>();
|
||||
// This can only be done if propagate_on_container_move_assignment::value
|
||||
@ -453,7 +453,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
X x1(rvalue_default<X>());
|
||||
X x2(boost::move(x1));
|
||||
x1 = rvalue_default<X>();
|
||||
|
@ -1,174 +0,0 @@
|
||||
|
||||
// Copyright 2008-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_UNORDERED_DEPRECATED_EQUALITY
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/preprocessor/seq.hpp>
|
||||
#include <list>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
namespace equality_tests
|
||||
{
|
||||
struct mod_compare
|
||||
{
|
||||
bool alt_hash_;
|
||||
|
||||
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
|
||||
|
||||
bool operator()(int x, int y) const
|
||||
{
|
||||
return x % 1000 == y % 1000;
|
||||
}
|
||||
|
||||
int operator()(int x) const
|
||||
{
|
||||
return alt_hash_ ? x % 250 : (x + 5) % 250;
|
||||
}
|
||||
};
|
||||
|
||||
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_TEST(set1 op set2); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
boost::unordered_multiset<int, mod_compare, mod_compare> \
|
||||
set1, set2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
|
||||
BOOST_TEST(set1 op set2); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
boost::unordered_map<int, int, mod_compare, mod_compare> \
|
||||
map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_TEST(map1 op map2); \
|
||||
}
|
||||
|
||||
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
|
||||
{ \
|
||||
boost::unordered_multimap<int, int, mod_compare, mod_compare> \
|
||||
map1, map2; \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
|
||||
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
|
||||
BOOST_TEST(map1 op map2); \
|
||||
}
|
||||
|
||||
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
|
||||
#define UNORDERED_MAP_INSERT(r, map, item) \
|
||||
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_size_tests)
|
||||
{
|
||||
boost::unordered_set<int> x1, x2;
|
||||
BOOST_TEST(x1 == x2);
|
||||
BOOST_TEST(!(x1 != x2));
|
||||
|
||||
x1.insert(1);
|
||||
BOOST_TEST(x1 != x2);
|
||||
BOOST_TEST(!(x1 == x2));
|
||||
BOOST_TEST(x2 != x1);
|
||||
BOOST_TEST(!(x2 == x1));
|
||||
|
||||
x2.insert(1);
|
||||
BOOST_TEST(x1 == x2);
|
||||
BOOST_TEST(!(x1 != x2));
|
||||
|
||||
x2.insert(2);
|
||||
BOOST_TEST(x1 != x2);
|
||||
BOOST_TEST(!(x1 == x2));
|
||||
BOOST_TEST(x2 != x1);
|
||||
BOOST_TEST(!(x2 == x1));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_key_value_tests)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2))
|
||||
UNORDERED_EQUALITY_SET_TEST((2), ==, (2))
|
||||
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_collision_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1), !=, (501))
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(251), !=, (1)(501))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(501), ==, (1)(501))
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1)(501), ==, (501)(1))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_group_size_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(10)(20)(20), !=, (10)(10)(20))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((10)(1))((20)(1))((20)(1)), !=,
|
||||
((10)(1))((20)(1))((10)(1)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((20)(1))((10)(1))((10)(1)), ==,
|
||||
((10)(1))((20)(1))((10)(1)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_map_value_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)))
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(1)), ==, ((1)(1)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1)), !=, ((1)(2)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
|
||||
UNORDERED_EQUALITY_MULTIMAP_TEST(
|
||||
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_predicate_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_SET_TEST(
|
||||
(1), ==, (1001))
|
||||
UNORDERED_EQUALITY_MAP_TEST(
|
||||
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
|
||||
}
|
||||
|
||||
// Test that equality still works when the two containers have
|
||||
// different hash functions but the same equality predicate.
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_different_hash_test)
|
||||
{
|
||||
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
|
||||
set set1(0, mod_compare(false), mod_compare(false));
|
||||
set set2(0, mod_compare(true), mod_compare(true));
|
||||
BOOST_TEST(set1 == set2);
|
||||
set1.insert(1); set2.insert(2);
|
||||
BOOST_TEST(set1 != set2);
|
||||
set1.insert(2); set2.insert(1);
|
||||
BOOST_TEST(set1 == set2);
|
||||
set1.insert(10); set2.insert(20);
|
||||
BOOST_TEST(set1 != set2);
|
||||
set1.insert(20); set2.insert(10);
|
||||
BOOST_TEST(set1 == set2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
@ -380,7 +380,7 @@ void move_emplace_tests(X*, test::random_generator generator)
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
typename X::value_type value = *it;
|
||||
typename X::value_type value = *it;
|
||||
x.emplace(boost::move(value));
|
||||
tracker.insert(*it);
|
||||
tracker.compare_key(x, *it);
|
||||
@ -549,13 +549,13 @@ UNORDERED_TEST(equivalent_emplace_tests1,
|
||||
|
||||
UNORDERED_TEST(move_emplace_tests,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
|
||||
(test_multiset)(test_multimap))
|
||||
(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(default_emplace_tests,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
|
||||
(test_multiset)(test_multimap))
|
||||
(test_multiset)(test_multimap))
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
@ -576,6 +576,21 @@ UNORDERED_TEST(map_insert_range_test2,
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
|
||||
struct initialize_from_two_ints
|
||||
{
|
||||
int a, b;
|
||||
|
||||
friend std::size_t hash_value(initialize_from_two_ints const& x)
|
||||
{
|
||||
return x.a + x.b;
|
||||
}
|
||||
|
||||
bool operator==(initialize_from_two_ints const& x) const
|
||||
{
|
||||
return a == x.a && b == x.b;
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
{
|
||||
boost::unordered_set<int> set;
|
||||
@ -583,6 +598,30 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
BOOST_TEST_EQ(set.size(), 3u);
|
||||
BOOST_TEST(set.find(1) != set.end());
|
||||
BOOST_TEST(set.find(4) == set.end());
|
||||
|
||||
boost::unordered_set<initialize_from_two_ints> set2;
|
||||
|
||||
set2.insert({1, 2});
|
||||
BOOST_TEST(set2.size() == 1);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({2,1}) == set2.end());
|
||||
|
||||
set2.insert({{3,4},{5,6},{7,8}});
|
||||
BOOST_TEST(set2.size() == 4);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({3,4}) != set2.end());
|
||||
BOOST_TEST(set2.find({5,6}) != set2.end());
|
||||
BOOST_TEST(set2.find({7,8}) != set2.end());
|
||||
BOOST_TEST(set2.find({8,7}) == set2.end());
|
||||
|
||||
set2.insert({{2, 1}, {3,4}});
|
||||
BOOST_TEST(set2.size() == 5);
|
||||
BOOST_TEST(set2.find({1,2}) != set2.end());
|
||||
BOOST_TEST(set2.find({2,1}) != set2.end());
|
||||
BOOST_TEST(set2.find({3,4}) != set2.end());
|
||||
BOOST_TEST(set2.find({5,6}) != set2.end());
|
||||
BOOST_TEST(set2.find({7,8}) != set2.end());
|
||||
BOOST_TEST(set2.find({8,7}) == set2.end());
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
|
||||
@ -658,20 +697,6 @@ UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
|
||||
#if defined (BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
|
||||
x.emplace(1);
|
||||
BOOST_TEST(x.find(1) != x.end() &&
|
||||
x.find(1)->second == overloaded_constructor());
|
||||
|
||||
x.emplace(4, 5, 6);
|
||||
BOOST_TEST(x.find(4) != x.end() &&
|
||||
x.find(4)->second == overloaded_constructor(5, 6));
|
||||
|
||||
x.emplace(7, 8, 9, 10);
|
||||
BOOST_TEST(x.find(7) != x.end() &&
|
||||
x.find(7)->second == overloaded_constructor(8, 9, 10));
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
@ -705,6 +730,19 @@ UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
}
|
||||
|
||||
struct derived_from_piecewise_construct_t :
|
||||
boost::unordered::piecewise_construct_t {};
|
||||
|
||||
derived_from_piecewise_construct_t piecewise_rvalue() {
|
||||
return derived_from_piecewise_construct_t();
|
||||
}
|
||||
|
||||
struct convertible_to_piecewise {
|
||||
operator boost::unordered::piecewise_construct_t() const {
|
||||
return boost::unordered::piecewise_construct;
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test2)
|
||||
{
|
||||
boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
|
||||
@ -713,13 +751,18 @@ UNORDERED_AUTO_TEST(map_emplace_test2)
|
||||
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());
|
||||
x.emplace(convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second == overloaded_constructor());
|
||||
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(2,3), boost::make_tuple(4,5,6));
|
||||
x.emplace(piecewise_rvalue(), boost::make_tuple(2,3), boost::make_tuple(4,5,6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, boost::make_tuple(9,3,1), boost::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9,3,1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9,3,1))->second == overloaded_constructor(10));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test2)
|
||||
|
@ -23,7 +23,7 @@
|
||||
namespace move_tests
|
||||
{
|
||||
test::seed_t initialize_seed(98624);
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#define BOOST_UNORDERED_TEST_MOVING 1
|
||||
#else
|
||||
#define BOOST_UNORDERED_TEST_MOVING 0
|
||||
@ -154,7 +154,7 @@ namespace move_tests
|
||||
|
||||
test::random_values<T> v(25, generator);
|
||||
T y(create(v, count, hf, eq, al, 1.0), al);
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
#elif defined(BOOST_HAS_NRVO)
|
||||
BOOST_TEST(
|
||||
|
125
test/unordered/noexcept_tests.cpp
Normal file
125
test/unordered/noexcept_tests.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
|
||||
// Copyright 2013 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
namespace noexcept_tests
|
||||
{
|
||||
// Test the noexcept is set correctly for the move constructor.
|
||||
|
||||
struct hash_possible_exception : boost::hash<int>
|
||||
{
|
||||
hash_possible_exception(hash_possible_exception const&) {}
|
||||
};
|
||||
|
||||
struct equal_to_possible_exception : std::equal_to<int>
|
||||
{
|
||||
equal_to_possible_exception(equal_to_possible_exception const&) {}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(test_noexcept)
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_set<int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multiset<int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_map<int, int> >::value));
|
||||
BOOST_TEST((boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multimap<int, int> >::value));
|
||||
#endif
|
||||
|
||||
BOOST_TEST((!boost::is_nothrow_move_constructible<
|
||||
boost::unordered_set<int, hash_possible_exception>
|
||||
>::value));
|
||||
BOOST_TEST((!boost::is_nothrow_move_constructible<
|
||||
boost::unordered_multiset<int, boost::hash<int>,
|
||||
equal_to_possible_exception>
|
||||
>::value));
|
||||
}
|
||||
|
||||
// Test that the move constructor does actually move without throwing
|
||||
// an exception when it claims to.
|
||||
|
||||
struct test_exception {};
|
||||
|
||||
bool throwing_test_exception = false;
|
||||
void test_throw(char const* name) {
|
||||
if (throwing_test_exception) {
|
||||
std::cerr << "Throw exception in: " << name << std::endl;
|
||||
throw test_exception();
|
||||
}
|
||||
}
|
||||
|
||||
class hash_nothrow_move : boost::hash<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
|
||||
|
||||
typedef boost::hash<int> base;
|
||||
public:
|
||||
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
|
||||
BOOST_NOEXCEPT {}
|
||||
|
||||
hash_nothrow_move() { test_throw("Constructor"); }
|
||||
hash_nothrow_move(hash_nothrow_move const& x) { test_throw("Copy"); }
|
||||
hash_nothrow_move& operator=(hash_nothrow_move const&)
|
||||
{ test_throw("Assign"); return *this; }
|
||||
std::size_t operator()(int x) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
|
||||
};
|
||||
|
||||
class equal_to_nothrow_move : std::equal_to<int>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
|
||||
|
||||
typedef std::equal_to<int> base;
|
||||
public:
|
||||
equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
|
||||
BOOST_NOEXCEPT {}
|
||||
equal_to_nothrow_move() { test_throw("Constructor"); }
|
||||
equal_to_nothrow_move(equal_to_nothrow_move const& x)
|
||||
{ test_throw("Copy"); }
|
||||
equal_to_nothrow_move& operator=(equal_to_nothrow_move const&)
|
||||
{ test_throw("Assign"); return *this; }
|
||||
std::size_t operator()(int x, int y) const
|
||||
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
|
||||
{
|
||||
typedef boost::unordered_set<int,
|
||||
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
|
||||
|
||||
if (boost::is_nothrow_move_constructible<throwing_set>::value)
|
||||
{
|
||||
throwing_test_exception = false;
|
||||
|
||||
throwing_set x1;
|
||||
x1.insert(10);
|
||||
x1.insert(50);
|
||||
|
||||
|
||||
try {
|
||||
throwing_test_exception = true;
|
||||
|
||||
throwing_set x2 = boost::move(x1);
|
||||
BOOST_TEST(x2.size() == 2);
|
||||
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
|
||||
} catch(test_exception) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
throwing_test_exception = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
@ -195,7 +195,7 @@ namespace unnecessary_copy_tests
|
||||
reset();
|
||||
T x;
|
||||
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1);
|
||||
#else
|
||||
COPY_COUNT(2);
|
||||
@ -215,7 +215,7 @@ namespace unnecessary_copy_tests
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#else
|
||||
// Since std::pair isn't movable, move only works for sets.
|
||||
@ -249,7 +249,7 @@ namespace unnecessary_copy_tests
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
@ -285,8 +285,8 @@ namespace unnecessary_copy_tests
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#else
|
||||
@ -313,7 +313,7 @@ namespace unnecessary_copy_tests
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0); MOVE_COUNT(1);
|
||||
@ -374,7 +374,7 @@ namespace unnecessary_copy_tests
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
|
||||
// This is a little odd, Visual C++ 11 seems to move the pair, which
|
||||
// results in one copy (for the const key) and one move (for the
|
||||
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
|
||||
|
Reference in New Issue
Block a user