Compare commits

..
Author SHA1 Message Date
Beman Dawes 01815c1dbd Release 1.48.0 beta 1
[SVN r75132]
2011-10-27 15:04:52 +00:00
63 changed files with 1111 additions and 2325 deletions
-29
View File
@@ -170,33 +170,4 @@ 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]
+3 -1
View File
@@ -36,7 +36,9 @@ A full implementation of `allocator_traits` requires sophisticated
member function detection so that the fallback is used whenever the
member function call is not well formed.
This requires support for SFINAE expressions, which are available on
GCC from version 4.4 and Clang.
GCC from version 4.4 and Clang. They aren't supported by
Visual C++ 2008/2010, but with a bit of hacking it's possible to support
certain use cases.
On other compilers, there's just a test to see if the allocator has
a member, but no check that it can be called. So rather than using a
-12
View File
@@ -963,18 +963,6 @@ 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
View File
@@ -846,18 +846,6 @@ 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==">
@@ -1809,18 +1797,6 @@ 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==">
@@ -2817,18 +2793,6 @@ 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==">
@@ -3794,18 +3758,6 @@ 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,40 +15,21 @@
# pragma once
#endif
#include <boost/unordered/detail/emplace_args.hpp>
#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/assert.hpp>
#include <boost/utility/addressof.hpp>
////////////////////////////////////////////////////////////////////////////////
//
// 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
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
# include <memory>
#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
@@ -94,22 +75,48 @@ namespace boost { namespace unordered { namespace detail {
#endif
////////////////////////////////////////////////////////////////////////////
// Expression test mechanism
// Bits and pieces for implementing traits
//
// 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.
// Some of these are also used elsewhere
#if !defined(BOOST_NO_SFINAE_EXPR)
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&);
};
#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
# 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), \
@@ -118,12 +125,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, \
@@ -135,9 +142,11 @@ 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); \
@@ -151,11 +160,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 { \
@@ -175,90 +184,84 @@ 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)
////////////////////////////////////////////////////////////////////////////////
//
// Allocator traits
//
// First our implementation, then later light wrappers around the alternatives
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
template <typename Alloc>
struct allocator_traits : std::allocator_traits<Alloc> {};
# 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
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename std::allocator_traits<Alloc>::rebind_alloc<T> type;
};
# 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 {
#else
// 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);
@@ -270,8 +273,7 @@ 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 !defined(BOOST_NO_SFINAE_EXPR)
#if BOOST_UNORDERED_HAVE_CALL_DETECTION
template <typename T>
BOOST_UNORDERED_HAS_FUNCTION(
select_on_container_copy_construction, U const, (), 0
@@ -282,33 +284,18 @@ 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);
@@ -320,8 +307,7 @@ 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<
@@ -389,7 +375,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.
@@ -397,49 +383,13 @@ 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:
# 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)
// Only supporting the basic copy constructor for now.
template <typename T>
static typename boost::enable_if_c<
@@ -473,67 +423,19 @@ 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(
@@ -546,117 +448,12 @@ 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
////////////////////////////////////////////////////////////////////////////////
//
// 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."
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
#undef BOOST_UNORDERED_DEFAULT_TYPE
#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
@@ -712,9 +509,7 @@ namespace boost { namespace unordered { namespace detail {
ptr_ = pointer();
return p;
}
private:
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
};
+67 -454
View File
@@ -13,12 +13,11 @@
#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)
@@ -30,10 +29,7 @@ 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, typename Policy>
struct buckets;
template <typename Types> struct table_impl;
template <typename Types> struct grouped_table_impl;
template <typename A, typename Bucket, typename Node> struct buckets;
///////////////////////////////////////////////////////////////////
//
@@ -53,14 +49,16 @@ namespace boost { namespace unordered { namespace detail {
node_allocator& alloc_;
node_pointer node_;
bool constructed_;
bool node_constructed_;
bool value_constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
constructed_(false)
node_constructed_(false),
value_constructed_(false)
{
}
@@ -71,40 +69,26 @@ namespace boost { namespace unordered { namespace detail {
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
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;
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
boost::unordered::detail::construct_impl(
node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
}
template <typename A0>
void construct_value2(BOOST_FWD_REF(A0) a0)
{
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_));
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
boost::unordered::detail::construct_impl2(
node_->value_ptr(), boost::forward<A0>(a0));
value_constructed_ = true;
}
value_type const& value() const {
BOOST_ASSERT(node_ && constructed_);
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
return node_->value();
}
node_pointer get()
{
return node_;
}
// no throw
node_pointer release()
{
@@ -122,8 +106,12 @@ namespace boost { namespace unordered { namespace detail {
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (constructed_) {
boost::unordered::detail::destroy_node(alloc_,
if (value_constructed_) {
boost::unordered::detail::destroy(node_->value_ptr());
}
if (node_constructed_) {
node_allocator_traits::destroy(alloc_,
boost::addressof(*node_));
}
@@ -135,13 +123,24 @@ namespace boost { namespace unordered { namespace detail {
void node_constructor<Alloc>::construct_node()
{
if(!node_) {
constructed_ = false;
node_constructed_ = false;
value_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 if (constructed_) {
boost::unordered::detail::destroy_node(alloc_,
boost::addressof(*node_));
constructed_ = false;
else {
BOOST_ASSERT(node_constructed_);
if (value_constructed_)
{
boost::unordered::detail::destroy(node_->value_ptr());
value_constructed_ = false;
}
}
}
@@ -180,373 +179,12 @@ 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, typename Policy>
struct buckets : Policy
template <typename A, typename Bucket, typename Node>
struct buckets
{
private:
buckets(buckets const&);
@@ -555,7 +193,6 @@ 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
@@ -577,16 +214,6 @@ 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_;
@@ -620,7 +247,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_bucket_count() const
{
// -1 to account for the start bucket.
return policy::prev_bucket_count(
return boost::unordered::detail::prev_prime(
bucket_allocator_traits::max_size(bucket_alloc()) - 1);
}
@@ -639,17 +266,16 @@ namespace boost { namespace unordered { namespace detail {
return this->get_bucket(bucket_index)->next_;
}
iterator get_start() const
node_pointer get_start() const
{
return iterator(static_cast<node_pointer>(
this->get_previous_start()->next_));
return static_cast<node_pointer>(this->get_previous_start()->next_);
}
iterator get_start(std::size_t bucket_index) const
node_pointer get_start(std::size_t bucket_index) const
{
previous_pointer prev = this->get_previous_start(bucket_index);
return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
iterator();
return prev ? static_cast<node_pointer>(prev->next_) :
node_pointer();
}
float load_factor() const
@@ -662,15 +288,14 @@ namespace boost { namespace unordered { namespace detail {
std::size_t bucket_size(std::size_t index) const
{
if (!this->size_) return 0;
iterator it = this->get_start(index);
if (!it.node_) return 0;
node_pointer ptr = this->get_start(index);
if (!ptr) return 0;
std::size_t count = 0;
while(it.node_ && policy::to_bucket(
this->bucket_count_, it.node_->hash_) == index)
while(ptr && ptr->hash_ % this->bucket_count_ == index)
{
++count;
++it;
ptr = static_cast<node_pointer>(ptr->next_);
}
return count;
@@ -724,14 +349,6 @@ 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();
@@ -774,21 +391,21 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////
// Delete/destruct
inline void delete_node(c_iterator n)
inline void delete_node(node_pointer n)
{
boost::unordered::detail::destroy_node(
node_alloc(), boost::addressof(*n.node_));
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
boost::unordered::detail::destroy(n->value_ptr());
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
--size_;
}
std::size_t delete_nodes(c_iterator begin, c_iterator end)
std::size_t delete_nodes(node_pointer begin, node_pointer end)
{
std::size_t count = 0;
while(begin != end) {
c_iterator n = begin;
++begin;
node_pointer n = begin;
begin = static_cast<node_pointer>(begin->next_);
delete_node(n);
++count;
}
@@ -799,8 +416,7 @@ 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(),
static_cast<typename node::node_base*>(boost::addressof(*n)));
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
}
@@ -817,7 +433,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(iterator(n));
delete_node(n);
}
delete_extra_node(prev);
@@ -847,7 +463,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(iterator(n));
delete_node(n);
}
bucket_pointer end = this->get_bucket(this->bucket_count_);
@@ -861,24 +477,22 @@ 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 this_bucket,
void fix_buckets(bucket_pointer bucket,
previous_pointer prev, node_pointer next)
{
if (!next)
{
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
if (bucket->next_ == prev) bucket->next_ = node_pointer();
}
else
{
bucket_pointer next_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, next->hash_));
next->hash_ % this->bucket_count_);
if (next_bucket != this_bucket)
if (next_bucket != bucket)
{
next_bucket->next_ = prev;
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
if (bucket->next_ == prev) bucket->next_ = node_pointer();
}
}
}
@@ -899,7 +513,7 @@ namespace boost { namespace unordered { namespace detail {
if (n == end) return;
std::size_t new_bucket_index =
policy::to_bucket(this->bucket_count_, n->hash_);
n->hash_ % this->bucket_count_;
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
break;
@@ -915,7 +529,7 @@ namespace boost { namespace unordered { namespace detail {
if (n == end) break;
std::size_t new_bucket_index =
policy::to_bucket(this->bucket_count_, n->hash_);
n->hash_ % this->bucket_count_;
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
this->get_bucket(bucket_index)->next_ = previous_pointer();
@@ -924,8 +538,7 @@ namespace boost { namespace unordered { namespace detail {
// Finally fix the bucket containing the trailing node.
if (n) {
this->get_bucket(
policy::to_bucket(this->bucket_count_, n->hash_))->next_
this->get_bucket(n->hash_ % this->bucket_count_)->next_
= prev;
}
}
+52 -143
View File
@@ -12,7 +12,6 @@
# pragma once
#endif
#include <boost/unordered/detail/fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
@@ -22,14 +21,13 @@
#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)
#include <tuple>
#elif defined(BOOST_HAS_TR1_TUPLE)
#include <tr1/tuple>
#endif
#if defined(BOOST_MSVC)
@@ -44,54 +42,35 @@
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
!defined(BOOST_NO_VARIADIC_TEMPLATES)
#define 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_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
#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_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
#define BOOST_UNORDERED_EMPLACE_FORWARD std::forward<Args>(args)...
#else
@@ -111,7 +90,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, b) \
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, B, a) \
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
{} \
\
@@ -121,34 +100,34 @@ 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, b) \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \
return e; \
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(B, n); \
BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)( \
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(b, n)))
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(a, n)))
#else
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
BOOST_PP_CAT(B, n); \
BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
#endif
@@ -196,11 +175,9 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
//
// Used for piecewise construction.
#if !defined(__SUNPRO_CC)
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
#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(); \
} \
@@ -208,74 +185,31 @@ 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)
#else
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
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::)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
#elif defined(BOOST_HAS_TR1_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1)
#endif
#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.
@@ -327,7 +261,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
#endif
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
////////////////////////////////////////////////////////////////////////////
// Construct from variadic parameters
@@ -335,7 +269,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename T, typename... Args>
inline void construct_impl(T* address, Args&&... args)
{
new((void*) address) T(boost::forward<Args>(args)...);
new((void*) address) T(std::forward<Args>(args)...);
}
template <typename A, typename B, typename A0, typename A1, typename A2>
@@ -354,7 +288,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
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(boost::forward<A0>(a0));
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B();
}
@@ -362,10 +296,10 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
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(boost::forward<A0>(a0));
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(a1),
boost::forward<A2>(a2));
std::forward<A1>(a1),
std::forward<A2>(a2));
}
template <typename A, typename B,
@@ -374,17 +308,17 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
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(boost::forward<A0>(a0));
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(a1),
boost::forward<A2>(a2),
boost::forward<A3>(a3),
boost::forward<Args>(args)...);
std::forward<A1>(a1),
std::forward<A2>(a2),
std::forward<A3>(a3),
std::forward<Args>(args)...);
}
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
#else // BOOST_UNORDERED_VARIADIC_MOVE
#else // BOOST_UNORDERED_STD_FORWARD_MOVE
////////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
@@ -404,32 +338,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
args.a)); \
}
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_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
@@ -496,7 +405,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
#undef BOOST_UNORDERED_CALL_FORWARD2
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
#endif // BOOST_UNORDERED_VARIADIC_MOVE
#endif // BOOST_UNORDERED_STD_FORWARD_MOVE
////////////////////////////////////////////////////////////////////////////
// Construct without using the emplace args mechanism.
+143 -197
View File
@@ -12,6 +12,7 @@
#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 {
@@ -22,40 +23,20 @@ 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() :
node_base(),
next_(),
group_prev_(),
hash_(0)
{}
#endif
void init(link_pointer self)
{
@@ -69,33 +50,16 @@ 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)
{
@@ -151,46 +115,42 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
template <typename A, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef boost::unordered::detail::multiset<A, H, P> types;
typedef T value_type;
typedef A allocator;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef value_type key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_grouped_node<A, 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 M, typename H, typename P>
template <typename A, typename K, typename H, typename P>
struct multimap
{
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
typedef boost::unordered::detail::multimap<A, K, H, P> types;
typedef std::pair<K const, M> value_type;
typedef A allocator;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -198,8 +158,6 @@ 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>
@@ -209,7 +167,6 @@ 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;
@@ -221,8 +178,6 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_type key_type;
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
@@ -256,61 +211,57 @@ namespace boost { namespace unordered { namespace detail {
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
node_pointer find_node_impl(
std::size_t hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
for (;;)
{
if (!n.node_) return n;
if (!n) return n;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
std::size_t node_hash = n->hash_;
if (hash == node_hash)
{
if (eq(k, this->get_key(*n)))
if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
}
n = iterator(static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_));
n = static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
}
}
std::size_t count(key_type const& k) const
{
iterator n = this->find_node(k);
if (!n.node_) return 0;
node_pointer n = this->find_node(k);
if (!n) return 0;
std::size_t x = 0;
node_pointer it = n.node_;
std::size_t count = 0;
node_pointer it = n;
do {
it = static_cast<node_pointer>(it->group_prev_);
++x;
} while(it != n.node_);
++count;
} while(it != n);
return x;
return count;
}
std::pair<iterator, iterator>
std::pair<node_pointer, node_pointer>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
return std::make_pair(
n, n.node_ ? iterator(
static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_
)) : n);
node_pointer n = this->find_node(k);
return std::make_pair(n,
n ? static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_) : n);
}
// Equality
@@ -320,14 +271,14 @@ namespace boost { namespace unordered { namespace detail {
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(iterator n1 = this->get_start(); n1.node_;)
for(node_pointer n1 = this->get_start(); n1;)
{
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_));
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_);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -337,24 +288,25 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
{
for(;;)
{
if (*n1 != *n2) break;
if (n1->value() != n2->value())
break;
++n1;
++n2;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(iterator n1a = n1, n2a = n2;;)
for(node_pointer n1a = n1, n2a = n2;;)
{
++n1a;
++n2a;
n1a = static_cast<node_pointer>(n1a->next_);
n2a = static_cast<node_pointer>(n2a->next_);
if (n1a == end1)
{
@@ -365,50 +317,50 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
iterator start = n1;
for(;n1 != end1; ++n1)
node_pointer start = n1;
for(;n1 != end2; n1 = static_cast<node_pointer>(n1->next_))
{
value_type const& v = *n1;
value_type const& v = n1->value();
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
if (!matches || matches != 1 + count_equal(
static_cast<node_pointer>(n1->next_), end1, v))
return false;
}
return true;
}
static bool find(iterator n, iterator end, value_type const& v)
static bool find(node_pointer n, node_pointer end, value_type const& v)
{
for(;n != end; ++n)
if (*n == v)
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v)
return true;
return false;
}
static std::size_t count_equal(iterator n, iterator end,
static std::size_t count_equal(node_pointer n, node_pointer end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; ++n)
if (*n == v) ++count;
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v) ++count;
return count;
}
#else
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
{
for(;;)
{
if(!extractor::compare_mapped(*n1, *n2))
if(!extractor::compare_mapped(
n1->value(), n2->value()))
return false;
++n1;
++n2;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
@@ -430,37 +382,35 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = static_cast<link_pointer>(n);
}
inline iterator add_node(
inline node_pointer add_node(
node_constructor& a,
std::size_t key_hash,
iterator pos)
std::size_t hash,
node_pointer pos)
{
node_pointer n = a.release();
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
n->hash_ = hash;
if(pos) {
this->add_after_node(n, pos);
if (n->next_) {
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)) {
std::size_t next_bucket =
static_cast<node_pointer>(n->next_)->hash_ %
this->bucket_count_;
if (next_bucket != hash % this->bucket_count_) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(
policy::to_bucket(this->bucket_count_, key_hash));
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(policy::to_bucket(this->bucket_count_,
this->get_bucket(
static_cast<node_pointer>(start_node->next_)->hash_
))->next_ = n;
% this->bucket_count_)->next_ = n;
}
b->next_ = start_node;
@@ -474,45 +424,46 @@ namespace boost { namespace unordered { namespace detail {
}
}
++this->size_;
return iterator(n);
return n;
}
iterator emplace_impl(node_constructor& a)
node_pointer emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer position = this->find_node(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, key_hash, position);
return this->add_node(a, hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
std::size_t hash = this->hash_function()(k);
this->add_node(a, hash,
this->find_node(hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
iterator emplace(boost::unordered::detail::emplace_args1<
node_pointer emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
return this->begin();
}
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
node_pointer emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return iterator(emplace_impl(a));
return emplace_impl(a);
}
////////////////////////////////////////////////////////////////////////
@@ -567,12 +518,11 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
bucket_pointer this_bucket = this->get_bucket(bucket_index);
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);
previous_pointer prev = this_bucket->next_;
previous_pointer prev = bucket->next_;
if (!prev) return 0;
for (;;)
@@ -580,10 +530,9 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
if (node_hash % this->bucket_count_ != bucket_index)
return 0;
if (node_hash == key_hash &&
if (node_hash == hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
@@ -596,39 +545,37 @@ 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(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
}
iterator erase(c_iterator r)
node_pointer erase(node_pointer r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
previous_pointer prev = unlink_node(*this_bucket, r.node_);
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
this->fix_buckets(this_bucket, prev, next.node_);
this->fix_buckets(bucket, prev, next);
this->delete_node(r);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
node_pointer erase_range(node_pointer r1, node_pointer r2)
{
if (r1 == r2) return iterator(r2.node_);
if (r1 == r2) return r2;
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1.node_, r2.node_);
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
this->delete_nodes(r1, r2);
return iterator(r2.node_);
return r2;
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
@@ -745,31 +692,31 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
iterator n = src.get_start();
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_
));
static_cast<node_pointer>(n->group_prev_)->next_);
a.construct_node();
a.construct_value2(*n);
a.construct_value2(n->value());
node_pointer first_node = a.release();
node_pointer end = first_node;
first_node->hash_ = key_hash;
first_node->hash_ = hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for (++n; n != group_end; ++n)
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
{
a.construct_node();
a.construct_value2(*n);
a.construct_value2(n->value());
end = a.release();
end->hash_ = key_hash;
end->hash_ = hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -792,31 +739,31 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
iterator n = src.get_start();
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_
));
static_cast<node_pointer>(n->group_prev_)->next_);
a.construct_node();
a.construct_value2(boost::move(*n));
a.construct_value2(boost::move(n->value()));
node_pointer first_node = a.release();
node_pointer end = first_node;
first_node->hash_ = key_hash;
first_node->hash_ = hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for(++n; n != group_end; ++n)
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
{
a.construct_node();
a.construct_value2(boost::move(*n));
a.construct_value2(boost::move(n->value()));
end = a.release();
end->hash_ = key_hash;
end->hash_ = hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -857,8 +804,7 @@ 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(policy::to_bucket(
dst.bucket_count_, end->hash_));
bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
if (!b->next_) {
b->next_ = static_cast<node_pointer>(prev);
+20 -3
View File
@@ -51,17 +51,25 @@ 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_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
@@ -98,6 +106,13 @@ 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)
{
@@ -111,7 +126,7 @@ namespace detail {
return v.first;
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class Arg1, class... Args>
static key_type const& extract(key_type const& k,
Arg1 const&, Args const&...)
@@ -150,7 +165,7 @@ namespace detail {
}
#endif
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
@@ -193,6 +208,8 @@ BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
#elif defined(BOOST_HAS_TR1_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::tr1)
#endif
+30
View File
@@ -10,11 +10,41 @@
# 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();
}
+276 -43
View File
@@ -11,8 +11,251 @@
#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 {
////////////////////////////////////////////////////////////////////////////
@@ -59,8 +302,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::buckets<
typename Types::allocator,
typename Types::bucket,
typename Types::node,
typename Types::policy>,
typename Types::node>,
boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal>
@@ -76,7 +318,6 @@ 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,
@@ -85,15 +326,22 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::buckets<
typename Types::allocator,
typename Types::bucket,
typename Types::node,
typename Types::policy> buckets;
typename Types::node> 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 typename table::iterator iterator;
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;
// Members
@@ -136,7 +384,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t min_buckets_for_size(std::size_t size) const
{
BOOST_ASSERT(this->mlf_ >= minimum_max_load_factor);
BOOST_ASSERT(this->mlf_ != 0);
using namespace std;
@@ -147,7 +395,7 @@ namespace boost { namespace unordered { namespace detail {
// Or from rehash post-condition:
// count > size / mlf_
return policy::new_bucket_count(
return boost::unordered::detail::next_prime(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_))) + 1);
@@ -160,7 +408,7 @@ namespace boost { namespace unordered { namespace detail {
hasher const& hf,
key_equal const& eq,
node_allocator const& a) :
buckets(a, policy::new_bucket_count(num_buckets)),
buckets(a, boost::unordered::detail::next_prime(num_buckets)),
functions(hf, eq),
mlf_(1.0f),
max_load_(0)
@@ -210,9 +458,9 @@ namespace boost { namespace unordered { namespace detail {
// Iterators
iterator begin() const {
node_pointer begin() const {
return !this->buckets_ ?
iterator() : this->get_start();
node_pointer() : this->get_start();
}
// Assignment
@@ -338,41 +586,36 @@ 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>
iterator generic_find_node(
node_pointer generic_find_node(
Key const& k,
Hash const& hf,
Hash const& hash_function,
Pred const& eq) const
{
if (!this->size_) return iterator();
if (!this->size_) return node_pointer();
return static_cast<table_impl const*>(this)->
find_node_impl(policy::apply_hash(hf, k), k, eq);
find_node_impl(hash_function(k), k, eq);
}
iterator find_node(
std::size_t key_hash,
node_pointer find_node(
std::size_t hash,
key_type const& k) const
{
if (!this->size_) return iterator();
if (!this->size_) return node_pointer();
return static_cast<table_impl const*>(this)->
find_node_impl(key_hash, k, this->key_eq());
find_node_impl(hash, k, this->key_eq());
}
iterator find_node(key_type const& k) const
node_pointer find_node(key_type const& k) const
{
if (!this->size_) return iterator();
if (!this->size_) return node_pointer();
return static_cast<table_impl const*>(this)->
find_node_impl(this->hash(k), k, this->key_eq());
find_node_impl(this->hash_function()(k), k, this->key_eq());
}
iterator find_matching_node(iterator n) const
node_pointer find_matching_node(node_pointer n) const
{
// TODO: Does this apply to C++11?
//
@@ -380,14 +623,13 @@ 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));
return find_node(get_key(n->value()));
}
// Reserve and rehash
void reserve_for_insert(std::size_t);
void rehash(std::size_t);
void reserve(std::size_t);
};
////////////////////////////////////////////////////////////////////////////
@@ -403,9 +645,7 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets();
this->max_load_ = this->calculate_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_) {
else if(size >= max_load_) {
std::size_t num_buckets
= this->min_buckets_for_size((std::max)(size,
this->size_ + (this->size_ >> 1)));
@@ -420,16 +660,16 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise.
template <typename Types>
inline void table<Types>::rehash(std::size_t min_buckets)
void table<Types>::rehash(std::size_t min_buckets)
{
using namespace std;
if(!this->size_) {
if(this->buckets_) this->delete_buckets();
this->bucket_count_ = policy::new_bucket_count(min_buckets);
this->bucket_count_ = next_prime(min_buckets);
}
else {
min_buckets = policy::new_bucket_count((std::max)(min_buckets,
min_buckets = next_prime((std::max)(min_buckets,
boost::unordered::detail::double_to_size(floor(
static_cast<double>(this->size_) /
static_cast<double>(mlf_))) + 1));
@@ -440,13 +680,6 @@ 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
+108 -158
View File
@@ -12,49 +12,31 @@
#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 unique_node;
template <typename A, typename T> struct node;
template <typename T> struct ptr_node;
template <typename Types> struct table_impl;
template <typename A, typename T>
struct unique_node :
boost::unordered::detail::node_base<
typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type::pointer
>,
struct node :
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type::pointer link_pointer;
typedef boost::unordered::detail::node_base<link_pointer> node_base;
A, node<A, T> >::type::pointer link_pointer;
link_pointer next_;
std::size_t hash_;
#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(),
node() :
next_(),
hash_(0)
{}
#endif
void init(link_pointer)
{
@@ -67,30 +49,14 @@ 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)
{
@@ -103,7 +69,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_node2
{
typedef boost::unordered::detail::unique_node<A, T> node;
typedef boost::unordered::detail::node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
@@ -145,46 +111,42 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
template <typename A, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef boost::unordered::detail::set<A, H, P> types;
typedef T value_type;
typedef A allocator;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef value_type key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_node<A, 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 M, typename H, typename P>
template <typename A, typename K, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef boost::unordered::detail::map<A, K, H, P> types;
typedef std::pair<K const, M> value_type;
typedef A allocator;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -192,8 +154,6 @@ 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>
@@ -203,7 +163,6 @@ 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;
@@ -215,10 +174,8 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_type key_type;
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;
typedef std::pair<node_pointer, bool> emplace_return;
// Constructors
@@ -252,59 +209,56 @@ namespace boost { namespace unordered { namespace detail {
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
std::size_t key_hash,
node_pointer find_node_impl(
std::size_t hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
for (;;)
{
if (!n.node_) return n;
if (!n) return n;
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
std::size_t node_hash = n->hash_;
if (hash == node_hash)
{
if (eq(k, this->get_key(*n)))
if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
}
++n;
n = static_cast<node_pointer>(n->next_);
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k).node_ ? 1 : 0;
return this->find_node(k) ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
iterator it = this->find_node(k);
if (it.node_) return *it;
node_pointer it = this->find_node(k);
if (it) return it->value();
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
std::pair<iterator, iterator>
std::pair<node_pointer, node_pointer>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
node_pointer n = this->find_node(k);
return std::make_pair(n,
n ? static_cast<node_pointer>(n->next_) : n);
}
// equals
@@ -314,15 +268,17 @@ namespace boost { namespace unordered { namespace detail {
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(iterator n1 = this->get_start(); n1.node_; ++n1)
for(node_pointer n1 = this->get_start(); n1;
n1 = static_cast<node_pointer>(n1->next_))
{
iterator n2 = other.find_matching_node(n1);
node_pointer n2 = other.find_matching_node(n1);
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if (!n2.node_ || *n1 != *n2)
if(!n2 || n1->value() != n2->value())
return false;
#else
if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
if(!n2 || !extractor::compare_mapped(
n1->value(), n2->value()))
return false;
#endif
}
@@ -332,24 +288,23 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline iterator add_node(
inline node_pointer add_node(
node_constructor& a,
std::size_t key_hash)
std::size_t hash)
{
node_pointer n = a.release();
n->hash_ = key_hash;
n->hash_ = hash;
bucket_pointer b = this->get_bucket(
policy::to_bucket(this->bucket_count_, key_hash));
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(policy::to_bucket(this->bucket_count_,
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
this->get_bucket(
static_cast<node_pointer>(start_node->next_)->hash_ %
this->bucket_count_)->next_ = n;
}
b->next_ = start_node;
@@ -363,23 +318,23 @@ namespace boost { namespace unordered { namespace detail {
}
++this->size_;
return iterator(n);
return n;
}
value_type& operator[](key_type const& k)
{
typedef typename value_type::second_type mapped_type;
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
if (pos.node_) return *pos;
if (pos) return pos->value();
// 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_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
a.construct_value(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple());
#else
@@ -391,7 +346,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
this->reserve_for_insert(this->size_ + 1);
return *add_node(a, key_hash);
return add_node(a, hash)->value();
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
@@ -406,7 +361,7 @@ namespace boost { namespace unordered { namespace detail {
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
@@ -418,7 +373,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
#if !defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
@@ -431,10 +386,10 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
if (pos.node_) return emplace_return(pos, false);
if (pos) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
@@ -445,21 +400,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(this->add_node(a, key_hash), true);
return emplace_return(this->add_node(a, hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
if (pos.node_) return emplace_return(pos, false);
if (pos) 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(this->add_node(a, key_hash), true);
return emplace_return(this->add_node(a, hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
@@ -515,12 +470,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 key_hash = this->hash(k);
std::size_t hash = this->hash_function()(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, key_hash);
this->add_node(a, hash);
}
template <class InputIt>
@@ -528,19 +483,19 @@ namespace boost { namespace unordered { namespace detail {
InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
if (!pos.node_) {
if (!pos) {
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, key_hash);
this->add_node(a, hash);
}
}
@@ -565,12 +520,11 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
bucket_pointer this_bucket = this->get_bucket(bucket_index);
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);
previous_pointer prev = this_bucket->next_;
previous_pointer prev = bucket->next_;
if (!prev) return 0;
for (;;)
@@ -578,10 +532,9 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
if (node_hash % this->bucket_count_ != bucket_index)
return 0;
if (node_hash == key_hash &&
if (node_hash == hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
@@ -591,39 +544,37 @@ 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(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
}
iterator erase(c_iterator r)
node_pointer erase(node_pointer r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
previous_pointer prev = unlink_node(*this_bucket, r.node_);
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
this->fix_buckets(this_bucket, prev, next.node_);
this->fix_buckets(bucket, prev, next);
this->delete_node(r);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
node_pointer erase_range(node_pointer r1, node_pointer r2)
{
if (r1 == r2) return iterator(r2.node_);
if (r1 == r2) return r2;
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1.node_, r2.node_);
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
this->delete_nodes(r1, r2);
return iterator(r2.node_);
return r2;
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
@@ -656,18 +607,18 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
iterator n = src.get_start();
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n.node_) {
while(n) {
a.construct_node();
a.construct_value2(*n);
a.construct_value2(n->value());
node_pointer node = a.release();
node->hash_ = n.node_->hash_;
node->hash_ = n->hash_;
prev->next_ = static_cast<link_pointer>(node);
++dst.size_;
++n;
n = static_cast<node_pointer>(n->next_);
prev = place_in_bucket(dst, prev);
}
@@ -687,18 +638,18 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
iterator n = src.get_start();
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
while(n) {
a.construct_node();
a.construct_value2(boost::move(*n));
a.construct_value2(boost::move(n->value()));
node_pointer node = a.release();
node->hash_ = n.node_->hash_;
node->hash_ = n->hash_;
prev->next_ = static_cast<link_pointer>(node);
++dst.size_;
++n;
n = static_cast<node_pointer>(n->next_);
prev = place_in_bucket(dst, prev);
}
@@ -735,8 +686,7 @@ namespace boost { namespace unordered { namespace detail {
previous_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(
buckets::to_bucket(dst.bucket_count_, n->hash_));
bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
if (!b->next_) {
b->next_ = prev;
+1 -1
View File
@@ -56,7 +56,7 @@ namespace boost { namespace unordered { namespace detail {
// primes
#define BOOST_UNORDERED_PRIMES \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(5ul)(11ul)(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) \
+96 -297
View File
@@ -41,9 +41,7 @@ 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:
@@ -56,9 +54,15 @@ namespace unordered
private:
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 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 typename types::table table;
public:
@@ -80,7 +84,7 @@ namespace unordered
private:
table table_;
public:
// constructors
@@ -117,17 +121,10 @@ 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&);
@@ -148,7 +145,6 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
{
table_.assign(x.table_);
@@ -160,21 +156,6 @@ 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>);
@@ -203,12 +184,12 @@ namespace unordered
iterator begin()
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end()
@@ -223,7 +204,7 @@ namespace unordered
const_iterator cbegin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const
@@ -233,115 +214,20 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
return iterator(table_.emplace(std::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) \
@@ -365,18 +251,39 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return iterator(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(4, BOOST_UNORDERED_EMPLACE_LIMIT,
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))
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)
@@ -465,8 +372,7 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
return table_.hash_function()(k) % table_.bucket_count_;
}
local_iterator begin(size_type n)
@@ -515,7 +421,6 @@ 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>(
@@ -528,9 +433,8 @@ 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;
@@ -542,9 +446,15 @@ namespace unordered
private:
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 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 typename types::table table;
public:
@@ -603,17 +513,10 @@ 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&);
@@ -634,7 +537,6 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap& operator=(
BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
{
@@ -647,21 +549,6 @@ 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>);
@@ -690,12 +577,12 @@ namespace unordered
iterator begin()
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end()
@@ -710,7 +597,7 @@ namespace unordered
const_iterator cbegin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const
@@ -720,115 +607,20 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
iterator emplace(Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return iterator(table_.emplace(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return iterator(table_.emplace(std::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) \
@@ -837,11 +629,11 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return iterator(table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)); \
))); \
} \
\
template < \
@@ -852,18 +644,39 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
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(4, BOOST_UNORDERED_EMPLACE_LIMIT,
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))
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)
@@ -948,8 +761,7 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
return table_.hash_function()(k) % table_.bucket_count_;
}
local_iterator begin(size_type n)
@@ -998,7 +810,6 @@ 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>(
@@ -1143,7 +954,7 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::erase(const_iterator position)
{
return table_.erase(position);
return iterator(table_.erase(position.node_));
}
template <class K, class T, class H, class P, class A>
@@ -1158,7 +969,7 @@ namespace unordered
unordered_map<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return table_.erase_range(first, last);
return iterator(table_.erase_range(first.node_, last.node_));
}
template <class K, class T, class H, class P, class A>
@@ -1216,14 +1027,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 table_.find_node(k);
return iterator(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 table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
@@ -1235,7 +1046,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return table_.generic_find_node(k, hash, eq);
return iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1247,7 +1058,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1302,12 +1113,6 @@ 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,
@@ -1476,7 +1281,7 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
{
return table_.erase(position);
return iterator(table_.erase(position.node_));
}
template <class K, class T, class H, class P, class A>
@@ -1491,7 +1296,7 @@ namespace unordered
unordered_multimap<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return table_.erase_range(first, last);
return iterator(table_.erase_range(first.node_, last.node_));
}
template <class K, class T, class H, class P, class A>
@@ -1528,14 +1333,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 table_.find_node(k);
return iterator(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 table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
@@ -1547,7 +1352,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return table_.generic_find_node(k, hash, eq);
return iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1559,7 +1364,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1614,12 +1419,6 @@ 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,23 +10,12 @@
# 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&);
@@ -37,13 +26,6 @@ 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&);
+96 -298
View File
@@ -41,9 +41,7 @@ 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;
@@ -54,9 +52,15 @@ namespace unordered
private:
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
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 typename types::table table;
public:
@@ -115,17 +119,10 @@ 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&);
@@ -146,7 +143,6 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
{
table_.assign(x.table_);
@@ -158,21 +154,6 @@ 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>);
@@ -201,12 +182,12 @@ namespace unordered
iterator begin()
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end()
@@ -221,7 +202,7 @@ namespace unordered
const_iterator cbegin() const
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const
@@ -231,115 +212,20 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
return iterator(table_.emplace(std::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) \
@@ -363,18 +249,39 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return iterator(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(4, BOOST_UNORDERED_EMPLACE_LIMIT,
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))
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)
@@ -450,8 +357,7 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
return table_.hash_function()(k) % table_.bucket_count_;
}
local_iterator begin(size_type n)
@@ -500,7 +406,6 @@ 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>(
@@ -513,9 +418,7 @@ 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;
@@ -526,9 +429,15 @@ namespace unordered
private:
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
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 typename types::table table;
public:
@@ -587,17 +496,10 @@ 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&);
@@ -618,7 +520,6 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset& operator=(
BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
{
@@ -631,21 +532,6 @@ 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>);
@@ -704,25 +590,56 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template <class... Args>
iterator emplace(Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return iterator(table_.emplace(std::forward<Args>(args)...));
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return iterator(table_.emplace(std::forward<Args>(args)...));
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
#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) \
))); \
}
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
// doesn't have a default constructor.
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))
iterator emplace(
boost::unordered::detail::empty_emplace
@@ -743,111 +660,6 @@ 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)
@@ -923,8 +735,7 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
return table_.hash_function()(k) % table_.bucket_count_;
}
local_iterator begin(size_type n)
@@ -973,7 +784,6 @@ 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>(
@@ -1118,7 +928,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::erase(const_iterator position)
{
return table_.erase(position);
return iterator(table_.erase(position.node_));
}
template <class T, class H, class P, class A>
@@ -1133,7 +943,7 @@ namespace unordered
unordered_set<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return table_.erase_range(first, last);
return iterator(table_.erase_range(first.node_, last.node_));
}
template <class T, class H, class P, class A>
@@ -1170,7 +980,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 table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class T, class H, class P, class A>
@@ -1182,7 +992,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class T, class H, class P, class A>
@@ -1228,12 +1038,6 @@ 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,
@@ -1402,7 +1206,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::erase(const_iterator position)
{
return table_.erase(position);
return iterator(table_.erase(position.node_));
}
template <class T, class H, class P, class A>
@@ -1417,7 +1221,7 @@ namespace unordered
unordered_multiset<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return table_.erase_range(first, last);
return iterator(table_.erase_range(first.node_, last.node_));
}
template <class T, class H, class P, class A>
@@ -1454,7 +1258,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 table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class T, class H, class P, class A>
@@ -1466,7 +1270,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class T, class H, class P, class A>
@@ -1512,12 +1316,6 @@ 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,22 +10,12 @@
# 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&);
@@ -36,12 +26,6 @@ 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 -1
View File
@@ -3,6 +3,8 @@
// 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"
@@ -11,7 +13,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
test::seed_t seed(12847);
template <class T>
struct self_assign_base : public test::exception_base
@@ -3,13 +3,15 @@
// 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 initialize_seed(91274);
test::seed_t seed(91274);
struct objects
{
-2
View File
@@ -3,10 +3,8 @@
// 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 -1
View File
@@ -3,12 +3,14 @@
// 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 initialize_seed(73041);
test::seed_t seed(73041);
template <class T>
struct copy_test1 : public test::exception_base
+3 -1
View File
@@ -3,12 +3,14 @@
// 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 initialize_seed(835193);
test::seed_t seed(835193);
template <class T>
struct erase_test_base : public test::exception_base
+3 -1
View File
@@ -3,6 +3,8 @@
// 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"
@@ -11,7 +13,7 @@
#include <boost/utility.hpp>
#include <cmath>
test::seed_t initialize_seed(747373);
test::seed_t seed(747373);
template <class T>
struct insert_test_base : public test::exception_base
+3 -1
View File
@@ -3,6 +3,8 @@
// 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"
@@ -11,7 +13,7 @@
#include <iostream>
test::seed_t initialize_seed(3298597);
test::seed_t seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
+3 -1
View File
@@ -3,6 +3,8 @@
// 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"
@@ -11,7 +13,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t initialize_seed(9387);
test::seed_t seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
+1 -1
View File
@@ -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 occurred before, required
// First test that the current key has not occured 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);
+3 -3
View File
@@ -219,14 +219,14 @@ namespace test
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator i, const_iterator j) {
void erase(const_iterator start, const_iterator end) {
node** ptr = &data_.first_;
while(*ptr != i.ptr_) {
while(*ptr != start.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != j.ptr_) {
while(*ptr != end.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
-10
View File
@@ -1,10 +0,0 @@
// 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
+6 -6
View File
@@ -124,8 +124,8 @@ namespace test
: base()
{}
explicit ordered(key_compare const& kc)
: base(kc)
explicit ordered(key_compare const& compare)
: base(compare)
{}
void compare(X const& x)
@@ -143,10 +143,10 @@ namespace test
}
template <class It>
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
void insert_range(It begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
}
}
};
+2 -2
View File
@@ -168,10 +168,10 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<typename... Args> void construct(T* p, Args&&... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(boost::forward<Args>(args)...);
new(p) T(std::forward<Args>(args)...);
}
#endif
+2 -2
View File
@@ -357,11 +357,11 @@ namespace exception
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_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(boost::forward<Args>(args)...);
new(p) T(std::forward<Args>(args)...);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
+5 -5
View File
@@ -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 const_void_pointer;
typedef void_const_ptr void_const_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_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
new((void*)p) T(boost::forward<Args>(args)...);
new((void*)p) T(std::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_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
new((void*)p) T(boost::forward<Args>(args)...);
new((void*)p) T(std::forward<Args>(args)...);
}
#endif
+2 -2
View File
@@ -259,10 +259,10 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(boost::forward<Args>(args)...);
new(p) T(std::forward<Args>(args)...);
}
#endif
+4 -22
View File
@@ -9,15 +9,13 @@ project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
# 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:<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"
#<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
@@ -52,20 +50,4 @@ 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 ]
;
-24
View File
@@ -90,12 +90,7 @@ 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*>));
@@ -128,12 +123,7 @@ 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*>));
@@ -196,20 +186,6 @@ 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
{
+5 -3
View File
@@ -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 initialize_seed(96785);
test::seed_t seed(96785);
template <class T>
void assign_tests1(T*,
@@ -208,7 +208,9 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
+1 -2
View File
@@ -4,9 +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_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include <string>
+2 -3
View File
@@ -4,10 +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 <algorithm>
#include "../objects/test.hpp"
@@ -21,7 +20,7 @@
namespace bucket_tests {
test::seed_t initialize_seed(54635);
test::seed_t seed(54635);
template <class X>
void tests(X* = 0, test::random_generator generator = test::default_generator)
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
-1
View File
@@ -22,7 +22,6 @@
#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 -4
View File
@@ -4,10 +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 "../helpers/random_values.hpp"
@@ -18,7 +17,7 @@
namespace constructor_tests {
test::seed_t initialize_seed(356730);
test::seed_t seed(356730);
template <class T>
void constructor_tests1(T*,
@@ -443,7 +442,8 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
+2 -3
View File
@@ -4,10 +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"
@@ -16,7 +15,7 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
test::seed_t initialize_seed(9063);
test::seed_t seed(9063);
namespace copy_tests
{
+1 -2
View File
@@ -6,10 +6,9 @@
#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"
+2 -10
View File
@@ -4,10 +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 <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
@@ -150,14 +149,6 @@ 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.
@@ -176,6 +167,7 @@ namespace equality_tests
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+1 -2
View File
@@ -4,10 +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 <algorithm>
#include <map>
+1 -2
View File
@@ -7,9 +7,8 @@
// 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 <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include <set>
+2 -3
View File
@@ -4,10 +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 <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -21,7 +20,7 @@
namespace erase_tests
{
test::seed_t initialize_seed(85638);
test::seed_t seed(85638);
template <class Container>
void erase_tests1(Container*,
+2 -3
View File
@@ -4,10 +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 "../helpers/random_values.hpp"
@@ -17,7 +16,7 @@
namespace find_tests
{
test::seed_t initialize_seed(78937);
test::seed_t seed(78937);
template <class X>
void find_tests1(X*, test::random_generator generator = test::default_generator)
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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; };
+2 -3
View File
@@ -4,11 +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_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <utility>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
namespace x
{
+1 -2
View File
@@ -4,10 +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 <iostream>
+4 -4
View File
@@ -4,10 +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 <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -21,7 +20,7 @@
namespace insert_tests {
test::seed_t initialize_seed(243432);
test::seed_t seed(243432);
template <class X>
void unique_insert_tests1(X*,
@@ -466,7 +465,8 @@ UNORDERED_TEST(map_insert_range_test2,
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
+1 -1
View File
@@ -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>&,
+1 -1
View File
@@ -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,
+2 -3
View File
@@ -4,10 +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 <boost/limits.hpp>
#include "../helpers/random_values.hpp"
@@ -20,7 +19,7 @@
namespace load_factor_tests
{
test::seed_t initialize_seed(783656);
test::seed_t seed(783656);
template <class X>
void set_load_factor_tests(X* = 0)
-6
View File
@@ -51,13 +51,7 @@ 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);
+10 -34
View File
@@ -4,10 +4,9 @@
// 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"
@@ -22,12 +21,7 @@
namespace move_tests
{
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
test::seed_t seed(98624);
template<class T>
T empty(T*) {
@@ -101,7 +95,7 @@ namespace move_tests
test::object_count count;
T y;
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
@@ -201,10 +195,7 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -219,9 +210,7 @@ namespace move_tests
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
#endif
@@ -230,10 +219,7 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -254,19 +240,14 @@ namespace move_tests
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
if (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 (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -291,9 +272,7 @@ namespace move_tests
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(count1.instances ==
test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
@@ -304,10 +283,7 @@ namespace move_tests
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
if (allocator_type::is_propagate_on_move) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
+2 -78
View File
@@ -4,10 +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 "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
@@ -15,7 +14,7 @@
namespace rehash_tests
{
test::seed_t initialize_seed(2974);
test::seed_t seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
@@ -100,75 +99,6 @@ 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;
@@ -186,12 +116,6 @@ 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))
)
}
+1 -2
View File
@@ -6,10 +6,9 @@
// 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>
+3 -4
View File
@@ -4,13 +4,12 @@
// 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"
@@ -25,7 +24,7 @@
namespace swap_tests
{
test::seed_t initialize_seed(783472);
test::seed_t seed(783472);
template <class X>
void swap_test_impl(X& x1, X& x2)
+5 -22
View File
@@ -1,33 +1,14 @@
#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
@@ -262,7 +243,9 @@ namespace unnecessary_copy_tests
// the existing element.
reset();
x.emplace();
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
COPY_COUNT(1); MOVE_COUNT(0);
#elif !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