Compare commits

..

7 Commits

Author SHA1 Message Date
Marshall Clow 79900798e6 Release 1.54.0
[SVN r84923]
2013-07-01 16:53:14 +00:00
Daniel James 0c7c7cc6ad Merge some change log entries to release.
[SVN r84497]
2013-05-25 15:53:49 +00:00
Daniel James bd10a8b5aa Merge initial unordered use of noexcept + friends.
Still more to come, hopefully in time for the release.


[SVN r84304]
2013-05-16 22:15:42 +00:00
Daniel James 0221f1a9bd Unordered: Merge assign fix.
[SVN r82651]
2013-01-27 23:10:29 +00:00
Daniel James 34b69e67ee Unordered: Merge test tweaks + inspect fixes from trunk.
[SVN r81922]
2012-12-13 22:39:44 +00:00
Daniel James 654fed166a Unordered: Remove and update various deprecated things.
[SVN r81727]
2012-12-05 22:06:57 +00:00
Daniel James 981f1e2acb Unordered: Merge code clean up.
[SVN r81358]
2012-11-15 13:43:37 +00:00
29 changed files with 649 additions and 1094 deletions
+15
View File
@@ -220,4 +220,19 @@ 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.
[endsect]
+2 -14
View File
@@ -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>
+8 -56
View File
@@ -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>
+44 -165
View File
@@ -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); \
@@ -342,7 +342,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 +432,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(
@@ -763,7 +763,7 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// call_construct
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
@@ -812,7 +812,7 @@ 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> \
@@ -921,62 +921,26 @@ 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)
@@ -985,9 +949,14 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
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)
{
@@ -997,70 +966,13 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
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,16 +1002,35 @@ 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::addressof(address->first), args.a1);
@@ -1107,59 +1038,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
boost::addressof(address->second), args.a2);
}
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
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
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
}}}
+185 -108
View File
@@ -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>
@@ -37,49 +39,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:
typedef typename Node::value_type value_type;
l_iterator() : ptr_() {}
l_iterator(iterator x, std::size_t b, std::size_t c)
: 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();
}
@@ -106,42 +109,44 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
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:
typedef typename Node::value_type value_type;
cl_iterator() : ptr_() {}
cl_iterator(iterator x, std::size_t b, std::size_t c) :
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) :
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();
}
@@ -168,18 +173,21 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
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 +197,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:
typedef typename Node::value_type value_type;
iterator() : node_() {}
explicit iterator(node_pointer const& x) : node_(x) {}
explicit iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
Value& operator*() const {
value_type& operator*() const {
return node_->value();
}
Value* operator->() const {
value_type* operator->() const {
return &node_->value();
}
@@ -226,14 +237,16 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
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 +258,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:
typedef typename Node::value_type value_type;
c_iterator() : node_() {}
explicit c_iterator(node_pointer const& x) : node_(x) {}
explicit c_iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
c_iterator(boost::unordered::iterator_detail::iterator<
NodePointer, Value> const& x) : node_(x.node_) {}
c_iterator(iterator const& x) : node_(x.node_) {}
Value const& operator*() const {
value_type const& operator*() const {
return node_->value();
}
Value const* operator->() const {
value_type const* operator->() const {
return &node_->value();
}
@@ -310,9 +323,6 @@ namespace boost { namespace unordered { namespace detail {
protected:
node_allocator& alloc_;
private:
node_pointer node_;
bool node_constructed_;
bool value_constructed_;
@@ -398,7 +408,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 {
@@ -432,8 +442,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 +454,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 +463,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
@@ -537,12 +547,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 +562,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 +578,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 +672,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,6 +705,11 @@ 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);
@@ -696,6 +720,12 @@ namespace boost { namespace unordered { namespace detail {
new((void*) &funcs_[which]) function_pair(f);
}
void construct(bool which, function_pair& f,
boost::unordered::detail::move_tag m)
{
new((void*) &funcs_[which]) function_pair(f, m);
}
void destroy(bool which)
{
boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
@@ -703,6 +733,9 @@ namespace boost { namespace unordered { namespace detail {
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 +748,17 @@ namespace boost { namespace unordered { namespace detail {
construct(current_, bf.current());
}
functions(functions& bf, boost::unordered::detail::move_tag m)
: current_(false)
{
if (nothrow_move_constructible) {
construct(current_, bf.current(), m);
}
else {
construct(current_, bf.current());
}
}
~functions() {
this->destroy(current_);
}
@@ -727,26 +771,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 +811,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 {
+90 -191
View File
@@ -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_;
+13 -36
View File
@@ -56,7 +56,7 @@ namespace detail {
return no_key();
}
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
@@ -75,11 +75,6 @@ namespace detail {
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,14 +101,13 @@ 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&...)
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
return k;
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
@@ -126,12 +115,6 @@ namespace detail {
}
#else
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
return k;
}
static no_key extract()
{
return no_key();
@@ -150,12 +133,12 @@ namespace detail {
}
#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;
}
};
}}}
+72 -118
View File
@@ -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),
@@ -459,10 +470,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 +509,29 @@ namespace boost { namespace unordered { namespace detail {
delete_buckets();
}
void delete_node(c_iterator n)
void delete_node(link_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
boost::unordered::detail::destroy_value_impl(node_alloc(),
n.node_->value_ptr());
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 +539,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 +559,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 +590,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 +636,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 +664,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 +711,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 +736,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_;
+45 -74
View File
@@ -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_;
@@ -360,8 +353,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 +374,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 +385,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 +511,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 +520,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 +541,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 +574,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 +593,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;
}
}
+48 -50
View File
@@ -120,14 +120,14 @@ namespace unordered
: 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)
: 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
@@ -165,7 +165,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 +178,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 +449,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 +463,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 +501,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);
@@ -602,14 +601,14 @@ namespace unordered
: 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)
: 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
@@ -648,7 +647,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 +660,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 +927,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 +941,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 +979,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);
@@ -1068,7 +1066,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 +1105,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 +1274,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);
}
@@ -1401,7 +1399,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 +1438,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 +1586,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);
}
+48 -50
View File
@@ -118,14 +118,14 @@ namespace unordered
: 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)
: 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
@@ -163,7 +163,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 +176,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 +434,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 +448,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 +486,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);
@@ -586,14 +585,14 @@ namespace unordered
: 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)
: 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
@@ -632,7 +631,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 +644,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 +902,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 +916,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 +954,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);
@@ -1043,7 +1041,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 +1080,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 +1200,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);
}
@@ -1327,7 +1325,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 +1364,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 +1484,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);
}
+2 -1
View File
@@ -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()
+2 -1
View File
@@ -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()
+2 -1
View File
@@ -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()
+4 -3
View File
@@ -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()
+2 -2
View File
@@ -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()
+2 -1
View File
@@ -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()
+23 -8
View File
@@ -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) \
+1 -1
View File
@@ -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)...);
+2 -2
View File
@@ -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.");
+3 -3
View File
@@ -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)...);
}
+1 -1
View File
@@ -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)...);
-4
View File
@@ -34,9 +34,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 +44,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 : :
+2 -2
View File
@@ -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>();
-174
View File
@@ -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()
+23 -19
View File
@@ -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))
)
@@ -658,20 +658,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 +691,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 +712,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)
+2 -2
View File
@@ -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(
+6 -6
View File
@@ -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);