mirror of
https://github.com/boostorg/unordered.git
synced 2026-08-07 14:14:07 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 251c4608d0 | |||
| c788780792 | |||
| e1416d0a3e | |||
| 808f1f939f | |||
| 880d778ab6 | |||
| a8cd8cdd0b | |||
| fa3d93ddbc | |||
| 5622afdafa | |||
| 63d56953af | |||
| 280b1971b6 |
@@ -170,4 +170,33 @@ C++11 support has resulted in some breaking changes:
|
||||
the variadic consturctors define
|
||||
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
|
||||
|
||||
[h2 Boost 1.49.0]
|
||||
|
||||
* Fix warning due to accidental odd assignment.
|
||||
* Slightly better error messages.
|
||||
|
||||
[h2 Boost 1.50.0]
|
||||
|
||||
* Fix equality for `unordered_multiset` and `unordered_multimap`.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
|
||||
Implement `reserve`.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
|
||||
Avoid gcc's `-Wfloat-equal` warning.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
|
||||
Fix some Sun specific code.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
|
||||
Avoid gcc's `-Wshadow` warning.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/6905 Ticket 6905]:
|
||||
Make namespaces in macros compatible with `bcp` custom namespaces.
|
||||
Fixed by Luke Elliott.
|
||||
* Remove some of the smaller prime number of buckets, as they may make
|
||||
collisions quite probable (e.g. multiples of 5 are very common because
|
||||
we used base 10).
|
||||
* On old versions of Visual C++, use the container library's implementation
|
||||
of `allocator_traits`, as it's more likely to work.
|
||||
* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas
|
||||
Wang's hash function to pick which one to use. As modulus is very slow
|
||||
for 64 bit values.
|
||||
* Some internal changes.
|
||||
|
||||
[endsect]
|
||||
|
||||
+12
@@ -963,6 +963,18 @@ EOL;
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
<method name="reserve">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
</method-group>
|
||||
<free-function-group name="Equality Comparisons">
|
||||
<function name="operator==">
|
||||
|
||||
+48
@@ -846,6 +846,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
<method name="reserve">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
</method-group>
|
||||
<free-function-group name="Equality Comparisons">
|
||||
<function name="operator==">
|
||||
@@ -1797,6 +1809,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
<method name="reserve">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
</method-group>
|
||||
<free-function-group name="Equality Comparisons">
|
||||
<function name="operator==">
|
||||
@@ -2793,6 +2817,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
<method name="reserve">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
</method-group>
|
||||
<free-function-group name="Equality Comparisons">
|
||||
<function name="operator==">
|
||||
@@ -3758,6 +3794,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
<method name="reserve">
|
||||
<parameter name="n">
|
||||
<paramtype>size_type</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
|
||||
</throws>
|
||||
</method>
|
||||
</method-group>
|
||||
<free-function-group name="Equality Comparisons">
|
||||
<function name="operator==">
|
||||
|
||||
@@ -15,21 +15,40 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/enum.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#include <boost/unordered/detail/emplace_args.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
|
||||
# include <memory>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pick which version of allocator_traits to use
|
||||
//
|
||||
// 0 = Own partial implementation
|
||||
// 1 = std::allocator_traits
|
||||
// 2 = boost::container::allocator_traits
|
||||
|
||||
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
||||
# elif defined(BOOST_MSVC)
|
||||
# if BOOST_MSVC < 1400
|
||||
// Use container's allocator_traits for older versions of Visual
|
||||
// C++ as I don't test with them.
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some utilities for implementing allocator_traits, but useful elsewhere so
|
||||
// they're always defined.
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
|
||||
# include <type_traits>
|
||||
#endif
|
||||
@@ -75,48 +94,22 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Bits and pieces for implementing traits
|
||||
// Expression test mechanism
|
||||
//
|
||||
// Some of these are also used elsewhere
|
||||
|
||||
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
||||
struct choice9 { typedef char (&type)[9]; };
|
||||
struct choice8 : choice9 { typedef char (&type)[8]; };
|
||||
struct choice7 : choice8 { typedef char (&type)[7]; };
|
||||
struct choice6 : choice7 { typedef char (&type)[6]; };
|
||||
struct choice5 : choice6 { typedef char (&type)[5]; };
|
||||
struct choice4 : choice5 { typedef char (&type)[4]; };
|
||||
struct choice3 : choice4 { typedef char (&type)[3]; };
|
||||
struct choice2 : choice3 { typedef char (&type)[2]; };
|
||||
struct choice1 : choice2 { typedef char (&type)[1]; };
|
||||
choice1 choose();
|
||||
|
||||
typedef choice1::type yes_type;
|
||||
typedef choice2::type no_type;
|
||||
|
||||
struct private_type
|
||||
{
|
||||
private_type const &operator,(int) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
no_type is_private_type(T const&);
|
||||
yes_type is_private_type(private_type const&);
|
||||
|
||||
struct convert_from_anything {
|
||||
template <typename T>
|
||||
convert_from_anything(T const&);
|
||||
};
|
||||
// When SFINAE expressions are available, define
|
||||
// BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
|
||||
// supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
|
||||
// can detect if a class has the specified member, but not that it has the
|
||||
// correct type, this is good enough for a passable impression of
|
||||
// allocator_traits.
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
|
||||
|
||||
template <typename T, unsigned int> struct expr_test;
|
||||
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
||||
template <typename U> static char for_expr_test(U const&);
|
||||
|
||||
#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
|
||||
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
|
||||
template <typename U> \
|
||||
static typename boost::unordered::detail::expr_test< \
|
||||
BOOST_PP_CAT(choice, result), \
|
||||
@@ -125,12 +118,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
0)))>::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
|
||||
# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
|
||||
template <typename U> \
|
||||
static BOOST_PP_CAT(choice, result)::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
|
||||
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
|
||||
struct BOOST_PP_CAT(has_, name) \
|
||||
{ \
|
||||
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
|
||||
@@ -142,11 +135,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
|
||||
|
||||
template <typename T> struct identity { typedef T type; };
|
||||
|
||||
#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
||||
# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
||||
\
|
||||
typedef typename boost::unordered::detail::identity<member>::type \
|
||||
BOOST_PP_CAT(check, count); \
|
||||
@@ -160,11 +151,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_PP_CAT(test, count)<&U::name>::type \
|
||||
test(BOOST_PP_CAT(choice, count))
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
|
||||
# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
|
||||
template <class U> static BOOST_PP_CAT(choice, result)::type \
|
||||
test(BOOST_PP_CAT(choice, count))
|
||||
|
||||
#define BOOST_UNORDERED_HAS_MEMBER(name) \
|
||||
# define BOOST_UNORDERED_HAS_MEMBER(name) \
|
||||
struct BOOST_PP_CAT(has_, name) \
|
||||
{ \
|
||||
struct impl { \
|
||||
@@ -184,84 +175,90 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator traits
|
||||
//
|
||||
// Uses the standard versions if available.
|
||||
// (although untested as I don't have access to a standard version yet)
|
||||
}}}
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Allocator traits
|
||||
//
|
||||
// First our implementation, then later light wrappers around the alternatives
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits : std::allocator_traits<Alloc> {};
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename std::allocator_traits<Alloc>::rebind_alloc<T> type;
|
||||
};
|
||||
# include <boost/limits.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# include <boost/pointer_to_other.hpp>
|
||||
# if defined(BOOST_NO_SFINAE_EXPR)
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# endif
|
||||
|
||||
#else
|
||||
# if defined(BOOST_UNORDERED_VARIADIC_MOVE) && \
|
||||
!defined(BOOST_NO_SFINAE_EXPR)
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||
# else
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||
# endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
|
||||
type;
|
||||
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice1::type test(choice1, typename X::tname* = 0); \
|
||||
template <typename X> \
|
||||
static choice1::type test(choice1, typename X::tname* = 0); \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2, void* = 0); \
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2, void* = 0); \
|
||||
\
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
\
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
\
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
template <typename T, typename T2>
|
||||
struct sfinae : T2 {};
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
\
|
||||
template <typename X> \
|
||||
static typename boost::unordered::detail::sfinae< \
|
||||
typename X::tname, choice1>::type \
|
||||
test(choice1); \
|
||||
template <typename X> \
|
||||
static typename boost::unordered::detail::sfinae< \
|
||||
typename X::tname, choice1>::type \
|
||||
test(choice1); \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2); \
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2); \
|
||||
\
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
\
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
\
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
typedef typename boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
|
||||
typename default_type_ ## tname<T, arg>::type
|
||||
# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
|
||||
typename default_type_ ## tname<T, arg>::type
|
||||
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
|
||||
@@ -273,7 +270,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
|
||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
|
||||
|
||||
#if BOOST_UNORDERED_HAVE_CALL_DETECTION
|
||||
# if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
select_on_container_copy_construction, U const, (), 0
|
||||
@@ -284,18 +282,33 @@ namespace boost { namespace unordered { namespace detail {
|
||||
max_size, U const, (), 0
|
||||
);
|
||||
|
||||
# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
template <typename T, typename ValueType, typename... Args>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
construct, U, (
|
||||
boost::unordered::detail::make<ValueType*>(),
|
||||
boost::unordered::detail::make<Args const>()...), 2
|
||||
);
|
||||
|
||||
# else
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
construct, U, (
|
||||
boost::unordered::detail::make<ValueType*>(),
|
||||
boost::unordered::detail::make<ValueType const>()), 2
|
||||
construct, U, (
|
||||
boost::unordered::detail::make<ValueType*>(),
|
||||
boost::unordered::detail::make<ValueType const>()), 2
|
||||
);
|
||||
|
||||
# endif
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_FUNCTION(
|
||||
destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
|
||||
);
|
||||
#else
|
||||
|
||||
# else
|
||||
|
||||
template <typename T>
|
||||
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
|
||||
|
||||
@@ -307,7 +320,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename T, typename ValueType>
|
||||
BOOST_UNORDERED_HAS_MEMBER(destroy);
|
||||
#endif
|
||||
|
||||
# endif
|
||||
|
||||
template <typename Alloc>
|
||||
inline typename boost::enable_if_c<
|
||||
@@ -375,7 +389,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// TODO: rebind_alloc and rebind_traits
|
||||
|
||||
static pointer allocate(Alloc& a, size_type n)
|
||||
static pointer allocate(Alloc& a, size_type n)
|
||||
{ return a.allocate(n); }
|
||||
|
||||
// I never use this, so I'll just comment it out for now.
|
||||
@@ -383,13 +397,49 @@ namespace boost { namespace unordered { namespace detail {
|
||||
//static pointer allocate(Alloc& a, size_type n,
|
||||
// const_void_pointer hint)
|
||||
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
|
||||
|
||||
|
||||
static void deallocate(Alloc& a, pointer p, size_type n)
|
||||
{ a.deallocate(p, n); }
|
||||
|
||||
public:
|
||||
|
||||
// Only supporting the basic copy constructor for now.
|
||||
# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||
::value>::type
|
||||
construct(Alloc& a, T* p, Args&&... x)
|
||||
{
|
||||
a.construct(p, boost::forward<Args>(x)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||
::value>::type
|
||||
construct(Alloc&, T* p, Args&&... x)
|
||||
{
|
||||
new ((void*) p) T(boost::forward<Args>(x)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc& a, T* p)
|
||||
{
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# elif !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
@@ -423,19 +473,67 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
// If we don't have SFINAE expressions, only call construct for the
|
||||
// copy constructor for the allocator's value_type - as that's
|
||||
// the only construct method that old fashioned allocators support.
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
construct(Alloc& a, T* p, T const& x)
|
||||
{
|
||||
a.construct(p, x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
construct(Alloc&, T* p, T const& x)
|
||||
{
|
||||
new ((void*) p) T(x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::enable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
destroy(Alloc& a, T* p)
|
||||
{
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename boost::disable_if_c<
|
||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||
boost::is_same<T, value_type>::value
|
||||
>::type
|
||||
destroy(Alloc&, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
static size_type max_size(const Alloc& a)
|
||||
{
|
||||
return boost::unordered::detail::call_max_size<size_type>(a);
|
||||
}
|
||||
|
||||
// Allocator propagation on construction
|
||||
|
||||
|
||||
static Alloc select_on_container_copy_construction(Alloc const& rhs)
|
||||
{
|
||||
return boost::unordered::detail::
|
||||
call_select_on_container_copy_construction(rhs);
|
||||
}
|
||||
|
||||
|
||||
// Allocator propagation on assignment and swap.
|
||||
// Return true if lhs is modified.
|
||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
||||
@@ -448,12 +546,117 @@ namespace boost { namespace unordered { namespace detail {
|
||||
Alloc,propagate_on_container_swap,false_type)
|
||||
propagate_on_container_swap;
|
||||
};
|
||||
}}}
|
||||
|
||||
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
||||
#undef BOOST_UNORDERED_DEFAULT_TYPE
|
||||
# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
||||
# undef BOOST_UNORDERED_DEFAULT_TYPE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// std::allocator_traits
|
||||
|
||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
|
||||
# include <memory>
|
||||
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits : std::allocator_traits<Alloc> {};
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename std::allocator_traits<Alloc>::
|
||||
template rebind_alloc<T> type;
|
||||
};
|
||||
}}}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// boost::container::allocator_traits
|
||||
|
||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
||||
|
||||
# include <boost/container/allocator_traits.hpp>
|
||||
|
||||
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename Alloc>
|
||||
struct allocator_traits :
|
||||
boost::container::allocator_traits<Alloc> {};
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap :
|
||||
boost::container::allocator_traits<Alloc>::
|
||||
template portable_rebind_alloc<T>
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#else
|
||||
|
||||
#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some helper functions for allocating & constructing
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// construct_node/destroy_node
|
||||
//
|
||||
// Construct a node using the best available method.
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
|
||||
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::construct(
|
||||
a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_node(Alloc& a, T* p)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
boost::unordered::detail::allocator_traits<Alloc>::construct(a, p, T());
|
||||
try {
|
||||
boost::unordered::detail::construct_impl(
|
||||
p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
} catch(...) {
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_node(Alloc& a, T* p)
|
||||
{
|
||||
boost::unordered::detail::destroy(p->value_ptr());
|
||||
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// array_constructor
|
||||
//
|
||||
// Allocate and construct an array in an exception safe manner, and
|
||||
@@ -509,7 +712,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
ptr_ = pointer();
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
array_constructor(array_constructor const&);
|
||||
array_constructor& operator=(array_constructor const&);
|
||||
};
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/unordered/detail/emplace_args.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
@@ -29,7 +30,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename Types> struct table;
|
||||
template <typename NodePointer> struct bucket;
|
||||
struct ptr_bucket;
|
||||
template <typename A, typename Bucket, typename Node> struct buckets;
|
||||
template <typename A, typename Bucket, typename Node, typename Policy>
|
||||
struct buckets;
|
||||
template <typename Types> struct table_impl;
|
||||
template <typename Types> struct grouped_table_impl;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -49,16 +53,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_allocator& alloc_;
|
||||
node_pointer node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
bool constructed_;
|
||||
|
||||
public:
|
||||
|
||||
node_constructor(node_allocator& n) :
|
||||
alloc_(n),
|
||||
node_(),
|
||||
node_constructed_(false),
|
||||
value_constructed_(false)
|
||||
constructed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -69,26 +71,40 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
|
||||
boost::unordered::detail::construct_impl(
|
||||
node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
value_constructed_ = true;
|
||||
BOOST_ASSERT(node_ && !constructed_);
|
||||
boost::unordered::detail::construct_node(alloc_,
|
||||
boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||
constructed_ = true;
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
void construct_value2(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
|
||||
boost::unordered::detail::construct_impl2(
|
||||
node_->value_ptr(), boost::forward<A0>(a0));
|
||||
value_constructed_ = true;
|
||||
BOOST_ASSERT(node_ && !constructed_);
|
||||
# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
boost::unordered::detail::construct_node(alloc_,
|
||||
boost::addressof(*node_), boost::forward<A0>(a0));
|
||||
# else
|
||||
boost::unordered::detail::construct_node(alloc_,
|
||||
boost::addressof(*node_),
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0)));
|
||||
# endif
|
||||
constructed_ = true;
|
||||
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||
}
|
||||
|
||||
value_type const& value() const {
|
||||
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
|
||||
BOOST_ASSERT(node_ && constructed_);
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
node_pointer get()
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
// no throw
|
||||
node_pointer release()
|
||||
{
|
||||
@@ -106,12 +122,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor<Alloc>::~node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
boost::unordered::detail::destroy(node_->value_ptr());
|
||||
}
|
||||
|
||||
if (node_constructed_) {
|
||||
node_allocator_traits::destroy(alloc_,
|
||||
if (constructed_) {
|
||||
boost::unordered::detail::destroy_node(alloc_,
|
||||
boost::addressof(*node_));
|
||||
}
|
||||
|
||||
@@ -123,24 +135,13 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void node_constructor<Alloc>::construct_node()
|
||||
{
|
||||
if(!node_) {
|
||||
node_constructed_ = false;
|
||||
value_constructed_ = false;
|
||||
|
||||
constructed_ = false;
|
||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||
|
||||
node_allocator_traits::construct(alloc_,
|
||||
boost::addressof(*node_), node());
|
||||
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||
node_constructed_ = true;
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_);
|
||||
|
||||
if (value_constructed_)
|
||||
{
|
||||
boost::unordered::detail::destroy(node_->value_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
else if (constructed_) {
|
||||
boost::unordered::detail::destroy_node(alloc_,
|
||||
boost::addressof(*node_));
|
||||
constructed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,12 +180,373 @@ namespace boost { namespace unordered { namespace detail {
|
||||
enum { extra_node = false };
|
||||
};
|
||||
|
||||
template <typename LinkPointer>
|
||||
struct node_base
|
||||
{
|
||||
typedef LinkPointer link_pointer;
|
||||
link_pointer next_;
|
||||
|
||||
node_base() : next_() {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
//
|
||||
// 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;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename NodePointer, typename Value, typename Policy>
|
||||
struct l_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename ConstNodePointer, typename NodePointer2,
|
||||
typename Value2, 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;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
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 {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
l_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
|
||||
!= bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
|
||||
l_iterator operator++(int) {
|
||||
l_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(l_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
|
||||
bool operator!=(l_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value,
|
||||
typename Policy>
|
||||
struct cl_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::l_iterator
|
||||
<NodePointer, Value, Policy>;
|
||||
private:
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
|
||||
iterator;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
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) :
|
||||
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
|
||||
{}
|
||||
|
||||
Value const&
|
||||
operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
cl_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
|
||||
!= bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
|
||||
cl_iterator operator++(int) {
|
||||
cl_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
|
||||
return x.ptr_ == y.ptr_;
|
||||
}
|
||||
|
||||
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
|
||||
return x.ptr_ != y.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodePointer, typename Value>
|
||||
struct iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename, typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::c_iterator;
|
||||
template <typename, typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::l_iterator;
|
||||
template <typename, typename, typename, typename>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::table;
|
||||
template <typename, typename, typename, typename>
|
||||
friend struct boost::unordered::detail::buckets;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::table_impl;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::grouped_table_impl;
|
||||
private:
|
||||
#endif
|
||||
typedef NodePointer node_pointer;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
iterator() : node_() {}
|
||||
|
||||
explicit iterator(node_pointer const& x) : node_(x) {}
|
||||
|
||||
Value& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
iterator& operator++() {
|
||||
node_ = static_cast<node_pointer>(node_->next_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
iterator tmp(node_);
|
||||
node_ = static_cast<node_pointer>(node_->next_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(iterator const& x) const {
|
||||
return node_ == x.node_;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const& x) const {
|
||||
return node_ != x.node_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value>
|
||||
struct c_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value>;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::table;
|
||||
template <typename, typename, typename, typename>
|
||||
friend struct boost::unordered::detail::buckets;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::table_impl;
|
||||
template <typename>
|
||||
friend struct boost::unordered::detail::grouped_table_impl;
|
||||
|
||||
private:
|
||||
#endif
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
|
||||
iterator;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
c_iterator() : node_() {}
|
||||
|
||||
explicit c_iterator(node_pointer const& x) : node_(x) {}
|
||||
|
||||
c_iterator(boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value> const& x) : node_(x.node_) {}
|
||||
|
||||
Value const& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
c_iterator& operator++() {
|
||||
node_ = static_cast<node_pointer>(node_->next_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
c_iterator operator++(int) {
|
||||
c_iterator tmp(node_);
|
||||
node_ = static_cast<node_pointer>(node_->next_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(c_iterator const& x, c_iterator const& y) {
|
||||
return x.node_ == y.node_;
|
||||
}
|
||||
|
||||
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
|
||||
return x.node_ != y.node_;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hash Policy
|
||||
//
|
||||
// Don't really want buckets to derive from this, but will for now.
|
||||
|
||||
template <typename SizeT>
|
||||
struct prime_policy
|
||||
{
|
||||
template <typename Hash, typename T>
|
||||
static inline SizeT apply_hash(Hash const& hf, T const& x) {
|
||||
return hf(x);
|
||||
}
|
||||
|
||||
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
|
||||
return hash % bucket_count;
|
||||
}
|
||||
|
||||
static inline SizeT new_bucket_count(SizeT min) {
|
||||
return boost::unordered::detail::next_prime(min);
|
||||
}
|
||||
|
||||
static inline SizeT prev_bucket_count(SizeT max) {
|
||||
return boost::unordered::detail::prev_prime(max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SizeT>
|
||||
struct mix64_policy
|
||||
{
|
||||
template <typename Hash, typename T>
|
||||
static inline SizeT apply_hash(Hash const& hf, T const& x) {
|
||||
SizeT key = hf(x);
|
||||
key = (~key) + (key << 21); // key = (key << 21) - key - 1;
|
||||
key = key ^ (key >> 24);
|
||||
key = (key + (key << 3)) + (key << 8); // key * 265
|
||||
key = key ^ (key >> 14);
|
||||
key = (key + (key << 2)) + (key << 4); // key * 21
|
||||
key = key ^ (key >> 28);
|
||||
key = key + (key << 31);
|
||||
return key;
|
||||
}
|
||||
|
||||
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
|
||||
return hash & (bucket_count - 1);
|
||||
}
|
||||
|
||||
static inline SizeT new_bucket_count(SizeT min) {
|
||||
if (min <= 4) return 4;
|
||||
--min;
|
||||
min |= min >> 1;
|
||||
min |= min >> 2;
|
||||
min |= min >> 4;
|
||||
min |= min >> 8;
|
||||
min |= min >> 16;
|
||||
min |= min >> 32;
|
||||
return min + 1;
|
||||
}
|
||||
|
||||
static inline SizeT prev_bucket_count(SizeT max) {
|
||||
max |= max >> 1;
|
||||
max |= max >> 2;
|
||||
max |= max >> 4;
|
||||
max |= max >> 8;
|
||||
max |= max >> 16;
|
||||
max |= max >> 32;
|
||||
return (max >> 1) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <int digits, int radix>
|
||||
struct pick_policy_impl {
|
||||
typedef prime_policy<std::size_t> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pick_policy_impl<64, 2> {
|
||||
typedef mix64_policy<std::size_t> type;
|
||||
};
|
||||
|
||||
struct pick_policy :
|
||||
pick_policy_impl<
|
||||
std::numeric_limits<std::size_t>::digits,
|
||||
std::numeric_limits<std::size_t>::radix> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Buckets
|
||||
|
||||
template <typename A, typename Bucket, typename Node>
|
||||
struct buckets
|
||||
template <typename A, typename Bucket, typename Node, typename Policy>
|
||||
struct buckets : Policy
|
||||
{
|
||||
private:
|
||||
buckets(buckets const&);
|
||||
@@ -193,6 +555,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::allocator_traits<A> traits;
|
||||
typedef typename traits::value_type value_type;
|
||||
|
||||
typedef Policy policy;
|
||||
typedef Node node;
|
||||
typedef Bucket bucket;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
|
||||
@@ -214,6 +577,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node_pointer, value_type> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node_pointer, value_type, policy> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<const_node_pointer, node_pointer, value_type, policy>
|
||||
cl_iterator;
|
||||
|
||||
// Members
|
||||
|
||||
bucket_pointer buckets_;
|
||||
@@ -247,7 +620,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::size_t max_bucket_count() const
|
||||
{
|
||||
// -1 to account for the start bucket.
|
||||
return boost::unordered::detail::prev_prime(
|
||||
return policy::prev_bucket_count(
|
||||
bucket_allocator_traits::max_size(bucket_alloc()) - 1);
|
||||
}
|
||||
|
||||
@@ -266,16 +639,17 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return this->get_bucket(bucket_index)->next_;
|
||||
}
|
||||
|
||||
node_pointer get_start() const
|
||||
iterator get_start() const
|
||||
{
|
||||
return static_cast<node_pointer>(this->get_previous_start()->next_);
|
||||
return iterator(static_cast<node_pointer>(
|
||||
this->get_previous_start()->next_));
|
||||
}
|
||||
|
||||
node_pointer get_start(std::size_t bucket_index) const
|
||||
iterator get_start(std::size_t bucket_index) const
|
||||
{
|
||||
previous_pointer prev = this->get_previous_start(bucket_index);
|
||||
return prev ? static_cast<node_pointer>(prev->next_) :
|
||||
node_pointer();
|
||||
return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
|
||||
iterator();
|
||||
}
|
||||
|
||||
float load_factor() const
|
||||
@@ -288,14 +662,15 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::size_t bucket_size(std::size_t index) const
|
||||
{
|
||||
if (!this->size_) return 0;
|
||||
node_pointer ptr = this->get_start(index);
|
||||
if (!ptr) return 0;
|
||||
iterator it = this->get_start(index);
|
||||
if (!it.node_) return 0;
|
||||
|
||||
std::size_t count = 0;
|
||||
while(ptr && ptr->hash_ % this->bucket_count_ == index)
|
||||
while(it.node_ && policy::to_bucket(
|
||||
this->bucket_count_, it.node_->hash_) == index)
|
||||
{
|
||||
++count;
|
||||
ptr = static_cast<node_pointer>(ptr->next_);
|
||||
++it;
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -349,6 +724,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
|
||||
// Since this node is just to mark the beginning it doesn't
|
||||
// contain a value, so just construct node::node_base
|
||||
// which containers the pointer to the next element.
|
||||
node_allocator_traits::construct(node_alloc(),
|
||||
static_cast<typename node::node_base*>(
|
||||
boost::addressof(*a.get())),
|
||||
typename node::node_base());
|
||||
|
||||
(constructor.get() +
|
||||
static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
|
||||
a.release();
|
||||
@@ -391,21 +774,21 @@ namespace boost { namespace unordered { namespace detail {
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Delete/destruct
|
||||
|
||||
inline void delete_node(node_pointer n)
|
||||
inline void delete_node(c_iterator n)
|
||||
{
|
||||
boost::unordered::detail::destroy(n->value_ptr());
|
||||
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
boost::unordered::detail::destroy_node(
|
||||
node_alloc(), boost::addressof(*n.node_));
|
||||
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
|
||||
--size_;
|
||||
}
|
||||
|
||||
std::size_t delete_nodes(node_pointer begin, node_pointer end)
|
||||
std::size_t delete_nodes(c_iterator begin, c_iterator end)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
|
||||
while(begin != end) {
|
||||
node_pointer n = begin;
|
||||
begin = static_cast<node_pointer>(begin->next_);
|
||||
c_iterator n = begin;
|
||||
++begin;
|
||||
delete_node(n);
|
||||
++count;
|
||||
}
|
||||
@@ -416,7 +799,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
inline void delete_extra_node(bucket_pointer) {}
|
||||
|
||||
inline void delete_extra_node(node_pointer n) {
|
||||
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
|
||||
node_allocator_traits::destroy(node_alloc(),
|
||||
static_cast<typename node::node_base*>(boost::addressof(*n)));
|
||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||
}
|
||||
|
||||
@@ -433,7 +817,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
while(prev->next_) {
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = n->next_;
|
||||
delete_node(n);
|
||||
delete_node(iterator(n));
|
||||
}
|
||||
|
||||
delete_extra_node(prev);
|
||||
@@ -463,7 +847,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
while(prev->next_) {
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
prev->next_ = n->next_;
|
||||
delete_node(n);
|
||||
delete_node(iterator(n));
|
||||
}
|
||||
|
||||
bucket_pointer end = this->get_bucket(this->bucket_count_);
|
||||
@@ -477,22 +861,24 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// This is called after erasing a node or group of nodes to fix up
|
||||
// the bucket pointers.
|
||||
void fix_buckets(bucket_pointer bucket,
|
||||
void fix_buckets(bucket_pointer this_bucket,
|
||||
previous_pointer prev, node_pointer next)
|
||||
{
|
||||
if (!next)
|
||||
{
|
||||
if (bucket->next_ == prev) bucket->next_ = node_pointer();
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = node_pointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
bucket_pointer next_bucket = this->get_bucket(
|
||||
next->hash_ % this->bucket_count_);
|
||||
policy::to_bucket(this->bucket_count_, next->hash_));
|
||||
|
||||
if (next_bucket != bucket)
|
||||
if (next_bucket != this_bucket)
|
||||
{
|
||||
next_bucket->next_ = prev;
|
||||
if (bucket->next_ == prev) bucket->next_ = node_pointer();
|
||||
if (this_bucket->next_ == prev)
|
||||
this_bucket->next_ = node_pointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,7 +899,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (n == end) return;
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
n->hash_ % this->bucket_count_;
|
||||
policy::to_bucket(this->bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
break;
|
||||
@@ -529,7 +915,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (n == end) break;
|
||||
|
||||
std::size_t new_bucket_index =
|
||||
n->hash_ % this->bucket_count_;
|
||||
policy::to_bucket(this->bucket_count_, n->hash_);
|
||||
if (bucket_index != new_bucket_index) {
|
||||
bucket_index = new_bucket_index;
|
||||
this->get_bucket(bucket_index)->next_ = previous_pointer();
|
||||
@@ -538,7 +924,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Finally fix the bucket containing the trailing node.
|
||||
if (n) {
|
||||
this->get_bucket(n->hash_ % this->bucket_count_)->next_
|
||||
this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, n->hash_))->next_
|
||||
= prev;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/inc.hpp>
|
||||
@@ -21,7 +22,10 @@
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
@@ -40,35 +44,54 @@
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
|
||||
# elif defined(_LIBCPP_VERSION)
|
||||
# define BOOST_UNORDERED_STD_FORWARD_MOVE
|
||||
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
|
||||
# define BOOST_UNORDERED_STD_FORWARD_MOVE
|
||||
# endif
|
||||
# elif defined(__STL_CONFIG_H)
|
||||
# elif defined(__MSL_CPP__)
|
||||
# elif defined(__IBMCPP__)
|
||||
# elif defined(MSIPL_COMPILE_H)
|
||||
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
|
||||
# endif
|
||||
#define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Bits and pieces for implementing traits
|
||||
|
||||
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
||||
struct choice9 { typedef char (&type)[9]; };
|
||||
struct choice8 : choice9 { typedef char (&type)[8]; };
|
||||
struct choice7 : choice8 { typedef char (&type)[7]; };
|
||||
struct choice6 : choice7 { typedef char (&type)[6]; };
|
||||
struct choice5 : choice6 { typedef char (&type)[5]; };
|
||||
struct choice4 : choice5 { typedef char (&type)[4]; };
|
||||
struct choice3 : choice4 { typedef char (&type)[3]; };
|
||||
struct choice2 : choice3 { typedef char (&type)[2]; };
|
||||
struct choice1 : choice2 { typedef char (&type)[1]; };
|
||||
choice1 choose();
|
||||
|
||||
typedef choice1::type yes_type;
|
||||
typedef choice2::type no_type;
|
||||
|
||||
struct private_type
|
||||
{
|
||||
private_type const &operator,(int) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
no_type is_private_type(T const&);
|
||||
yes_type is_private_type(private_type const&);
|
||||
|
||||
struct convert_from_anything {
|
||||
template <typename T>
|
||||
convert_from_anything(T const&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// emplace_args
|
||||
//
|
||||
// Either forwarding variadic arguments, or storing the arguments in
|
||||
// emplace_args##n
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
|
||||
#define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args
|
||||
#define BOOST_UNORDERED_EMPLACE_FORWARD std::forward<Args>(args)...
|
||||
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
|
||||
|
||||
#else
|
||||
|
||||
@@ -88,7 +111,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{ \
|
||||
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
|
||||
BOOST_PP_CAT(emplace_args, n) ( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, a) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
|
||||
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
|
||||
{} \
|
||||
\
|
||||
@@ -98,12 +121,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
inline BOOST_PP_CAT(emplace_args, n) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
|
||||
> create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
|
||||
) \
|
||||
{ \
|
||||
BOOST_PP_CAT(emplace_args, n) < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
|
||||
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \
|
||||
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
@@ -115,7 +138,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
|
||||
BOOST_PP_CAT(a, n)( \
|
||||
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(a, n)))
|
||||
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(b, n)))
|
||||
|
||||
#else
|
||||
|
||||
@@ -125,7 +148,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
|
||||
|
||||
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
|
||||
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
|
||||
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -173,9 +196,11 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
|
||||
//
|
||||
// Used for piecewise construction.
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
#if !defined(__SUNPRO_CC)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
template<typename T> \
|
||||
void construct_from_tuple(T* ptr, namespace_::tuple<>) \
|
||||
void construct_from_tuple(T* ptr, namespace_ tuple<>) \
|
||||
{ \
|
||||
new ((void*) ptr) T(); \
|
||||
} \
|
||||
@@ -183,29 +208,74 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
|
||||
BOOST_PP_REPEAT_FROM_TO(1, n, \
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
|
||||
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
void construct_from_tuple(T* ptr, \
|
||||
namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
{ \
|
||||
new ((void*) ptr) T( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
|
||||
namespace_::get<n>(x)
|
||||
# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
|
||||
namespace_ get<n>(x)
|
||||
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
|
||||
#else
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
template <int N> struct length {};
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
|
||||
template<typename T> \
|
||||
void construct_from_tuple_impl( \
|
||||
boost::unordered::detail::length<0>, T* ptr, \
|
||||
namespace_ tuple<>) \
|
||||
{ \
|
||||
new ((void*) ptr) T(); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT_FROM_TO(1, n, \
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
|
||||
|
||||
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
|
||||
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
void construct_from_tuple_impl( \
|
||||
boost::unordered::detail::length<n>, T* ptr, \
|
||||
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
|
||||
{ \
|
||||
new ((void*) ptr) T( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
|
||||
); \
|
||||
}
|
||||
|
||||
# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
|
||||
namespace_ get<n>(x)
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
|
||||
#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
|
||||
#endif
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
|
||||
#undef BOOST_UNORDERED_GET_TUPLE_ARG
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
|
||||
template <typename T, typename Tuple>
|
||||
void construct_from_tuple(T* ptr, Tuple const& x)
|
||||
{
|
||||
construct_from_tuple_impl(
|
||||
boost::unordered::detail::length<
|
||||
boost::tuples::length<Tuple>::value>(),
|
||||
ptr, x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SFINAE traits for construction.
|
||||
|
||||
@@ -257,7 +327,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from variadic parameters
|
||||
@@ -265,7 +335,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
template <typename T, typename... Args>
|
||||
inline void construct_impl(T* address, Args&&... args)
|
||||
{
|
||||
new((void*) address) T(std::forward<Args>(args)...);
|
||||
new((void*) address) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename A, typename B, typename A0, typename A1, typename A2>
|
||||
@@ -284,7 +354,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
inline typename enable_if<emulation1<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address, A0&& a0)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->second)) B();
|
||||
}
|
||||
|
||||
@@ -292,10 +362,10 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
inline typename enable_if<emulation3<A, B, A0>, void>::type
|
||||
construct_impl(std::pair<A, B>* address, A0&& a0, A1&& a1, A2&& a2)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
std::forward<A1>(a1),
|
||||
std::forward<A2>(a2));
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
template <typename A, typename B,
|
||||
@@ -304,17 +374,17 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
inline void construct_impl(std::pair<A, B>* address,
|
||||
A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args)
|
||||
{
|
||||
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
|
||||
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
|
||||
|
||||
new((void*) boost::addressof(address->second)) B(
|
||||
std::forward<A1>(a1),
|
||||
std::forward<A2>(a2),
|
||||
std::forward<A3>(a3),
|
||||
std::forward<Args>(args)...);
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2),
|
||||
boost::forward<A3>(a3),
|
||||
boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#else // BOOST_UNORDERED_STD_FORWARD_MOVE
|
||||
#else // BOOST_UNORDERED_VARIADIC_MOVE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Construct from emplace_args
|
||||
@@ -334,7 +404,32 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
args.a)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
template <typename T, typename A0>
|
||||
inline void construct_impl(T* address, emplace_args1<A0> const& args)
|
||||
{
|
||||
new((void*) address) T(boost::forward<A0>(args.a0));
|
||||
}
|
||||
|
||||
template <typename T, typename A0, typename A1>
|
||||
inline void construct_impl(T* address, emplace_args2<A0, A1> const& args)
|
||||
{
|
||||
new((void*) address) T(
|
||||
boost::forward<A0>(args.a0),
|
||||
boost::forward<A1>(args.a1)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T, typename A0, typename A1, typename A2>
|
||||
inline void construct_impl(T* address, emplace_args3<A0, A1, A2> const& args)
|
||||
{
|
||||
new((void*) address) T(
|
||||
boost::forward<A0>(args.a0),
|
||||
boost::forward<A1>(args.a1),
|
||||
boost::forward<A2>(args.a2)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
@@ -401,7 +496,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
|
||||
#undef BOOST_UNORDERED_CALL_FORWARD2
|
||||
|
||||
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
|
||||
#endif // BOOST_UNORDERED_STD_FORWARD_MOVE
|
||||
#endif // BOOST_UNORDERED_VARIADIC_MOVE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Construct without using the emplace args mechanism.
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/emplace_args.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
@@ -23,20 +22,40 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename A, typename T>
|
||||
struct grouped_node :
|
||||
boost::unordered::detail::node_base<
|
||||
typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, grouped_node<A, T> >::type::pointer
|
||||
>,
|
||||
boost::unordered::detail::value_base<T>
|
||||
{
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, grouped_node<A, T> >::type::pointer link_pointer;
|
||||
typedef boost::unordered::detail::node_base<link_pointer> node_base;
|
||||
|
||||
link_pointer next_;
|
||||
link_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
node_base(),
|
||||
group_prev_(),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~grouped_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
#else
|
||||
grouped_node() :
|
||||
next_(),
|
||||
node_base(),
|
||||
group_prev_(),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(link_pointer self)
|
||||
{
|
||||
@@ -50,16 +69,33 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::ptr_bucket
|
||||
{
|
||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||
typedef bucket_base node_base;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
link_pointer group_prev_;
|
||||
std::size_t hash_;
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
bucket_base(),
|
||||
group_prev_(0),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~grouped_ptr_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
#else
|
||||
grouped_ptr_node() :
|
||||
bucket_base(),
|
||||
group_prev_(0),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(link_pointer self)
|
||||
{
|
||||
@@ -115,42 +151,46 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
};
|
||||
|
||||
template <typename A, typename H, typename P>
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct multiset
|
||||
{
|
||||
typedef boost::unordered::detail::multiset<A, H, P> types;
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<A> traits;
|
||||
typedef typename traits::value_type value_type;
|
||||
typedef value_type key_type;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename H, typename P>
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
typedef boost::unordered::detail::multimap<A, K, H, P> types;
|
||||
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<A> traits;
|
||||
typedef typename traits::value_type value_type;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
@@ -158,6 +198,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
@@ -167,6 +209,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::value_type value_type;
|
||||
typedef typename table::bucket bucket;
|
||||
typedef typename table::buckets buckets;
|
||||
typedef typename table::policy policy;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
typedef typename table::node_allocator node_allocator;
|
||||
typedef typename table::node_allocator_traits node_allocator_traits;
|
||||
@@ -179,6 +222,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
|
||||
// Constructors
|
||||
|
||||
@@ -212,59 +256,61 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Accessors
|
||||
|
||||
template <class Key, class Pred>
|
||||
node_pointer find_node_impl(
|
||||
std::size_t hash,
|
||||
iterator find_node_impl(
|
||||
std::size_t key_hash,
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
node_pointer n = this->get_start(bucket_index);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
iterator n = this->get_start(bucket_index);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!n) return n;
|
||||
if (!n.node_) return n;
|
||||
|
||||
std::size_t node_hash = n->hash_;
|
||||
if (hash == node_hash)
|
||||
std::size_t node_hash = n.node_->hash_;
|
||||
if (key_hash == node_hash)
|
||||
{
|
||||
if (eq(k, this->get_key(n->value())))
|
||||
if (eq(k, this->get_key(*n)))
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
return node_pointer();
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
n = static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n->group_prev_)->next_);
|
||||
n = iterator(static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t count(key_type const& k) const
|
||||
{
|
||||
node_pointer n = this->find_node(k);
|
||||
if (!n) return 0;
|
||||
iterator n = this->find_node(k);
|
||||
if (!n.node_) return 0;
|
||||
|
||||
std::size_t count = 0;
|
||||
node_pointer it = n;
|
||||
std::size_t x = 0;
|
||||
node_pointer it = n.node_;
|
||||
do {
|
||||
it = static_cast<node_pointer>(it->group_prev_);
|
||||
++count;
|
||||
} while(it != n);
|
||||
++x;
|
||||
} while(it != n.node_);
|
||||
|
||||
return count;
|
||||
return x;
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(key_type const& k) const
|
||||
{
|
||||
node_pointer n = this->find_node(k);
|
||||
iterator n = this->find_node(k);
|
||||
return std::make_pair(
|
||||
iterator(n), iterator(n ?
|
||||
n, n.node_ ? iterator(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n->group_prev_)->next_) :
|
||||
n));
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
)) : n);
|
||||
}
|
||||
|
||||
// Equality
|
||||
@@ -274,14 +320,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
for(node_pointer n1 = this->get_start(); n1;)
|
||||
for(iterator n1 = this->get_start(); n1.node_;)
|
||||
{
|
||||
node_pointer n2 = other.find_matching_node(n1);
|
||||
if (!n2) return false;
|
||||
node_pointer end1 = static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n1->group_prev_)->next_);
|
||||
node_pointer end2 = static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n2->group_prev_)->next_);
|
||||
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_));
|
||||
if (!group_equals(n1, end1, n2, end2)) return false;
|
||||
n1 = end1;
|
||||
}
|
||||
@@ -291,25 +337,24 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
|
||||
static bool group_equals(node_pointer n1, node_pointer end1,
|
||||
node_pointer n2, node_pointer end2)
|
||||
static bool group_equals(iterator n1, iterator end1,
|
||||
iterator n2, iterator end2)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if (n1->value() != n2->value())
|
||||
break;
|
||||
if (*n1 != *n2) break;
|
||||
|
||||
n1 = static_cast<node_pointer>(n1->next_);
|
||||
n2 = static_cast<node_pointer>(n2->next_);
|
||||
++n1;
|
||||
++n2;
|
||||
|
||||
if (n1 == end1) return n2 == end2;
|
||||
if (n2 == end2) return false;
|
||||
}
|
||||
|
||||
for(node_pointer n1a = n1, n2a = n2;;)
|
||||
for(iterator n1a = n1, n2a = n2;;)
|
||||
{
|
||||
n1a = static_cast<node_pointer>(n1a->next_);
|
||||
n2a = static_cast<node_pointer>(n2a->next_);
|
||||
++n1a;
|
||||
++n2a;
|
||||
|
||||
if (n1a == end1)
|
||||
{
|
||||
@@ -320,50 +365,50 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (n2a == end2) return false;
|
||||
}
|
||||
|
||||
node_pointer start = n1;
|
||||
for(;n1 != end2; n1 = static_cast<node_pointer>(n1->next_))
|
||||
iterator start = n1;
|
||||
for(;n1 != end1; ++n1)
|
||||
{
|
||||
value_type const& v = n1->value();
|
||||
value_type const& v = *n1;
|
||||
if (find(start, n1, v)) continue;
|
||||
std::size_t matches = count_equal(n2, end2, v);
|
||||
if (!matches || matches != 1 + count_equal(
|
||||
static_cast<node_pointer>(n1->next_), end1, v))
|
||||
return false;
|
||||
if (!matches) return false;
|
||||
iterator next = n1;
|
||||
++next;
|
||||
if (matches != 1 + count_equal(next, end1, v)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool find(node_pointer n, node_pointer end, value_type const& v)
|
||||
static bool find(iterator n, iterator end, value_type const& v)
|
||||
{
|
||||
for(;n != end; n = static_cast<node_pointer>(n->next_))
|
||||
if (n->value() == v)
|
||||
for(;n != end; ++n)
|
||||
if (*n == v)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::size_t count_equal(node_pointer n, node_pointer end,
|
||||
static std::size_t count_equal(iterator n, iterator end,
|
||||
value_type const& v)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for(;n != end; n = static_cast<node_pointer>(n->next_))
|
||||
if (n->value() == v) ++count;
|
||||
for(;n != end; ++n)
|
||||
if (*n == v) ++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool group_equals(node_pointer n1, node_pointer end1,
|
||||
node_pointer n2, node_pointer end2)
|
||||
static bool group_equals(iterator n1, iterator end1,
|
||||
iterator n2, iterator end2)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(!extractor::compare_mapped(
|
||||
n1->value(), n2->value()))
|
||||
if(!extractor::compare_mapped(*n1, *n2))
|
||||
return false;
|
||||
|
||||
n1 = static_cast<node_pointer>(n1->next_);
|
||||
n2 = static_cast<node_pointer>(n2->next_);
|
||||
++n1;
|
||||
++n2;
|
||||
|
||||
if (n1 == end1) return n2 == end2;
|
||||
if (n2 == end2) return false;
|
||||
@@ -385,35 +430,37 @@ namespace boost { namespace unordered { namespace detail {
|
||||
pos->group_prev_ = static_cast<link_pointer>(n);
|
||||
}
|
||||
|
||||
inline node_pointer add_node(
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
std::size_t hash,
|
||||
node_pointer pos)
|
||||
std::size_t key_hash,
|
||||
iterator pos)
|
||||
{
|
||||
node_pointer n = a.release();
|
||||
n->hash_ = hash;
|
||||
if(pos) {
|
||||
this->add_after_node(n, pos);
|
||||
n->hash_ = key_hash;
|
||||
if (pos.node_) {
|
||||
this->add_after_node(n, pos.node_);
|
||||
if (n->next_) {
|
||||
std::size_t next_bucket =
|
||||
static_cast<node_pointer>(n->next_)->hash_ %
|
||||
this->bucket_count_;
|
||||
if (next_bucket != hash % this->bucket_count_) {
|
||||
std::size_t next_bucket = policy::to_bucket(
|
||||
this->bucket_count_,
|
||||
static_cast<node_pointer>(n->next_)->hash_);
|
||||
if (next_bucket !=
|
||||
policy::to_bucket(this->bucket_count_, key_hash)) {
|
||||
this->get_bucket(next_bucket)->next_ = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
|
||||
bucket_pointer b = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(
|
||||
this->get_bucket(policy::to_bucket(this->bucket_count_,
|
||||
static_cast<node_pointer>(start_node->next_)->hash_
|
||||
% this->bucket_count_)->next_ = n;
|
||||
))->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
@@ -427,46 +474,45 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
}
|
||||
++this->size_;
|
||||
return n;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
node_pointer emplace_impl(node_constructor& a)
|
||||
iterator emplace_impl(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
node_pointer position = this->find_node(hash, k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator position = this->find_node(key_hash, k);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return this->add_node(a, hash, position);
|
||||
return this->add_node(a, key_hash, position);
|
||||
}
|
||||
|
||||
void emplace_impl_no_rehash(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
this->add_node(a, hash,
|
||||
this->find_node(hash, k));
|
||||
std::size_t key_hash = this->hash(k);
|
||||
this->add_node(a, key_hash, this->find_node(key_hash, k));
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
node_pointer emplace(boost::unordered::detail::emplace_args1<
|
||||
iterator emplace(boost::unordered::detail::emplace_args1<
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return this->begin();
|
||||
return iterator();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
node_pointer emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
|
||||
return emplace_impl(a);
|
||||
return iterator(emplace_impl(a));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -521,11 +567,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
bucket_pointer bucket = this->get_bucket(bucket_index);
|
||||
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 = bucket->next_;
|
||||
previous_pointer prev = this_bucket->next_;
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
@@ -533,9 +580,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return 0;
|
||||
if (node_hash == hash &&
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
static_cast<node_pointer>(prev->next_)->value())))
|
||||
break;
|
||||
@@ -548,37 +596,39 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static_cast<node_pointer>(pos->group_prev_)->next_;
|
||||
node_pointer end = static_cast<node_pointer>(end1);
|
||||
prev->next_ = end1;
|
||||
this->fix_buckets(bucket, prev, end);
|
||||
return this->delete_nodes(pos, end);
|
||||
this->fix_buckets(this_bucket, prev, end);
|
||||
return this->delete_nodes(c_iterator(pos), c_iterator(end));
|
||||
}
|
||||
|
||||
node_pointer erase(node_pointer r)
|
||||
iterator erase(c_iterator r)
|
||||
{
|
||||
BOOST_ASSERT(r);
|
||||
node_pointer next = static_cast<node_pointer>(r->next_);
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
|
||||
bucket_pointer bucket = this->get_bucket(
|
||||
r->hash_ % this->bucket_count_);
|
||||
previous_pointer prev = unlink_node(*bucket, r);
|
||||
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(bucket, prev, next);
|
||||
this->fix_buckets(this_bucket, prev, next.node_);
|
||||
|
||||
this->delete_node(r);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
node_pointer erase_range(node_pointer r1, node_pointer r2)
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return r2;
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
|
||||
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
|
||||
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, r2);
|
||||
this->fix_buckets_range(bucket_index, prev, r1, r2);
|
||||
*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);
|
||||
|
||||
return r2;
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
static previous_pointer unlink_node(bucket& b, node_pointer n)
|
||||
@@ -695,31 +745,31 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
node_pointer n = src.get_start();
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n) {
|
||||
std::size_t hash = n->hash_;
|
||||
node_pointer group_end =
|
||||
while (n.node_) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n->group_prev_)->next_);
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
));
|
||||
|
||||
a.construct_node();
|
||||
a.construct_value2(n->value());
|
||||
a.construct_value2(*n);
|
||||
|
||||
node_pointer first_node = a.release();
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = hash;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = static_cast<link_pointer>(first_node);
|
||||
++dst.size_;
|
||||
|
||||
for(n = static_cast<node_pointer>(n->next_); n != group_end;
|
||||
n = static_cast<node_pointer>(n->next_))
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
a.construct_node();
|
||||
a.construct_value2(n->value());
|
||||
a.construct_value2(*n);
|
||||
end = a.release();
|
||||
end->hash_ = hash;
|
||||
end->hash_ = key_hash;
|
||||
add_after_node(end, first_node);
|
||||
++dst.size_;
|
||||
}
|
||||
@@ -742,31 +792,31 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
node_pointer n = src.get_start();
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n) {
|
||||
std::size_t hash = n->hash_;
|
||||
node_pointer group_end =
|
||||
while (n.node_) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n->group_prev_)->next_);
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
));
|
||||
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(n->value()));
|
||||
a.construct_value2(boost::move(*n));
|
||||
|
||||
node_pointer first_node = a.release();
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = hash;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = static_cast<link_pointer>(first_node);
|
||||
++dst.size_;
|
||||
|
||||
for(n = static_cast<node_pointer>(n->next_); n != group_end;
|
||||
n = static_cast<node_pointer>(n->next_))
|
||||
for(++n; n != group_end; ++n)
|
||||
{
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(n->value()));
|
||||
a.construct_value2(boost::move(*n));
|
||||
end = a.release();
|
||||
end->hash_ = hash;
|
||||
end->hash_ = key_hash;
|
||||
add_after_node(end, first_node);
|
||||
++dst.size_;
|
||||
}
|
||||
@@ -807,7 +857,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static previous_pointer place_in_bucket(buckets& dst,
|
||||
previous_pointer prev, node_pointer end)
|
||||
{
|
||||
bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
|
||||
bucket_pointer b = dst.get_bucket(policy::to_bucket(
|
||||
dst.bucket_count_, end->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = static_cast<node_pointer>(prev);
|
||||
|
||||
@@ -51,25 +51,17 @@ namespace detail {
|
||||
return v;
|
||||
}
|
||||
|
||||
#if BOOST_UNORDERED_USE_RV_REF
|
||||
static key_type const& extract(BOOST_RV_REF(key_type) v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
static no_key extract()
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class... Args>
|
||||
static no_key extract(Args const&...)
|
||||
{
|
||||
return no_key();
|
||||
}
|
||||
|
||||
#else
|
||||
template <class Arg>
|
||||
static no_key extract(Arg const&)
|
||||
@@ -106,13 +98,6 @@ namespace detail {
|
||||
return v;
|
||||
}
|
||||
|
||||
// TODO: Why does this cause errors?
|
||||
//
|
||||
//static key_type const& extract(BOOST_RV_REF(key_type) v)
|
||||
//{
|
||||
// return v;
|
||||
//}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type, Second> const& v)
|
||||
{
|
||||
@@ -126,7 +111,7 @@ namespace detail {
|
||||
return v.first;
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class Arg1, class... Args>
|
||||
static key_type const& extract(key_type const& k,
|
||||
Arg1 const&, Args const&...)
|
||||
@@ -165,7 +150,7 @@ namespace detail {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
|
||||
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
|
||||
template <typename T2> \
|
||||
|
||||
@@ -10,41 +10,11 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_map;
|
||||
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_multimap;
|
||||
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_set;
|
||||
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_multiset;
|
||||
|
||||
struct piecewise_construct_t {};
|
||||
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
|
||||
}
|
||||
|
||||
@@ -11,251 +11,8 @@
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
//
|
||||
// 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> struct l_iterator;
|
||||
template <typename ConstNodePointer, typename NodePointer,
|
||||
typename Value> struct cl_iterator;
|
||||
|
||||
// Local Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
template <typename NodePointer, typename Value>
|
||||
struct l_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename ConstNodePointer, typename NodePointer2,
|
||||
typename Value2>
|
||||
friend struct boost::unordered::iterator_detail::cl_iterator;
|
||||
private:
|
||||
#endif
|
||||
typedef NodePointer node_pointer;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
l_iterator() : ptr_() {}
|
||||
|
||||
l_iterator(node_pointer x, std::size_t b, std::size_t c)
|
||||
: ptr_(x), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
Value& operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
l_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
|
||||
l_iterator operator++(int) {
|
||||
l_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(l_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
|
||||
bool operator!=(l_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value>
|
||||
struct cl_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::l_iterator
|
||||
<NodePointer, Value>;
|
||||
private:
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
node_pointer ptr_;
|
||||
std::size_t bucket_;
|
||||
std::size_t bucket_count_;
|
||||
|
||||
public:
|
||||
|
||||
cl_iterator() : ptr_() {}
|
||||
|
||||
cl_iterator(node_pointer x, std::size_t b, std::size_t c) :
|
||||
ptr_(x), bucket_(b), bucket_count_(c) {}
|
||||
|
||||
cl_iterator(boost::unordered::iterator_detail::l_iterator<
|
||||
NodePointer, Value> const& x) :
|
||||
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
|
||||
{}
|
||||
|
||||
Value const&
|
||||
operator*() const {
|
||||
return ptr_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
return ptr_->value_ptr();
|
||||
}
|
||||
|
||||
cl_iterator& operator++() {
|
||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
|
||||
ptr_ = node_pointer();
|
||||
return *this;
|
||||
}
|
||||
|
||||
cl_iterator operator++(int) {
|
||||
cl_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
|
||||
return x.ptr_ == y.ptr_;
|
||||
}
|
||||
|
||||
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
|
||||
return x.ptr_ != y.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodePointer, typename Value>
|
||||
struct iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
NodePointer, Value&>
|
||||
{
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename ConstNodePointer, typename NodePointer2,
|
||||
typename Value2>
|
||||
friend struct boost::unordered::iterator_detail::c_iterator;
|
||||
private:
|
||||
#endif
|
||||
typedef NodePointer node_pointer;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
iterator() : node_() {}
|
||||
|
||||
explicit iterator(node_pointer const& x) : node_(x) {}
|
||||
|
||||
Value& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
iterator& operator++() {
|
||||
node_ = node_ = static_cast<node_pointer>(node_->next_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
iterator tmp(node_);
|
||||
node_ = node_ = static_cast<node_pointer>(node_->next_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(iterator const& x) const {
|
||||
return node_ == x.node_;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const& x) const {
|
||||
return node_ != x.node_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ConstNodePointer, typename NodePointer, typename Value>
|
||||
struct c_iterator
|
||||
: public boost::iterator<
|
||||
std::forward_iterator_tag, Value, std::ptrdiff_t,
|
||||
ConstNodePointer, Value const&>
|
||||
{
|
||||
friend struct boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value>;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <typename K, typename T, typename H, typename P, typename A>
|
||||
friend class boost::unordered::unordered_map;
|
||||
template <typename K, typename T, typename H, typename P, typename A>
|
||||
friend class boost::unordered::unordered_multimap;
|
||||
template <typename T, typename H, typename P, typename A>
|
||||
friend class boost::unordered::unordered_set;
|
||||
template <typename T, typename H, typename P, typename A>
|
||||
friend class boost::unordered::unordered_multiset;
|
||||
|
||||
private:
|
||||
#endif
|
||||
|
||||
typedef NodePointer node_pointer;
|
||||
node_pointer node_;
|
||||
|
||||
public:
|
||||
|
||||
c_iterator() : node_() {}
|
||||
|
||||
explicit c_iterator(node_pointer const& x) : node_(x) {}
|
||||
|
||||
c_iterator(boost::unordered::iterator_detail::iterator<
|
||||
NodePointer, Value> const& x) : node_(x.node_) {}
|
||||
|
||||
Value const& operator*() const {
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
return &node_->value();
|
||||
}
|
||||
|
||||
c_iterator& operator++() {
|
||||
node_ = static_cast<node_pointer>(node_->next_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
c_iterator operator++(int) {
|
||||
c_iterator tmp(node_);
|
||||
node_ = node_ = static_cast<node_pointer>(node_->next_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(c_iterator const& x, c_iterator const& y) {
|
||||
return x.node_ == y.node_;
|
||||
}
|
||||
|
||||
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
|
||||
return x.node_ != y.node_;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -302,7 +59,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node>,
|
||||
typename Types::node,
|
||||
typename Types::policy>,
|
||||
boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
typename Types::key_equal>
|
||||
@@ -318,6 +76,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename Types::value_type value_type;
|
||||
typedef typename Types::table table_impl;
|
||||
typedef typename Types::link_pointer link_pointer;
|
||||
typedef typename Types::policy policy;
|
||||
|
||||
typedef boost::unordered::detail::functions<
|
||||
typename Types::hasher,
|
||||
@@ -326,22 +85,15 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::buckets<
|
||||
typename Types::allocator,
|
||||
typename Types::bucket,
|
||||
typename Types::node> buckets;
|
||||
typename Types::node,
|
||||
typename Types::policy> buckets;
|
||||
|
||||
typedef typename buckets::node_allocator node_allocator;
|
||||
typedef typename buckets::node_allocator_traits node_allocator_traits;
|
||||
typedef typename buckets::node_pointer node_pointer;
|
||||
typedef typename buckets::const_node_pointer const_node_pointer;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node_pointer, value_type> iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
l_iterator<node_pointer, value_type> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::
|
||||
cl_iterator<const_node_pointer, node_pointer, value_type>
|
||||
cl_iterator;
|
||||
typedef typename table::iterator iterator;
|
||||
|
||||
// Members
|
||||
|
||||
@@ -384,7 +136,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
std::size_t min_buckets_for_size(std::size_t size) const
|
||||
{
|
||||
BOOST_ASSERT(this->mlf_ != 0);
|
||||
BOOST_ASSERT(this->mlf_ >= minimum_max_load_factor);
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -395,7 +147,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Or from rehash post-condition:
|
||||
// count > size / mlf_
|
||||
|
||||
return boost::unordered::detail::next_prime(
|
||||
return policy::new_bucket_count(
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(size) /
|
||||
static_cast<double>(mlf_))) + 1);
|
||||
@@ -408,7 +160,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
hasher const& hf,
|
||||
key_equal const& eq,
|
||||
node_allocator const& a) :
|
||||
buckets(a, boost::unordered::detail::next_prime(num_buckets)),
|
||||
buckets(a, policy::new_bucket_count(num_buckets)),
|
||||
functions(hf, eq),
|
||||
mlf_(1.0f),
|
||||
max_load_(0)
|
||||
@@ -458,9 +210,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Iterators
|
||||
|
||||
node_pointer begin() const {
|
||||
iterator begin() const {
|
||||
return !this->buckets_ ?
|
||||
node_pointer() : this->get_start();
|
||||
iterator() : this->get_start();
|
||||
}
|
||||
|
||||
// Assignment
|
||||
@@ -586,36 +338,41 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return extractor::extract(x);
|
||||
}
|
||||
|
||||
std::size_t hash(key_type const& k) const
|
||||
{
|
||||
return policy::apply_hash(this->hash_function(), k);
|
||||
}
|
||||
|
||||
// Find Node
|
||||
|
||||
template <typename Key, typename Hash, typename Pred>
|
||||
node_pointer generic_find_node(
|
||||
iterator generic_find_node(
|
||||
Key const& k,
|
||||
Hash const& hash_function,
|
||||
Hash const& hf,
|
||||
Pred const& eq) const
|
||||
{
|
||||
if (!this->size_) return node_pointer();
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(hash_function(k), k, eq);
|
||||
find_node_impl(policy::apply_hash(hf, k), k, eq);
|
||||
}
|
||||
|
||||
node_pointer find_node(
|
||||
std::size_t hash,
|
||||
iterator find_node(
|
||||
std::size_t key_hash,
|
||||
key_type const& k) const
|
||||
{
|
||||
if (!this->size_) return node_pointer();
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(hash, k, this->key_eq());
|
||||
find_node_impl(key_hash, k, this->key_eq());
|
||||
}
|
||||
|
||||
node_pointer find_node(key_type const& k) const
|
||||
iterator find_node(key_type const& k) const
|
||||
{
|
||||
if (!this->size_) return node_pointer();
|
||||
if (!this->size_) return iterator();
|
||||
return static_cast<table_impl const*>(this)->
|
||||
find_node_impl(this->hash_function()(k), k, this->key_eq());
|
||||
find_node_impl(this->hash(k), k, this->key_eq());
|
||||
}
|
||||
|
||||
node_pointer find_matching_node(node_pointer n) const
|
||||
iterator find_matching_node(iterator n) const
|
||||
{
|
||||
// TODO: Does this apply to C++11?
|
||||
//
|
||||
@@ -623,13 +380,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// when different hash functions are used. So I can't use the hash
|
||||
// value from the node here.
|
||||
|
||||
return find_node(get_key(n->value()));
|
||||
return find_node(get_key(*n));
|
||||
}
|
||||
|
||||
// Reserve and rehash
|
||||
|
||||
void reserve_for_insert(std::size_t);
|
||||
void rehash(std::size_t);
|
||||
void reserve(std::size_t);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -645,7 +403,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
this->create_buckets();
|
||||
this->max_load_ = this->calculate_max_load();
|
||||
}
|
||||
else if(size >= max_load_) {
|
||||
// According to the standard this should be 'size >= max_load_',
|
||||
// but I think this is better, defect report filed.
|
||||
else if(size > max_load_) {
|
||||
std::size_t num_buckets
|
||||
= this->min_buckets_for_size((std::max)(size,
|
||||
this->size_ + (this->size_ >> 1)));
|
||||
@@ -660,16 +420,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// strong otherwise.
|
||||
|
||||
template <typename Types>
|
||||
void table<Types>::rehash(std::size_t min_buckets)
|
||||
inline void table<Types>::rehash(std::size_t min_buckets)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if(!this->size_) {
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->bucket_count_ = next_prime(min_buckets);
|
||||
this->bucket_count_ = policy::new_bucket_count(min_buckets);
|
||||
}
|
||||
else {
|
||||
min_buckets = next_prime((std::max)(min_buckets,
|
||||
min_buckets = policy::new_bucket_count((std::max)(min_buckets,
|
||||
boost::unordered::detail::double_to_size(floor(
|
||||
static_cast<double>(this->size_) /
|
||||
static_cast<double>(mlf_))) + 1));
|
||||
@@ -680,6 +440,13 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Types>
|
||||
inline void table<Types>::reserve(std::size_t num_elements)
|
||||
{
|
||||
rehash(static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>(num_elements) / this->mlf_)));
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,31 +12,49 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/emplace_args.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
template <typename A, typename T> struct node;
|
||||
template <typename A, typename T> struct unique_node;
|
||||
template <typename T> struct ptr_node;
|
||||
template <typename Types> struct table_impl;
|
||||
|
||||
template <typename A, typename T>
|
||||
struct node :
|
||||
struct unique_node :
|
||||
boost::unordered::detail::node_base<
|
||||
typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, unique_node<A, T> >::type::pointer
|
||||
>,
|
||||
boost::unordered::detail::value_base<T>
|
||||
{
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||
A, node<A, T> >::type::pointer link_pointer;
|
||||
A, unique_node<A, T> >::type::pointer link_pointer;
|
||||
typedef boost::unordered::detail::node_base<link_pointer> node_base;
|
||||
|
||||
link_pointer next_;
|
||||
std::size_t hash_;
|
||||
|
||||
node() :
|
||||
next_(),
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
unique_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
node_base(),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~unique_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
#else
|
||||
unique_node() :
|
||||
node_base(),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(link_pointer)
|
||||
{
|
||||
@@ -49,14 +67,30 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::ptr_bucket
|
||||
{
|
||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||
typedef bucket_base node_base;
|
||||
typedef ptr_bucket* link_pointer;
|
||||
|
||||
std::size_t hash_;
|
||||
|
||||
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||
bucket_base(),
|
||||
hash_(0)
|
||||
{
|
||||
boost::unordered::detail::construct_impl(
|
||||
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
}
|
||||
|
||||
~ptr_node() {
|
||||
boost::unordered::detail::destroy(this->value_ptr());
|
||||
}
|
||||
#else
|
||||
ptr_node() :
|
||||
bucket_base(),
|
||||
hash_(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void init(link_pointer)
|
||||
{
|
||||
@@ -69,7 +103,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename T, typename NodePtr, typename BucketPtr>
|
||||
struct pick_node2
|
||||
{
|
||||
typedef boost::unordered::detail::node<A, T> node;
|
||||
typedef boost::unordered::detail::unique_node<A, T> node;
|
||||
|
||||
typedef typename boost::unordered::detail::allocator_traits<
|
||||
typename boost::unordered::detail::rebind_wrap<A, node>::type
|
||||
@@ -111,42 +145,46 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
};
|
||||
|
||||
template <typename A, typename H, typename P>
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct set
|
||||
{
|
||||
typedef boost::unordered::detail::set<A, H, P> types;
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<A> traits;
|
||||
typedef typename traits::value_type value_type;
|
||||
typedef value_type key_type;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename H, typename P>
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct map
|
||||
{
|
||||
typedef boost::unordered::detail::map<A, K, H, P> types;
|
||||
typedef boost::unordered::detail::map<A, K, M, H, P> types;
|
||||
|
||||
typedef A allocator;
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K key_type;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<A> traits;
|
||||
typedef typename traits::value_type value_type;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
A, value_type>::type allocator;
|
||||
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
@@ -154,6 +192,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef boost::unordered::detail::pick_policy::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
@@ -163,6 +203,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::value_type value_type;
|
||||
typedef typename table::bucket bucket;
|
||||
typedef typename table::buckets buckets;
|
||||
typedef typename table::policy policy;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
typedef typename table::node_allocator node_allocator;
|
||||
typedef typename table::node_allocator_traits node_allocator_traits;
|
||||
@@ -175,6 +216,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
|
||||
typedef std::pair<iterator, bool> emplace_return;
|
||||
|
||||
@@ -210,44 +252,46 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Accessors
|
||||
|
||||
template <class Key, class Pred>
|
||||
node_pointer find_node_impl(
|
||||
std::size_t hash,
|
||||
iterator find_node_impl(
|
||||
std::size_t key_hash,
|
||||
Key const& k,
|
||||
Pred const& eq) const
|
||||
{
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
node_pointer n = this->get_start(bucket_index);
|
||||
std::size_t bucket_index =
|
||||
policy::to_bucket(this->bucket_count_, key_hash);
|
||||
iterator n = this->get_start(bucket_index);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!n) return n;
|
||||
if (!n.node_) return n;
|
||||
|
||||
std::size_t node_hash = n->hash_;
|
||||
if (hash == node_hash)
|
||||
std::size_t node_hash = n.node_->hash_;
|
||||
if (key_hash == node_hash)
|
||||
{
|
||||
if (eq(k, this->get_key(n->value())))
|
||||
if (eq(k, this->get_key(*n)))
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
return node_pointer();
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return iterator();
|
||||
}
|
||||
|
||||
n = static_cast<node_pointer>(n->next_);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t count(key_type const& k) const
|
||||
{
|
||||
return this->find_node(k) ? 1 : 0;
|
||||
return this->find_node(k).node_ ? 1 : 0;
|
||||
}
|
||||
|
||||
value_type& at(key_type const& k) const
|
||||
{
|
||||
if (this->size_) {
|
||||
node_pointer it = this->find_node(k);
|
||||
if (it) return it->value();
|
||||
iterator it = this->find_node(k);
|
||||
if (it.node_) return *it;
|
||||
}
|
||||
|
||||
boost::throw_exception(
|
||||
@@ -257,9 +301,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(key_type const& k) const
|
||||
{
|
||||
node_pointer n = this->find_node(k);
|
||||
return std::make_pair(iterator(n),
|
||||
iterator(n ? static_cast<node_pointer>(n->next_) : n));
|
||||
iterator n = this->find_node(k);
|
||||
iterator n2 = n;
|
||||
if (n2.node_) ++n2;
|
||||
return std::make_pair(n, n2);
|
||||
}
|
||||
|
||||
// equals
|
||||
@@ -269,17 +314,15 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
for(node_pointer n1 = this->get_start(); n1;
|
||||
n1 = static_cast<node_pointer>(n1->next_))
|
||||
for(iterator n1 = this->get_start(); n1.node_; ++n1)
|
||||
{
|
||||
node_pointer n2 = other.find_matching_node(n1);
|
||||
iterator n2 = other.find_matching_node(n1);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
|
||||
if(!n2 || n1->value() != n2->value())
|
||||
if (!n2.node_ || *n1 != *n2)
|
||||
return false;
|
||||
#else
|
||||
if(!n2 || !extractor::compare_mapped(
|
||||
n1->value(), n2->value()))
|
||||
if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -289,23 +332,24 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Emplace/Insert
|
||||
|
||||
inline node_pointer add_node(
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
std::size_t hash)
|
||||
std::size_t key_hash)
|
||||
{
|
||||
node_pointer n = a.release();
|
||||
n->hash_ = hash;
|
||||
n->hash_ = key_hash;
|
||||
|
||||
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
|
||||
bucket_pointer b = this->get_bucket(
|
||||
policy::to_bucket(this->bucket_count_, key_hash));
|
||||
|
||||
if (!b->next_)
|
||||
{
|
||||
previous_pointer start_node = this->get_previous_start();
|
||||
|
||||
if (start_node->next_) {
|
||||
this->get_bucket(
|
||||
static_cast<node_pointer>(start_node->next_)->hash_ %
|
||||
this->bucket_count_)->next_ = n;
|
||||
this->get_bucket(policy::to_bucket(this->bucket_count_,
|
||||
static_cast<node_pointer>(start_node->next_)->hash_)
|
||||
)->next_ = n;
|
||||
}
|
||||
|
||||
b->next_ = start_node;
|
||||
@@ -319,23 +363,23 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
++this->size_;
|
||||
return n;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
value_type& operator[](key_type const& k)
|
||||
{
|
||||
typedef typename value_type::second_type mapped_type;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos) return pos->value();
|
||||
if (pos.node_) return *pos;
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_node();
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
a.construct_value(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(k), boost::make_tuple());
|
||||
#else
|
||||
@@ -347,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return add_node(a, hash)->value();
|
||||
return *add_node(a, key_hash);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
@@ -355,14 +399,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
boost::unordered::detail::please_ignore_this_overload> const&)
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return emplace_return(iterator(this->begin()), false);
|
||||
return emplace_return(this->begin(), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
return emplace_impl(
|
||||
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
@@ -374,7 +418,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if !defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <typename A0>
|
||||
emplace_return emplace(
|
||||
boost::unordered::detail::emplace_args1<A0> const& args)
|
||||
@@ -387,10 +431,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
emplace_return emplace_impl(key_type const& k,
|
||||
BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos) return emplace_return(iterator(pos), false);
|
||||
if (pos.node_) return emplace_return(pos, false);
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
@@ -401,21 +445,21 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(iterator(this->add_node(a, hash)), true);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
}
|
||||
|
||||
emplace_return emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos) return emplace_return(iterator(pos), false);
|
||||
if (pos.node_) return emplace_return(pos, false);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(iterator(this->add_node(a, hash)), true);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
@@ -471,12 +515,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void insert_range_empty(node_constructor& a, key_type const& k,
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
this->add_node(a, hash);
|
||||
this->add_node(a, key_hash);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
@@ -484,19 +528,19 @@ namespace boost { namespace unordered { namespace detail {
|
||||
InputIt i, InputIt j)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
node_pointer pos = this->find_node(hash, k);
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (!pos) {
|
||||
if (!pos.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(*i);
|
||||
|
||||
if(this->size_ + 1 >= this->max_load_)
|
||||
if(this->size_ + 1 > this->max_load_)
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
|
||||
// Nothing after this point can throw.
|
||||
this->add_node(a, hash);
|
||||
this->add_node(a, key_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,11 +565,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
if(!this->size_) return 0;
|
||||
|
||||
std::size_t hash = this->hash_function()(k);
|
||||
std::size_t bucket_index = hash % this->bucket_count_;
|
||||
bucket_pointer bucket = this->get_bucket(bucket_index);
|
||||
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 = bucket->next_;
|
||||
previous_pointer prev = this_bucket->next_;
|
||||
if (!prev) return 0;
|
||||
|
||||
for (;;)
|
||||
@@ -533,9 +578,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
if (!prev->next_) return 0;
|
||||
std::size_t node_hash =
|
||||
static_cast<node_pointer>(prev->next_)->hash_;
|
||||
if (node_hash % this->bucket_count_ != bucket_index)
|
||||
if (policy::to_bucket(this->bucket_count_, node_hash)
|
||||
!= bucket_index)
|
||||
return 0;
|
||||
if (node_hash == hash &&
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(
|
||||
static_cast<node_pointer>(prev->next_)->value())))
|
||||
break;
|
||||
@@ -545,37 +591,39 @@ namespace boost { namespace unordered { namespace detail {
|
||||
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(bucket, prev, end);
|
||||
return this->delete_nodes(pos, end);
|
||||
this->fix_buckets(this_bucket, prev, end);
|
||||
return this->delete_nodes(c_iterator(pos), c_iterator(end));
|
||||
}
|
||||
|
||||
node_pointer erase(node_pointer r)
|
||||
iterator erase(c_iterator r)
|
||||
{
|
||||
BOOST_ASSERT(r);
|
||||
node_pointer next = static_cast<node_pointer>(r->next_);
|
||||
BOOST_ASSERT(r.node_);
|
||||
iterator next(r.node_);
|
||||
++next;
|
||||
|
||||
bucket_pointer bucket = this->get_bucket(
|
||||
r->hash_ % this->bucket_count_);
|
||||
previous_pointer prev = unlink_node(*bucket, r);
|
||||
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(bucket, prev, next);
|
||||
this->fix_buckets(this_bucket, prev, next.node_);
|
||||
|
||||
this->delete_node(r);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
node_pointer erase_range(node_pointer r1, node_pointer r2)
|
||||
iterator erase_range(c_iterator r1, c_iterator r2)
|
||||
{
|
||||
if (r1 == r2) return r2;
|
||||
if (r1 == r2) return iterator(r2.node_);
|
||||
|
||||
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
|
||||
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, r2);
|
||||
this->fix_buckets_range(bucket_index, prev, r1, r2);
|
||||
*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);
|
||||
|
||||
return r2;
|
||||
return iterator(r2.node_);
|
||||
}
|
||||
|
||||
static previous_pointer unlink_node(bucket& b, node_pointer n)
|
||||
@@ -608,18 +656,18 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
node_pointer n = src.get_start();
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n) {
|
||||
while(n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(n->value());
|
||||
a.construct_value2(*n);
|
||||
|
||||
node_pointer node = a.release();
|
||||
node->hash_ = n->hash_;
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
n = static_cast<node_pointer>(n->next_);
|
||||
++n;
|
||||
|
||||
prev = place_in_bucket(dst, prev);
|
||||
}
|
||||
@@ -639,18 +687,18 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
node_pointer n = src.get_start();
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n) {
|
||||
while (n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(n->value()));
|
||||
a.construct_value2(boost::move(*n));
|
||||
|
||||
node_pointer node = a.release();
|
||||
node->hash_ = n->hash_;
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
n = static_cast<node_pointer>(n->next_);
|
||||
++n;
|
||||
|
||||
prev = place_in_bucket(dst, prev);
|
||||
}
|
||||
@@ -687,7 +735,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
previous_pointer prev)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(prev->next_);
|
||||
bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
|
||||
bucket_pointer b = dst.get_bucket(
|
||||
buckets::to_bucket(dst.bucket_count_, n->hash_));
|
||||
|
||||
if (!b->next_) {
|
||||
b->next_ = prev;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// primes
|
||||
|
||||
#define BOOST_UNORDERED_PRIMES \
|
||||
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
||||
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
||||
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
|
||||
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
|
||||
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
|
||||
|
||||
@@ -41,7 +41,9 @@ namespace unordered
|
||||
template <class K, class T, class H, class P, class A>
|
||||
class unordered_map
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_map)
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@@ -54,15 +56,9 @@ namespace unordered
|
||||
|
||||
private:
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
allocator_traits;
|
||||
|
||||
typedef boost::unordered::detail::map<value_allocator, K, H, P>
|
||||
types;
|
||||
typedef boost::unordered::detail::map<A, K, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
public:
|
||||
@@ -84,7 +80,7 @@ namespace unordered
|
||||
private:
|
||||
|
||||
table table_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
@@ -121,10 +117,17 @@ namespace unordered
|
||||
|
||||
unordered_map(unordered_map const&, allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_map(BOOST_RV_REF(unordered_map) other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&& other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map(unordered_map&&, allocator_type const&);
|
||||
@@ -145,6 +148,7 @@ namespace unordered
|
||||
|
||||
// Assign
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
@@ -156,6 +160,21 @@ namespace unordered
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_map& operator=(unordered_map const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_map& operator=(unordered_map&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_map& operator=(std::initializer_list<value_type>);
|
||||
@@ -184,12 +203,12 @@ namespace unordered
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
@@ -204,7 +223,7 @@ namespace unordered
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
@@ -214,20 +233,115 @@ namespace unordered
|
||||
|
||||
// emplace
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...).first);
|
||||
return table_.emplace(boost::forward<Args>(args)...).first;
|
||||
}
|
||||
#else
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
// 0 argument emplace requires special treatment in case
|
||||
// the container is instantiated with a value type that
|
||||
// doesn't have a default constructor.
|
||||
|
||||
std::pair<iterator, bool> emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return this->emplace(boost::move(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return this->emplace_hint(hint, boost::move(v));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename A0>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
std::pair<iterator, bool> emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
std::pair<iterator, bool> emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
@@ -251,39 +365,18 @@ namespace unordered
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)).first); \
|
||||
)).first; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
std::pair<iterator, bool> emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return this->emplace(boost::move(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return this->emplace_hint(hint, boost::move(v));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
std::pair<iterator, bool> insert(value_type const& x)
|
||||
@@ -372,7 +465,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@@ -421,6 +515,7 @@ namespace unordered
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<K,T,H,P,A>(
|
||||
@@ -433,8 +528,9 @@ namespace unordered
|
||||
template <class K, class T, class H, class P, class A>
|
||||
class unordered_multimap
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
|
||||
|
||||
#endif
|
||||
public:
|
||||
|
||||
typedef K key_type;
|
||||
@@ -446,15 +542,9 @@ namespace unordered
|
||||
|
||||
private:
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
allocator_traits;
|
||||
|
||||
typedef boost::unordered::detail::multimap<value_allocator, K, H, P>
|
||||
types;
|
||||
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
public:
|
||||
@@ -513,10 +603,17 @@ namespace unordered
|
||||
|
||||
unordered_multimap(unordered_multimap const&, allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap(unordered_multimap&&, allocator_type const&);
|
||||
@@ -537,6 +634,7 @@ namespace unordered
|
||||
|
||||
// Assign
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multimap& operator=(
|
||||
BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
|
||||
{
|
||||
@@ -549,6 +647,21 @@ namespace unordered
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multimap& operator=(unordered_multimap const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multimap& operator=(unordered_multimap&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_multimap& operator=(std::initializer_list<value_type>);
|
||||
@@ -577,12 +690,12 @@ namespace unordered
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
@@ -597,7 +710,7 @@ namespace unordered
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
@@ -607,20 +720,115 @@ namespace unordered
|
||||
|
||||
// emplace
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
#else
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
// 0 argument emplace requires special treatment in case
|
||||
// the container is instantiated with a value type that
|
||||
// doesn't have a default constructor.
|
||||
|
||||
iterator emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return this->emplace(boost::move(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return this->emplace_hint(hint, boost::move(v));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
@@ -629,11 +837,11 @@ namespace unordered
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
))); \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
@@ -644,39 +852,18 @@ namespace unordered
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
))); \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
iterator emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return iterator(this->emplace(boost::move(v)));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return iterator(this->emplace_hint(hint, boost::move(v)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
iterator insert(value_type const& x)
|
||||
@@ -761,7 +948,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@@ -810,6 +998,7 @@ namespace unordered
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<K,T,H,P,A>(
|
||||
@@ -954,7 +1143,7 @@ namespace unordered
|
||||
typename unordered_map<K,T,H,P,A>::iterator
|
||||
unordered_map<K,T,H,P,A>::erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(position.node_));
|
||||
return table_.erase(position);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -969,7 +1158,7 @@ namespace unordered
|
||||
unordered_map<K,T,H,P,A>::erase(
|
||||
const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(first.node_, last.node_));
|
||||
return table_.erase_range(first, last);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1027,14 +1216,14 @@ namespace unordered
|
||||
typename unordered_map<K,T,H,P,A>::iterator
|
||||
unordered_map<K,T,H,P,A>::find(const key_type& k)
|
||||
{
|
||||
return iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
typename unordered_map<K,T,H,P,A>::const_iterator
|
||||
unordered_map<K,T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1046,7 +1235,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq)
|
||||
{
|
||||
return iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1058,7 +1247,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1113,6 +1302,12 @@ namespace unordered
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_map<K,T,H,P,A>::reserve(size_type n)
|
||||
{
|
||||
table_.reserve(n);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(
|
||||
unordered_map<K,T,H,P,A> const& m1,
|
||||
@@ -1281,7 +1476,7 @@ namespace unordered
|
||||
typename unordered_multimap<K,T,H,P,A>::iterator
|
||||
unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(position.node_));
|
||||
return table_.erase(position);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1296,7 +1491,7 @@ namespace unordered
|
||||
unordered_multimap<K,T,H,P,A>::erase(
|
||||
const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(first.node_, last.node_));
|
||||
return table_.erase_range(first, last);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1333,14 +1528,14 @@ namespace unordered
|
||||
typename unordered_multimap<K,T,H,P,A>::iterator
|
||||
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
|
||||
{
|
||||
return iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
typename unordered_multimap<K,T,H,P,A>::const_iterator
|
||||
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1352,7 +1547,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq)
|
||||
{
|
||||
return iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1364,7 +1559,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1419,6 +1614,12 @@ namespace unordered
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_multimap<K,T,H,P,A>::reserve(size_type n)
|
||||
{
|
||||
table_.reserve(n);
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(
|
||||
unordered_multimap<K,T,H,P,A> const& m1,
|
||||
|
||||
@@ -10,12 +10,23 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_map;
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
@@ -26,6 +37,13 @@ namespace boost
|
||||
inline void swap(unordered_map<K, T, H, P, A>&,
|
||||
unordered_map<K, T, H, P, A>&);
|
||||
|
||||
template <class K,
|
||||
class T,
|
||||
class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_multimap;
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
|
||||
@@ -41,7 +41,9 @@ namespace unordered
|
||||
template <class T, class H, class P, class A>
|
||||
class unordered_set
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_set)
|
||||
#endif
|
||||
public:
|
||||
|
||||
typedef T key_type;
|
||||
@@ -52,15 +54,9 @@ namespace unordered
|
||||
|
||||
private:
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
allocator_traits;
|
||||
|
||||
typedef boost::unordered::detail::set<value_allocator, H, P>
|
||||
types;
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
public:
|
||||
@@ -119,10 +115,17 @@ namespace unordered
|
||||
|
||||
unordered_set(unordered_set const&, allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_set(BOOST_RV_REF(unordered_set) other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&& other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set(unordered_set&&, allocator_type const&);
|
||||
@@ -143,6 +146,7 @@ namespace unordered
|
||||
|
||||
// Assign
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
@@ -154,6 +158,21 @@ namespace unordered
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_set& operator=(unordered_set const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_set& operator=(unordered_set&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_set& operator=(std::initializer_list<value_type>);
|
||||
@@ -182,12 +201,12 @@ namespace unordered
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
@@ -202,7 +221,7 @@ namespace unordered
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(table_.begin());
|
||||
return table_.begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
@@ -212,20 +231,115 @@ namespace unordered
|
||||
|
||||
// emplace
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...).first);
|
||||
return table_.emplace(boost::forward<Args>(args)...).first;
|
||||
}
|
||||
#else
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
// 0 argument emplace requires special treatment in case
|
||||
// the container is instantiated with a value type that
|
||||
// doesn't have a default constructor.
|
||||
|
||||
std::pair<iterator, bool> emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return this->emplace(boost::move(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return this->emplace_hint(hint, boost::move(v));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename A0>
|
||||
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
std::pair<iterator, bool> emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
).first;
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
std::pair<iterator, bool> emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
@@ -249,39 +363,18 @@ namespace unordered
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)).first); \
|
||||
)).first; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
std::pair<iterator, bool> emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type())
|
||||
{
|
||||
return this->emplace(boost::move(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
value_type v = value_type()
|
||||
)
|
||||
{
|
||||
return iterator(this->emplace_hint(hint, boost::move(v)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
std::pair<iterator, bool> insert(value_type const& x)
|
||||
@@ -357,7 +450,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@@ -406,6 +500,7 @@ namespace unordered
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<T,H,P,A>(
|
||||
@@ -418,7 +513,9 @@ namespace unordered
|
||||
template <class T, class H, class P, class A>
|
||||
class unordered_multiset
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
|
||||
#endif
|
||||
public:
|
||||
|
||||
typedef T key_type;
|
||||
@@ -429,15 +526,9 @@ namespace unordered
|
||||
|
||||
private:
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
allocator_traits;
|
||||
|
||||
typedef boost::unordered::detail::multiset<value_allocator, H, P>
|
||||
types;
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
typedef typename types::allocator value_allocator;
|
||||
typedef typename types::traits allocator_traits;
|
||||
typedef typename types::table table;
|
||||
|
||||
public:
|
||||
@@ -496,10 +587,17 @@ namespace unordered
|
||||
|
||||
unordered_multiset(unordered_multiset const&, allocator_type const&);
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
: table_(other.table_, boost::unordered::detail::move_tag())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset(unordered_multiset&&, allocator_type const&);
|
||||
@@ -520,6 +618,7 @@ namespace unordered
|
||||
|
||||
// Assign
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multiset& operator=(
|
||||
BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
|
||||
{
|
||||
@@ -532,6 +631,21 @@ namespace unordered
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multiset& operator=(unordered_multiset const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
unordered_multiset& operator=(unordered_multiset&& x)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_multiset& operator=(std::initializer_list<value_type>);
|
||||
@@ -590,57 +704,26 @@ namespace unordered
|
||||
|
||||
// emplace
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template <class... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace(std::forward<Args>(args)...));
|
||||
return table_.emplace(boost::forward<Args>(args)...);
|
||||
}
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
))); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
|
||||
// 0 argument emplace requires special treatment in case
|
||||
// the container is instantiated with a value type that
|
||||
// doesn't have a default constructor.
|
||||
|
||||
iterator emplace(
|
||||
boost::unordered::detail::empty_emplace
|
||||
= boost::unordered::detail::empty_emplace(),
|
||||
@@ -660,6 +743,111 @@ namespace unordered
|
||||
|
||||
#endif
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace(
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
iterator emplace_hint(const_iterator,
|
||||
BOOST_FWD_REF(A0) a0,
|
||||
BOOST_FWD_REF(A1) a1,
|
||||
BOOST_FWD_REF(A2) a2)
|
||||
{
|
||||
return table_.emplace(
|
||||
boost::unordered::detail::create_emplace_args(
|
||||
boost::forward<A0>(a0),
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2))
|
||||
);
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
iterator emplace_hint( \
|
||||
const_iterator, \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
||||
) \
|
||||
{ \
|
||||
return table_.emplace( \
|
||||
boost::unordered::detail::create_emplace_args( \
|
||||
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
||||
a) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_EMPLACE, _)
|
||||
|
||||
#undef BOOST_UNORDERED_EMPLACE
|
||||
|
||||
#endif
|
||||
|
||||
iterator insert(value_type const& x)
|
||||
@@ -735,7 +923,8 @@ namespace unordered
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{
|
||||
return table_.hash_function()(k) % table_.bucket_count_;
|
||||
return table::to_bucket(table_.bucket_count_,
|
||||
table_.hash(k));
|
||||
}
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
@@ -784,6 +973,7 @@ namespace unordered
|
||||
float load_factor() const;
|
||||
void max_load_factor(float);
|
||||
void rehash(size_type);
|
||||
void reserve(size_type);
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<T,H,P,A>(
|
||||
@@ -928,7 +1118,7 @@ namespace unordered
|
||||
typename unordered_set<T,H,P,A>::iterator
|
||||
unordered_set<T,H,P,A>::erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(position.node_));
|
||||
return table_.erase(position);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -943,7 +1133,7 @@ namespace unordered
|
||||
unordered_set<T,H,P,A>::erase(
|
||||
const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(first.node_, last.node_));
|
||||
return table_.erase_range(first, last);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -980,7 +1170,7 @@ namespace unordered
|
||||
typename unordered_set<T,H,P,A>::const_iterator
|
||||
unordered_set<T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -992,7 +1182,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1038,6 +1228,12 @@ namespace unordered
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_set<T,H,P,A>::reserve(size_type n)
|
||||
{
|
||||
table_.reserve(n);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(
|
||||
unordered_set<T,H,P,A> const& m1,
|
||||
@@ -1206,7 +1402,7 @@ namespace unordered
|
||||
typename unordered_multiset<T,H,P,A>::iterator
|
||||
unordered_multiset<T,H,P,A>::erase(const_iterator position)
|
||||
{
|
||||
return iterator(table_.erase(position.node_));
|
||||
return table_.erase(position);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1221,7 +1417,7 @@ namespace unordered
|
||||
unordered_multiset<T,H,P,A>::erase(
|
||||
const_iterator first, const_iterator last)
|
||||
{
|
||||
return iterator(table_.erase_range(first.node_, last.node_));
|
||||
return table_.erase_range(first, last);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1258,7 +1454,7 @@ namespace unordered
|
||||
typename unordered_multiset<T,H,P,A>::const_iterator
|
||||
unordered_multiset<T,H,P,A>::find(const key_type& k) const
|
||||
{
|
||||
return const_iterator(table_.find_node(k));
|
||||
return table_.find_node(k);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1270,7 +1466,7 @@ namespace unordered
|
||||
CompatibleHash const& hash,
|
||||
CompatiblePredicate const& eq) const
|
||||
{
|
||||
return const_iterator(table_.generic_find_node(k, hash, eq));
|
||||
return table_.generic_find_node(k, hash, eq);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1316,6 +1512,12 @@ namespace unordered
|
||||
table_.rehash(n);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_multiset<T,H,P,A>::reserve(size_type n)
|
||||
{
|
||||
table_.reserve(n);
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(
|
||||
unordered_multiset<T,H,P,A> const& m1,
|
||||
|
||||
@@ -10,12 +10,22 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_set;
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
@@ -26,6 +36,12 @@ namespace boost
|
||||
inline void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2);
|
||||
|
||||
template <class T,
|
||||
class H = boost::hash<T>,
|
||||
class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
class unordered_multiset;
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
inline bool operator==(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
@@ -13,7 +11,7 @@
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t seed(12847);
|
||||
test::seed_t initialize_seed(12847);
|
||||
|
||||
template <class T>
|
||||
struct self_assign_base : public test::exception_base
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
test::seed_t seed(91274);
|
||||
test::seed_t initialize_seed(91274);
|
||||
|
||||
struct objects
|
||||
{
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
#include "../objects/exception.hpp"
|
||||
|
||||
typedef boost::unordered_set<
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
test::seed_t seed(73041);
|
||||
test::seed_t initialize_seed(73041);
|
||||
|
||||
template <class T>
|
||||
struct copy_test1 : public test::exception_base
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
test::seed_t seed(835193);
|
||||
test::seed_t initialize_seed(835193);
|
||||
|
||||
template <class T>
|
||||
struct erase_test_base : public test::exception_base
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include <string>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -13,7 +11,7 @@
|
||||
#include <boost/utility.hpp>
|
||||
#include <cmath>
|
||||
|
||||
test::seed_t seed(747373);
|
||||
test::seed_t initialize_seed(747373);
|
||||
|
||||
template <class T>
|
||||
struct insert_test_base : public test::exception_base
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include <string>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -13,7 +11,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
test::seed_t seed(3298597);
|
||||
test::seed_t initialize_seed(3298597);
|
||||
|
||||
template <class T>
|
||||
struct rehash_test_base : public test::exception_base
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include "./containers.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
@@ -13,7 +11,7 @@
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
test::seed_t seed(9387);
|
||||
test::seed_t initialize_seed(9387);
|
||||
|
||||
template <class T>
|
||||
struct self_swap_base : public test::exception_base
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace test
|
||||
it = x1.begin(), end = x1.end();
|
||||
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
|
||||
while(it != end) {
|
||||
// First test that the current key has not occured before, required
|
||||
// First test that the current key has not occurred before, required
|
||||
// to test either that keys are unique or that equivalent keys are
|
||||
// adjacent. (6.3.1/6)
|
||||
key_type key = get_key<X>(*it);
|
||||
|
||||
@@ -219,14 +219,14 @@ namespace test
|
||||
data_.last_ptr_ = &data_.first_;
|
||||
}
|
||||
|
||||
void erase(const_iterator start, const_iterator end) {
|
||||
void erase(const_iterator i, const_iterator j) {
|
||||
node** ptr = &data_.first_;
|
||||
|
||||
while(*ptr != start.ptr_) {
|
||||
while(*ptr != i.ptr_) {
|
||||
ptr = &(*ptr)->next_;
|
||||
}
|
||||
|
||||
while(*ptr != end.ptr_) {
|
||||
while(*ptr != j.ptr_) {
|
||||
node* to_delete = *ptr;
|
||||
*ptr = (*ptr)->next_;
|
||||
--data_.size_;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
// Copyright 2012 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Include this after the boost headers, but before other test headers.
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
@@ -124,8 +124,8 @@ namespace test
|
||||
: base()
|
||||
{}
|
||||
|
||||
explicit ordered(key_compare const& compare)
|
||||
: base(compare)
|
||||
explicit ordered(key_compare const& kc)
|
||||
: base(kc)
|
||||
{}
|
||||
|
||||
void compare(X const& x)
|
||||
@@ -143,10 +143,10 @@ namespace test
|
||||
}
|
||||
|
||||
template <class It>
|
||||
void insert_range(It begin, It end) {
|
||||
while(begin != end) {
|
||||
this->insert(*begin);
|
||||
++begin;
|
||||
void insert_range(It b, It e) {
|
||||
while(b != e) {
|
||||
this->insert(*b);
|
||||
++b;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,10 +168,10 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<typename... Args> void construct(T* p, Args&&... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -357,11 +357,11 @@ namespace exception
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
|
||||
UNORDERED_EPOINT("Mock allocator construct function.");
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ namespace minimal
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef void_ptr void_pointer;
|
||||
typedef void_const_ptr void_const_pointer;
|
||||
typedef void_const_ptr const_void_pointer;
|
||||
typedef ptr<T> pointer;
|
||||
typedef const_ptr<T> const_pointer;
|
||||
typedef T& reference;
|
||||
@@ -367,9 +367,9 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
new((void*)p) T(std::forward<Args>(args)...);
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -439,9 +439,9 @@ namespace minimal
|
||||
|
||||
void construct(T* p, T const& t) { new((void*)p) T(t); }
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
new((void*)p) T(std::forward<Args>(args)...);
|
||||
new((void*)p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -259,10 +259,10 @@ namespace test
|
||||
new(p) T(t);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
template<class... Args> void construct(T* p, Args&&... args) {
|
||||
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new(p) T(std::forward<Args>(args)...);
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9,13 +9,15 @@ project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
# Would be nice to define -Wundef, but I'm getting warnings from
|
||||
# Boost.Preprocessor on trunk.
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
|
||||
#<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
<toolset>gcc:<warnings-as-errors>on
|
||||
<toolset>darwin:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
test-suite unordered
|
||||
@@ -50,4 +52,20 @@ test-suite unordered
|
||||
[ run equality_tests.cpp ]
|
||||
[ run equality_deprecated.cpp ]
|
||||
[ run swap_tests.cpp ]
|
||||
|
||||
[ run compile_set.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_set ]
|
||||
[ run compile_map.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_compile_map ]
|
||||
[ run copy_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_copy ]
|
||||
[ run move_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_move ]
|
||||
[ run assign_tests.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
: bmove_assign ]
|
||||
;
|
||||
|
||||
@@ -90,7 +90,12 @@ void test_empty_allocator()
|
||||
{
|
||||
typedef empty_allocator<int> allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
|
||||
#endif
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
|
||||
@@ -123,7 +128,12 @@ void test_allocator1()
|
||||
{
|
||||
typedef allocator1<int> allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<allocator> traits;
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
|
||||
#endif
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
|
||||
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
|
||||
@@ -186,6 +196,20 @@ struct ptr
|
||||
T& operator*() const { return *value_; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ptr<void>
|
||||
{
|
||||
void* value_;
|
||||
ptr(void* v) : value_(v) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ptr<const void>
|
||||
{
|
||||
void const* value_;
|
||||
ptr(void const* v) : value_(v) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct allocator3
|
||||
{
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace assign_tests {
|
||||
|
||||
test::seed_t seed(96785);
|
||||
test::seed_t initialize_seed(96785);
|
||||
|
||||
template <class T>
|
||||
void assign_tests1(T*,
|
||||
@@ -208,9 +208,7 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
UNORDERED_AUTO_TEST(assign_initializer_list)
|
||||
{
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <algorithm>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
namespace bucket_tests {
|
||||
|
||||
test::seed_t seed(54635);
|
||||
test::seed_t initialize_seed(54635);
|
||||
|
||||
template <class X>
|
||||
void tests(X* = 0, test::random_generator generator = test::default_generator)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
// requirements. Makes sure everything compiles and is defined correctly.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
// requirements. Makes sure everything compiles and is defined correctly.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include "../helpers/check_return_type.hpp"
|
||||
|
||||
typedef long double comparison_type;
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -17,7 +18,7 @@
|
||||
|
||||
namespace constructor_tests {
|
||||
|
||||
test::seed_t seed(356730);
|
||||
test::seed_t initialize_seed(356730);
|
||||
|
||||
template <class T>
|
||||
void constructor_tests1(T*,
|
||||
@@ -442,8 +443,7 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_initializer_list) {
|
||||
std::cerr<<"Initializer List Tests\n";
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
@@ -15,7 +16,7 @@
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
test::seed_t seed(9063);
|
||||
test::seed_t initialize_seed(9063);
|
||||
|
||||
namespace copy_tests
|
||||
{
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#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"
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/preprocessor/seq.hpp>
|
||||
#include <list>
|
||||
#include "../helpers/test.hpp"
|
||||
@@ -149,6 +150,14 @@ namespace equality_tests
|
||||
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(equality_multiple_group_test)
|
||||
{
|
||||
UNORDERED_EQUALITY_MULTISET_TEST(
|
||||
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
|
||||
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
|
||||
);
|
||||
}
|
||||
|
||||
// Test that equality still works when the two containers have
|
||||
// different hash functions but the same equality predicate.
|
||||
|
||||
@@ -167,7 +176,6 @@ namespace equality_tests
|
||||
set1.insert(20); set2.insert(10);
|
||||
BOOST_TEST(set1 == set2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
// hairy with several tricky edge cases - so explicitly test each one.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/list.hpp"
|
||||
#include <set>
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -20,7 +21,7 @@
|
||||
namespace erase_tests
|
||||
{
|
||||
|
||||
test::seed_t seed(85638);
|
||||
test::seed_t initialize_seed(85638);
|
||||
|
||||
template <class Container>
|
||||
void erase_tests1(Container*,
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -16,7 +17,7 @@
|
||||
namespace find_tests
|
||||
{
|
||||
|
||||
test::seed_t seed(78937);
|
||||
test::seed_t initialize_seed(78937);
|
||||
|
||||
template <class X>
|
||||
void find_tests1(X*, test::random_generator generator = test::default_generator)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
template <typename T>
|
||||
void call_swap(boost::unordered_map<T,T>& x,
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
struct true_type { char x[100]; };
|
||||
struct false_type { char x; };
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace x
|
||||
{
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
namespace insert_tests {
|
||||
|
||||
test::seed_t seed(243432);
|
||||
test::seed_t initialize_seed(243432);
|
||||
|
||||
template <class X>
|
||||
void unique_insert_tests1(X*,
|
||||
@@ -465,8 +466,7 @@ UNORDERED_TEST(map_insert_range_test2,
|
||||
((default_generator)(generate_collisions))
|
||||
)
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
|
||||
!defined(BOOST_NO_INITIALIZER_LISTS)
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_initializer_list_set)
|
||||
{
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
void foo(boost::unordered_set<int>&,
|
||||
boost::unordered_map<int, int>&,
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
void foo(boost::unordered_set<int>& x1,
|
||||
boost::unordered_map<int, int>& x2,
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/limits.hpp>
|
||||
#include "../helpers/random_values.hpp"
|
||||
@@ -19,7 +20,7 @@
|
||||
namespace load_factor_tests
|
||||
{
|
||||
|
||||
test::seed_t seed(783656);
|
||||
test::seed_t initialize_seed(783656);
|
||||
|
||||
template <class X>
|
||||
void set_load_factor_tests(X* = 0)
|
||||
|
||||
@@ -51,7 +51,13 @@ void test_simple_allocator()
|
||||
//BOOST_MPL_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>));
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>));
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type,
|
||||
std::make_unsigned<std::ptrdiff_t>::type>));
|
||||
#else
|
||||
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type, std::size_t>));
|
||||
#endif
|
||||
|
||||
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
|
||||
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
@@ -21,7 +22,12 @@
|
||||
|
||||
namespace move_tests
|
||||
{
|
||||
test::seed_t seed(98624);
|
||||
test::seed_t initialize_seed(98624);
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#define BOOST_UNORDERED_TEST_MOVING 1
|
||||
#else
|
||||
#define BOOST_UNORDERED_TEST_MOVING 0
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
T empty(T*) {
|
||||
@@ -95,7 +101,7 @@ namespace move_tests
|
||||
test::object_count count;
|
||||
T y;
|
||||
y = create(v, count);
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
#endif
|
||||
test::check_container(y, v);
|
||||
@@ -195,7 +201,10 @@ namespace move_tests
|
||||
BOOST_TEST(y.max_load_factor() == 2.0);
|
||||
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING ?
|
||||
(bool) allocator_type::is_propagate_on_move :
|
||||
(bool) allocator_type::is_propagate_on_assign)
|
||||
{
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
@@ -210,7 +219,9 @@ namespace move_tests
|
||||
T y(0, hf, eq, al1);
|
||||
y = create(v, count, hf, eq, al2, 0.5);
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING &&
|
||||
allocator_type::is_propagate_on_move)
|
||||
{
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
}
|
||||
#endif
|
||||
@@ -219,7 +230,10 @@ namespace move_tests
|
||||
BOOST_TEST(y.max_load_factor() == 0.5);
|
||||
|
||||
#if defined(BOOST_HAS_NRVO)
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING ?
|
||||
(bool) allocator_type::is_propagate_on_move :
|
||||
(bool) allocator_type::is_propagate_on_assign)
|
||||
{
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
@@ -240,14 +254,19 @@ namespace move_tests
|
||||
|
||||
test::object_count count = test::global_object_count;
|
||||
y = boost::move(x);
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING &&
|
||||
allocator_type::is_propagate_on_move)
|
||||
{
|
||||
BOOST_TEST(count == test::global_object_count);
|
||||
}
|
||||
test::check_container(y, v);
|
||||
test::check_equivalent_keys(y);
|
||||
BOOST_TEST(y.max_load_factor() == 0.25);
|
||||
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING ?
|
||||
(bool) allocator_type::is_propagate_on_move :
|
||||
(bool) allocator_type::is_propagate_on_assign)
|
||||
{
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
@@ -272,7 +291,9 @@ namespace move_tests
|
||||
|
||||
test::object_count count2 = test::global_object_count;
|
||||
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING &&
|
||||
allocator_type::is_propagate_on_move)
|
||||
{
|
||||
BOOST_TEST(count1.instances ==
|
||||
test::global_object_count.instances);
|
||||
BOOST_TEST(count2.constructions ==
|
||||
@@ -283,7 +304,10 @@ namespace move_tests
|
||||
test::check_equivalent_keys(y);
|
||||
BOOST_TEST(y.max_load_factor() == 0.5);
|
||||
|
||||
if (allocator_type::is_propagate_on_move) {
|
||||
if (BOOST_UNORDERED_TEST_MOVING ?
|
||||
(bool) allocator_type::is_propagate_on_move :
|
||||
(bool) allocator_type::is_propagate_on_assign)
|
||||
{
|
||||
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
@@ -14,7 +15,7 @@
|
||||
namespace rehash_tests
|
||||
{
|
||||
|
||||
test::seed_t seed(2974);
|
||||
test::seed_t initialize_seed(2974);
|
||||
|
||||
template <class X>
|
||||
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
|
||||
@@ -99,6 +100,75 @@ void rehash_test1(X* = 0,
|
||||
tracker.compare(x);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_test1(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
|
||||
{
|
||||
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
|
||||
{
|
||||
test::random_values<X> v(i, generator);
|
||||
|
||||
test::ordered<X> tracker;
|
||||
tracker.insert_range(v.begin(), v.end());
|
||||
|
||||
X x;
|
||||
x.max_load_factor(random_mlf ?
|
||||
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
|
||||
|
||||
// For the current standard this should reserve i+1, I've
|
||||
// submitted a defect report and will assume it's a defect
|
||||
// for now.
|
||||
x.reserve(i);
|
||||
|
||||
// Insert an element before the range insert, otherwise there are
|
||||
// no iterators to invalidate in the range insert, and it can
|
||||
// rehash.
|
||||
typename test::random_values<X>::iterator it = v.begin();
|
||||
x.insert(*it);
|
||||
++it;
|
||||
|
||||
std::size_t bucket_count = x.bucket_count();
|
||||
x.insert(it, v.end());
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
tracker.compare(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void reserve_test2(X* = 0,
|
||||
test::random_generator generator = test::default_generator)
|
||||
{
|
||||
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
|
||||
{
|
||||
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
|
||||
{
|
||||
test::random_values<X> v(i, generator);
|
||||
|
||||
test::ordered<X> tracker;
|
||||
tracker.insert_range(v.begin(), v.end());
|
||||
|
||||
X x;
|
||||
x.max_load_factor(random_mlf ?
|
||||
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
|
||||
|
||||
x.reserve(i);
|
||||
std::size_t bucket_count = x.bucket_count();
|
||||
|
||||
for (typename test::random_values<X>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
x.insert(*it);
|
||||
}
|
||||
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
tracker.compare(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::unordered_set<int>* int_set_ptr;
|
||||
boost::unordered_multiset<int>* int_multiset_ptr;
|
||||
boost::unordered_map<int, int>* int_map_ptr;
|
||||
@@ -116,6 +186,12 @@ UNORDERED_TEST(rehash_empty_test3,
|
||||
UNORDERED_TEST(rehash_test1,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(reserve_test1,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
UNORDERED_TEST(reserve_test2,
|
||||
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
// This test checks the runtime requirements of containers.
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include "../objects/cxx11_allocator.hpp"
|
||||
@@ -24,7 +25,7 @@
|
||||
namespace swap_tests
|
||||
{
|
||||
|
||||
test::seed_t seed(783472);
|
||||
test::seed_t initialize_seed(783472);
|
||||
|
||||
template <class X>
|
||||
void swap_test_impl(X& x1, X& x2)
|
||||
|
||||
@@ -1,14 +1,33 @@
|
||||
#include <iostream>
|
||||
|
||||
// Copyright 2006-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/prefix.hpp"
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
|
||||
# elif defined(_LIBCPP_VERSION)
|
||||
# define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
|
||||
# define BOOST_UNORDERED_VARIADIC_MOVE
|
||||
# endif
|
||||
# elif defined(__STL_CONFIG_H)
|
||||
# elif defined(__MSL_CPP__)
|
||||
# elif defined(__IBMCPP__)
|
||||
# elif defined(MSIPL_COMPILE_H)
|
||||
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace unnecessary_copy_tests
|
||||
{
|
||||
struct count_copies
|
||||
@@ -243,9 +262,7 @@ namespace unnecessary_copy_tests
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user