Compare commits

..

14 Commits

Author SHA1 Message Date
Marshall Clow a4076e1297 Release 1.51.0
[SVN r80098]
2012-08-20 22:07:05 +00:00
Daniel James 8683332b2c Unordered: Merge from trunk
- Avoid an incorrect MSVC unused variable warning in the tests.
- Remove a `try..catch`.
- Adjust SFINAE use to try to supprt g++ 3.4. Fixes #7175.
- Fix some use of rvalues.
- Extra info in `at_tests`.



[SVN r79868]
2012-08-05 08:34:44 +00:00
Daniel James d77453b7ad Unordered: Merge allocator fix + improved tests. Fixes #7100.
[SVN r79547]
2012-07-15 23:58:02 +00:00
Daniel James cf9930fe20 Unordered: Merge updated c++11 config macros.
[SVN r79546]
2012-07-15 23:47:12 +00:00
Daniel James e30a99d2fc Unordered: Merge some of the older changes from trunk.
Code reorganization, simpler tests, better use of Boost.Move.


[SVN r79545]
2012-07-15 23:44:41 +00:00
Daniel James c788780792 Unordered: Merge msvc 11 fix from trunk.
[SVN r78853]
2012-06-07 19:47:01 +00:00
Daniel James e1416d0a3e Unordered: Fix bcp namespace fix. Fixes #6905.
[SVN r78534]
2012-05-21 22:08:19 +00:00
Daniel James 808f1f939f Unordered: Merge unordered from trunk.
- Activate `std::allocator_traits` for gcc 4.7 and Visual C++ 11.
- Implement variadic construct in `boost::unordered::detail::allocator_traits`
  when variadics, rvalue references and SFINAE expression are available.
- Use variadic construct from `allocator_traits`, or when not available move
  the logic for constructing `value_type` to a lower level, so the container
  code is a bit simpler.
- Avoid `-Wshadow` warnings. Fixes #6190.
- Implement `reserve`. Fixes #6857.


[SVN r78432]
2012-05-12 08:14:05 +00:00
Daniel James 880d778ab6 Unordered: Missing revision from last merge.
[SVN r78320]
2012-05-03 22:29:25 +00:00
Daniel James a8cd8cdd0b Unordered/Hash: Merge from trunk.
[SVN r78319]
2012-05-03 22:05:21 +00:00
Daniel James fa3d93ddbc Unordered: Merge to release. Fixes #6522.
Fixes undefined macros, removes some unused code and fix some potential issues
for when `std::allocator_traits` is used.


[SVN r76943]
2012-02-07 20:48:50 +00:00
Daniel James 5622afdafa Iostreams: Merge spelling fix.
[SVN r76787]
2012-01-29 22:54:03 +00:00
Daniel James 63d56953af Unordered: Merge move changes. Fixes #6311.
[SVN r76531]
2012-01-15 20:22:15 +00:00
Daniel James 280b1971b6 Unordered: merge from trunk.
[SVN r75908]
2011-12-11 21:39:18 +00:00
70 changed files with 3609 additions and 2425 deletions
+29
View File
@@ -170,4 +170,33 @@ C++11 support has resulted in some breaking changes:
the variadic consturctors define
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
[h2 Boost 1.49.0]
* Fix warning due to accidental odd assignment.
* Slightly better error messages.
[h2 Boost 1.50.0]
* Fix equality for `unordered_multiset` and `unordered_multimap`.
* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
Implement `reserve`.
* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
Fix some Sun specific code.
* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
Avoid gcc's `-Wshadow` warning.
* [@https://svn.boost.org/trac/boost/ticket/6905 Ticket 6905]:
Make namespaces in macros compatible with `bcp` custom namespaces.
Fixed by Luke Elliott.
* Remove some of the smaller prime number of buckets, as they may make
collisions quite probable (e.g. multiples of 5 are very common because
we used base 10).
* On old versions of Visual C++, use the container library's implementation
of `allocator_traits`, as it's more likely to work.
* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas
Wang's hash function to pick which one to use. As modulus is very slow
for 64 bit values.
* Some internal changes.
[endsect]
+12
View File
@@ -963,6 +963,18 @@ EOL;
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
+48
View File
@@ -846,6 +846,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -1797,6 +1809,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -2793,6 +2817,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -3758,6 +3794,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
File diff suppressed because it is too large Load Diff
@@ -1,518 +0,0 @@
// Copyright 2005-2011 Daniel James.
// Copyright 2009 Pablo Halpern.
//
// 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)
//
// Allocator traits written by Daniel James based on Pablo Halpern's
// implementation.
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/enum.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
# include <memory>
#endif
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
# include <type_traits>
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// Integral_constrant, true_type, false_type
//
// Uses the standard versions if available.
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
using std::integral_constant;
using std::true_type;
using std::false_type;
#else
template <typename T, T Value>
struct integral_constant { enum { value = Value }; };
typedef boost::unordered::detail::integral_constant<bool, true> true_type;
typedef boost::unordered::detail::integral_constant<bool, false> false_type;
#endif
////////////////////////////////////////////////////////////////////////////
// Explicitly call a destructor
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
template <class T>
inline void destroy(T* x) {
x->~T();
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
////////////////////////////////////////////////////////////////////////////
// Bits and pieces for implementing traits
//
// Some of these are also used elsewhere
template <typename T> typename boost::add_lvalue_reference<T>::type make();
struct choice9 { typedef char (&type)[9]; };
struct choice8 : choice9 { typedef char (&type)[8]; };
struct choice7 : choice8 { typedef char (&type)[7]; };
struct choice6 : choice7 { typedef char (&type)[6]; };
struct choice5 : choice6 { typedef char (&type)[5]; };
struct choice4 : choice5 { typedef char (&type)[4]; };
struct choice3 : choice4 { typedef char (&type)[3]; };
struct choice2 : choice3 { typedef char (&type)[2]; };
struct choice1 : choice2 { typedef char (&type)[1]; };
choice1 choose();
typedef choice1::type yes_type;
typedef choice2::type no_type;
struct private_type
{
private_type const &operator,(int) const;
};
template <typename T>
no_type is_private_type(T const&);
yes_type is_private_type(private_type const&);
struct convert_from_anything {
template <typename T>
convert_from_anything(T const&);
};
#if !defined(BOOST_NO_SFINAE_EXPR)
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
template <typename T, unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {};
template <typename U> static char for_expr_test(U const&);
#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template <typename U> \
static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \
sizeof(boost::unordered::detail::for_expr_test(( \
(expression), \
0)))>::type test( \
BOOST_PP_CAT(choice, count))
#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, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
\
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
}
#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) \
\
typedef typename boost::unordered::detail::identity<member>::type \
BOOST_PP_CAT(check, count); \
\
template <BOOST_PP_CAT(check, count) e> \
struct BOOST_PP_CAT(test, count) { \
typedef BOOST_PP_CAT(choice, result) type; \
}; \
\
template <class U> static typename \
BOOST_PP_CAT(test, count)<&U::name>::type \
test(BOOST_PP_CAT(choice, count))
#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) \
struct BOOST_PP_CAT(has_, name) \
{ \
struct impl { \
struct base_mixin { int name; }; \
struct base : public T, public base_mixin {}; \
\
BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
\
enum { value = sizeof(choice2::type) == \
sizeof(test<base>(choose())) \
}; \
}; \
\
enum { value = impl::value }; \
}
#endif
////////////////////////////////////////////////////////////////////////////
// Allocator traits
//
// Uses the standard versions if available.
// (although untested as I don't have access to a standard version yet)
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
template <typename Alloc>
struct allocator_traits : std::allocator_traits<Alloc> {};
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename std::allocator_traits<Alloc>::rebind_alloc<T> type;
};
#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;
};
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
#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 choice2::type test(choice2, void* = 0); \
\
struct DefaultWrap { typedef Default tname; }; \
\
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\
typedef typename boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#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 { \
\
template <typename X> \
static typename boost::unordered::detail::sfinae< \
typename X::tname, choice1>::type \
test(choice1); \
\
template <typename X> \
static choice2::type test(choice2); \
\
struct DefaultWrap { typedef Default tname; }; \
\
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\
typedef typename boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#endif
#define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
typename default_type_ ## tname<T, arg>::type
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
#if BOOST_UNORDERED_HAVE_CALL_DETECTION
template <typename T>
BOOST_UNORDERED_HAS_FUNCTION(
select_on_container_copy_construction, U const, (), 0
);
template <typename T>
BOOST_UNORDERED_HAS_FUNCTION(
max_size, U const, (), 0
);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_FUNCTION(
construct, U, (
boost::unordered::detail::make<ValueType*>(),
boost::unordered::detail::make<ValueType const>()), 2
);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_FUNCTION(
destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
);
#else
template <typename T>
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
template <typename T>
BOOST_UNORDERED_HAS_MEMBER(max_size);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_MEMBER(construct);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_MEMBER(destroy);
#endif
template <typename Alloc>
inline typename boost::enable_if_c<
boost::unordered::detail::
has_select_on_container_copy_construction<Alloc>::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs.select_on_container_copy_construction();
}
template <typename Alloc>
inline typename boost::disable_if_c<
boost::unordered::detail::
has_select_on_container_copy_construction<Alloc>::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs;
}
template <typename SizeType, typename Alloc>
inline typename boost::enable_if_c<
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
>::type call_max_size(const Alloc& a)
{
return a.max_size();
}
template <typename SizeType, typename Alloc>
inline typename boost::disable_if_c<
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
>::type call_max_size(const Alloc&)
{
return (std::numeric_limits<SizeType>::max)();
}
template <typename Alloc>
struct allocator_traits
{
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
pointer;
template <typename T>
struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
typename pointer_to_other<const value_type>::type)
const_pointer;
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
// typename pointer_to_other<void>::type)
// void_pointer;
//
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
// typename pointer_to_other<const void>::type)
// const_void_pointer;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
std::ptrdiff_t) difference_type;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
// TODO: rebind_alloc and rebind_traits
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.
//
//static pointer allocate(Alloc& a, size_type n,
// const_void_pointer hint)
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
static void deallocate(Alloc& a, pointer p, size_type n)
{ a.deallocate(p, n); }
public:
// Only supporting the basic copy constructor for now.
template <typename T>
static typename boost::enable_if_c<
boost::unordered::detail::has_construct<Alloc, T>::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>::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>::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);
}
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(
Alloc, propagate_on_container_copy_assignment, false_type)
propagate_on_container_copy_assignment;
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_move_assignment, false_type)
propagate_on_container_move_assignment;
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
#undef BOOST_UNORDERED_DEFAULT_TYPE
#endif
// array_constructor
//
// Allocate and construct an array in an exception safe manner, and
// clean up if an exception is thrown before the container takes charge
// of it.
template <typename Allocator>
struct array_constructor
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
typedef typename traits::pointer pointer;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
constructed_ = pointer();
ptr_ = pointer();
}
~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
traits::destroy(alloc_, boost::addressof(*p));
traits::deallocate(alloc_, ptr_, length_);
}
}
template <typename V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
traits::construct(alloc_, boost::addressof(*constructed_), v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
return p;
}
private:
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
};
}}}
#endif
+451 -68
View File
@@ -12,12 +12,13 @@
#endif
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/emplace_args.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -29,7 +30,10 @@ namespace boost { namespace unordered { namespace detail {
template <typename Types> struct table;
template <typename NodePointer> struct bucket;
struct ptr_bucket;
template <typename A, typename Bucket, typename Node> struct buckets;
template <typename A, typename Bucket, typename Node, typename Policy>
struct buckets;
template <typename Types> struct table_impl;
template <typename Types> struct grouped_table_impl;
///////////////////////////////////////////////////////////////////
//
@@ -49,16 +53,14 @@ namespace boost { namespace unordered { namespace detail {
node_allocator& alloc_;
node_pointer node_;
bool node_constructed_;
bool value_constructed_;
bool constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false),
value_constructed_(false)
constructed_(false)
{
}
@@ -69,26 +71,36 @@ namespace boost { namespace unordered { namespace detail {
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
boost::unordered::detail::construct_impl(
node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
BOOST_ASSERT(node_ && !constructed_);
boost::unordered::detail::construct_node(alloc_,
boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
node_->init(static_cast<typename node::link_pointer>(node_));
constructed_ = true;
}
template <typename A0>
void construct_value2(BOOST_FWD_REF(A0) a0)
{
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
boost::unordered::detail::construct_impl2(
node_->value_ptr(), boost::forward<A0>(a0));
value_constructed_ = true;
BOOST_ASSERT(node_ && !constructed_);
boost::unordered::detail::construct_node(alloc_,
boost::addressof(*node_),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
constructed_ = true;
node_->init(static_cast<typename node::link_pointer>(node_));
}
value_type const& value() const {
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
BOOST_ASSERT(node_ && constructed_);
return node_->value();
}
node_pointer get()
{
return node_;
}
// no throw
node_pointer release()
{
@@ -106,12 +118,8 @@ namespace boost { namespace unordered { namespace detail {
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (value_constructed_) {
boost::unordered::detail::destroy(node_->value_ptr());
}
if (node_constructed_) {
node_allocator_traits::destroy(alloc_,
if (constructed_) {
boost::unordered::detail::destroy_node(alloc_,
boost::addressof(*node_));
}
@@ -123,24 +131,13 @@ namespace boost { namespace unordered { namespace detail {
void node_constructor<Alloc>::construct_node()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
node_allocator_traits::construct(alloc_,
boost::addressof(*node_), node());
node_->init(static_cast<typename node::link_pointer>(node_));
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_);
if (value_constructed_)
{
boost::unordered::detail::destroy(node_->value_ptr());
value_constructed_ = false;
}
else if (constructed_) {
boost::unordered::detail::destroy_node(alloc_,
boost::addressof(*node_));
constructed_ = false;
}
}
@@ -179,12 +176,373 @@ namespace boost { namespace unordered { namespace detail {
enum { extra_node = false };
};
template <typename LinkPointer>
struct node_base
{
typedef LinkPointer link_pointer;
link_pointer next_;
node_base() : next_() {}
};
}}}
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
// Iterators
//
// all no throw
template <typename NodePointer, typename Value> struct iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value> struct c_iterator;
template <typename NodePointer, typename Value, typename Policy>
struct l_iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value, typename Policy> struct cl_iterator;
// Local Iterators
//
// all no throw
template <typename NodePointer, typename Value, typename Policy>
struct l_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename ConstNodePointer, typename NodePointer2,
typename Value2, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
l_iterator() : ptr_() {}
l_iterator(iterator x, std::size_t b, std::size_t c)
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
Value& operator*() const {
return ptr_->value();
}
Value* operator->() const {
return ptr_->value_ptr();
}
l_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
!= bucket_)
ptr_ = node_pointer();
return *this;
}
l_iterator operator++(int) {
l_iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(l_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(l_iterator x) const {
return ptr_ != x.ptr_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value,
typename Policy>
struct cl_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
<NodePointer, Value, Policy>;
private:
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
cl_iterator() : ptr_() {}
cl_iterator(iterator x, std::size_t b, std::size_t c) :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
NodePointer, Value, Policy> const& x) :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
Value const&
operator*() const {
return ptr_->value();
}
Value const* operator->() const {
return ptr_->value_ptr();
}
cl_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
!= bucket_)
ptr_ = node_pointer();
return *this;
}
cl_iterator operator++(int) {
cl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ == y.ptr_;
}
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ != y.ptr_;
}
};
template <typename NodePointer, typename Value>
struct iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename, typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
template <typename, typename, typename, typename>
friend struct boost::unordered::detail::buckets;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
typedef NodePointer node_pointer;
node_pointer node_;
public:
iterator() : node_() {}
explicit iterator(node_pointer const& x) : node_(x) {}
Value& operator*() const {
return node_->value();
}
Value* operator->() const {
return &node_->value();
}
iterator& operator++() {
node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
iterator operator++(int) {
iterator tmp(node_);
node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
bool operator==(iterator const& x) const {
return node_ == x.node_;
}
bool operator!=(iterator const& x) const {
return node_ != x.node_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value>
struct c_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::iterator<
NodePointer, Value>;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
friend struct boost::unordered::detail::table;
template <typename, typename, typename, typename>
friend struct boost::unordered::detail::buckets;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
typedef NodePointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
iterator;
node_pointer node_;
public:
c_iterator() : node_() {}
explicit c_iterator(node_pointer const& x) : node_(x) {}
c_iterator(boost::unordered::iterator_detail::iterator<
NodePointer, Value> const& x) : node_(x.node_) {}
Value const& operator*() const {
return node_->value();
}
Value const* operator->() const {
return &node_->value();
}
c_iterator& operator++() {
node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
c_iterator operator++(int) {
c_iterator tmp(node_);
node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
friend bool operator==(c_iterator const& x, c_iterator const& y) {
return x.node_ == y.node_;
}
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
return x.node_ != y.node_;
}
};
}}}
namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
//
// Hash Policy
//
// Don't really want buckets to derive from this, but will for now.
template <typename SizeT>
struct prime_policy
{
template <typename Hash, typename T>
static inline SizeT apply_hash(Hash const& hf, T const& x) {
return hf(x);
}
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
return hash % bucket_count;
}
static inline SizeT new_bucket_count(SizeT min) {
return boost::unordered::detail::next_prime(min);
}
static inline SizeT prev_bucket_count(SizeT max) {
return boost::unordered::detail::prev_prime(max);
}
};
template <typename SizeT>
struct mix64_policy
{
template <typename Hash, typename T>
static inline SizeT apply_hash(Hash const& hf, T const& x) {
SizeT key = hf(x);
key = (~key) + (key << 21); // key = (key << 21) - key - 1;
key = key ^ (key >> 24);
key = (key + (key << 3)) + (key << 8); // key * 265
key = key ^ (key >> 14);
key = (key + (key << 2)) + (key << 4); // key * 21
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}
static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
return hash & (bucket_count - 1);
}
static inline SizeT new_bucket_count(SizeT min) {
if (min <= 4) return 4;
--min;
min |= min >> 1;
min |= min >> 2;
min |= min >> 4;
min |= min >> 8;
min |= min >> 16;
min |= min >> 32;
return min + 1;
}
static inline SizeT prev_bucket_count(SizeT max) {
max |= max >> 1;
max |= max >> 2;
max |= max >> 4;
max |= max >> 8;
max |= max >> 16;
max |= max >> 32;
return (max >> 1) + 1;
}
};
template <int digits, int radix>
struct pick_policy_impl {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy_impl<64, 2> {
typedef mix64_policy<std::size_t> type;
};
struct pick_policy :
pick_policy_impl<
std::numeric_limits<std::size_t>::digits,
std::numeric_limits<std::size_t>::radix> {};
///////////////////////////////////////////////////////////////////
//
// Buckets
template <typename A, typename Bucket, typename Node>
struct buckets
template <typename A, typename Bucket, typename Node, typename Policy>
struct buckets : Policy
{
private:
buckets(buckets const&);
@@ -193,6 +551,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef Policy policy;
typedef Node node;
typedef Bucket bucket;
typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
@@ -214,6 +573,16 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::node_constructor<node_allocator>
node_constructor;
typedef boost::unordered::iterator_detail::
iterator<node_pointer, value_type> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node_pointer, value_type, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<const_node_pointer, node_pointer, value_type, policy>
cl_iterator;
// Members
bucket_pointer buckets_;
@@ -247,7 +616,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_bucket_count() const
{
// -1 to account for the start bucket.
return boost::unordered::detail::prev_prime(
return policy::prev_bucket_count(
bucket_allocator_traits::max_size(bucket_alloc()) - 1);
}
@@ -266,16 +635,17 @@ namespace boost { namespace unordered { namespace detail {
return this->get_bucket(bucket_index)->next_;
}
node_pointer get_start() const
iterator get_start() const
{
return static_cast<node_pointer>(this->get_previous_start()->next_);
return iterator(static_cast<node_pointer>(
this->get_previous_start()->next_));
}
node_pointer get_start(std::size_t bucket_index) const
iterator get_start(std::size_t bucket_index) const
{
previous_pointer prev = this->get_previous_start(bucket_index);
return prev ? static_cast<node_pointer>(prev->next_) :
node_pointer();
return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
iterator();
}
float load_factor() const
@@ -288,14 +658,15 @@ namespace boost { namespace unordered { namespace detail {
std::size_t bucket_size(std::size_t index) const
{
if (!this->size_) return 0;
node_pointer ptr = this->get_start(index);
if (!ptr) return 0;
iterator it = this->get_start(index);
if (!it.node_) return 0;
std::size_t count = 0;
while(ptr && ptr->hash_ % this->bucket_count_ == index)
while(it.node_ && policy::to_bucket(
this->bucket_count_, it.node_->hash_) == index)
{
++count;
ptr = static_cast<node_pointer>(ptr->next_);
++it;
}
return count;
@@ -349,6 +720,14 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
a.construct_node();
// Since this node is just to mark the beginning it doesn't
// contain a value, so just construct node::node_base
// which containers the pointer to the next element.
node_allocator_traits::construct(node_alloc(),
static_cast<typename node::node_base*>(
boost::addressof(*a.get())),
typename node::node_base());
(constructor.get() +
static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
a.release();
@@ -391,21 +770,21 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////
// Delete/destruct
inline void delete_node(node_pointer n)
inline void delete_node(c_iterator n)
{
boost::unordered::detail::destroy(n->value_ptr());
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
boost::unordered::detail::destroy_node(
node_alloc(), boost::addressof(*n.node_));
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
--size_;
}
std::size_t delete_nodes(node_pointer begin, node_pointer end)
std::size_t delete_nodes(c_iterator begin, c_iterator end)
{
std::size_t count = 0;
while(begin != end) {
node_pointer n = begin;
begin = static_cast<node_pointer>(begin->next_);
c_iterator n = begin;
++begin;
delete_node(n);
++count;
}
@@ -416,7 +795,8 @@ namespace boost { namespace unordered { namespace detail {
inline void delete_extra_node(bucket_pointer) {}
inline void delete_extra_node(node_pointer n) {
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
node_allocator_traits::destroy(node_alloc(),
static_cast<typename node::node_base*>(boost::addressof(*n)));
node_allocator_traits::deallocate(node_alloc(), n, 1);
}
@@ -433,7 +813,7 @@ namespace boost { namespace unordered { namespace detail {
while(prev->next_) {
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
delete_node(n);
delete_node(iterator(n));
}
delete_extra_node(prev);
@@ -463,7 +843,7 @@ namespace boost { namespace unordered { namespace detail {
while(prev->next_) {
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
delete_node(n);
delete_node(iterator(n));
}
bucket_pointer end = this->get_bucket(this->bucket_count_);
@@ -477,22 +857,24 @@ namespace boost { namespace unordered { namespace detail {
// This is called after erasing a node or group of nodes to fix up
// the bucket pointers.
void fix_buckets(bucket_pointer bucket,
void fix_buckets(bucket_pointer this_bucket,
previous_pointer prev, node_pointer next)
{
if (!next)
{
if (bucket->next_ == prev) bucket->next_ = node_pointer();
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
}
else
{
bucket_pointer next_bucket = this->get_bucket(
next->hash_ % this->bucket_count_);
policy::to_bucket(this->bucket_count_, next->hash_));
if (next_bucket != bucket)
if (next_bucket != this_bucket)
{
next_bucket->next_ = prev;
if (bucket->next_ == prev) bucket->next_ = node_pointer();
if (this_bucket->next_ == prev)
this_bucket->next_ = node_pointer();
}
}
}
@@ -513,7 +895,7 @@ namespace boost { namespace unordered { namespace detail {
if (n == end) return;
std::size_t new_bucket_index =
n->hash_ % this->bucket_count_;
policy::to_bucket(this->bucket_count_, n->hash_);
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
break;
@@ -529,7 +911,7 @@ namespace boost { namespace unordered { namespace detail {
if (n == end) break;
std::size_t new_bucket_index =
n->hash_ % this->bucket_count_;
policy::to_bucket(this->bucket_count_, n->hash_);
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
this->get_bucket(bucket_index)->next_ = previous_pointer();
@@ -538,7 +920,8 @@ namespace boost { namespace unordered { namespace detail {
// Finally fix the bucket containing the trailing node.
if (n) {
this->get_bucket(n->hash_ % this->bucket_count_)->next_
this->get_bucket(
policy::to_bucket(this->bucket_count_, n->hash_))->next_
= prev;
}
}
@@ -1,423 +0,0 @@
// Copyright (C) 2011 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/unordered for documentation
#ifndef BOOST_UNORDERED_EMPLACE_ARGS_HPP
#define BOOST_UNORDERED_EMPLACE_ARGS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#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/tuple/tuple.hpp>
#include <utility>
#if !defined(BOOST_NO_0X_HDR_TUPLE)
#include <tuple>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4512) // assignment operator could not be generated.
#pragma warning(disable:4345) // behavior change: an object of POD type
// constructed with an initializer of the form ()
// will be default-initialized.
#endif
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
!defined(BOOST_NO_VARIADIC_TEMPLATES)
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
# elif defined(_LIBCPP_VERSION)
# define BOOST_UNORDERED_STD_FORWARD_MOVE
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
# define BOOST_UNORDERED_STD_FORWARD_MOVE
# endif
# elif defined(__STL_CONFIG_H)
# elif defined(__MSL_CPP__)
# elif defined(__IBMCPP__)
# elif defined(MSIPL_COMPILE_H)
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
# endif
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
// Either forwarding variadic arguments, or storing the arguments in
// emplace_args##n
#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 std::forward<Args>(args)...
#else
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
#define BOOST_UNORDERED_EMPLACE_FORWARD args
#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
#define BOOST_UNORDERED_EARGS(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
struct BOOST_PP_CAT(emplace_args, n) \
{ \
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
BOOST_PP_CAT(emplace_args, n) ( \
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, a) \
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
{} \
\
}; \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
inline BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> 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);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, 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);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
#endif
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
_)
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
#undef BOOST_UNORDERED_EARGS_MEMBER
#undef BOOST_UNORDERED_EARGS_INIT
#endif
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
#if !defined(BOOST_NO_RVALUE_REFERENCES)
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
#else
struct please_ignore_this_overload {
typedef please_ignore_this_overload type;
};
template <typename T>
struct rv_ref_impl {
typedef BOOST_RV_REF(T) type;
};
template <typename T>
struct rv_ref :
boost::detail::if_true<
boost::is_class<T>::value
>::BOOST_NESTED_TEMPLATE then <
boost::unordered::detail::rv_ref_impl<T>,
please_ignore_this_overload
>::type
{};
# define BOOST_UNORDERED_RV_REF(T) \
typename boost::unordered::detail::rv_ref<T>::type
#endif
////////////////////////////////////////////////////////////////////////////
// Construct from tuple
//
// Used for piecewise construction.
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
template<typename T> \
void construct_from_tuple(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(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)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
#endif
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
#undef BOOST_UNORDERED_GET_TUPLE_ARG
////////////////////////////////////////////////////////////////////////////
// SFINAE traits for construction.
// Decide which construction method to use for a three argument
// call. Note that this is difficult to do using overloads because
// the arguments are packed into 'emplace_args3'.
//
// The decision is made on the first argument.
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct emulation1 {
static choice1::type test(choice1, std::pair<A, B> const&);
static choice2::type test(choice2, A const&);
static choice3::type test(choice3, convert_from_anything const&);
enum { value =
sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
sizeof(choice2::type) };
};
#endif
template <typename A, typename B, typename A0>
struct check3_base {
static choice1::type test(choice1,
boost::unordered::piecewise_construct_t);
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
static choice2::type test(choice2, A const&);
#endif
static choice3::type test(choice3, ...);
enum { value =
sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
};
template <typename A, typename B, typename A0>
struct piecewise3 {
enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
};
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct emulation3 {
enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
};
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
////////////////////////////////////////////////////////////////////////////
// Construct from variadic parameters
template <typename T, typename... Args>
inline void construct_impl(T* address, Args&&... args)
{
new((void*) address) T(std::forward<Args>(args)...);
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<piecewise3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&&, A1&& a1, A2&& a2)
{
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->first), a1);
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->second), a2);
}
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
inline typename enable_if<emulation1<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&& a0)
{
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B();
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<emulation3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&& a0, A1&& a1, A2&& a2)
{
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
std::forward<A1>(a1),
std::forward<A2>(a2));
}
template <typename A, typename B,
typename A0, typename A1, typename A2, typename A3,
typename... Args>
inline void construct_impl(std::pair<A, B>* address,
A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args)
{
new((void*) boost::addressof(address->first)) A(std::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
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_STD_FORWARD_MOVE
////////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_impl(T* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new((void*) address) T( \
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
args.a)); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<piecewise3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->first), args.a1);
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->second), args.a2);
}
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
inline typename enable_if<emulation1<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args1<A0> const& args)
{
new((void*) boost::addressof(address->first)) A(
boost::forward<A0>(args.a0));
new((void*) boost::addressof(address->second)) B();
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<emulation3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
new((void*) boost::addressof(address->first)) A(
boost::forward<A0>(args.a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(args.a1),
boost::forward<A2>(args.a2));
}
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
template <typename A, typename B, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_impl(std::pair<A, B>* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new((void*) boost::addressof(address->first)) A( \
boost::forward<A0>(args.a0)); \
new((void*) boost::addressof(address->second)) B( \
BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params), \
BOOST_UNORDERED_CALL_FORWARD2, args.a)); \
}
#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
#undef BOOST_UNORDERED_CALL_FORWARD2
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
#endif // BOOST_UNORDERED_STD_FORWARD_MOVE
////////////////////////////////////////////////////////////////////////////
// Construct without using the emplace args mechanism.
template <typename T, typename A0>
inline void construct_impl2(T* address, BOOST_FWD_REF(A0) a0)
{
new((void*) address) T(
boost::forward<A0>(a0)
);
}
}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
+216 -142
View File
@@ -12,7 +12,6 @@
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/emplace_args.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -23,25 +22,52 @@ 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>
explicit 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());
}
grouped_node(grouped_node const&) {
assert(false);
}
#else
grouped_node() :
next_(),
node_base(),
group_prev_(),
hash_(0)
{}
#endif
void init(link_pointer self)
{
group_prev_ = self;
}
private:
grouped_node& operator=(grouped_node const&);
};
template <typename T>
@@ -50,21 +76,45 @@ 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>
explicit 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());
}
grouped_ptr_node(grouped_ptr_node const&) {
assert(false);
}
#else
grouped_ptr_node() :
bucket_base(),
group_prev_(0),
hash_(0)
{}
#endif
void init(link_pointer self)
{
group_prev_ = self;
}
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
// If the allocator uses raw pointers use grouped_ptr_node
@@ -115,42 +165,46 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename H, typename P>
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, H, P> types;
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef value_type key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename H, typename P>
template <typename A, typename K, typename M, typename H, typename P>
struct multimap
{
typedef boost::unordered::detail::multimap<A, K, H, P> types;
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -158,6 +212,8 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
@@ -167,6 +223,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::buckets buckets;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
@@ -179,6 +236,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
// Constructors
@@ -212,59 +270,61 @@ namespace boost { namespace unordered { namespace detail {
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
std::size_t hash,
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
if (hash == node_hash)
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
}
n = static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
n = iterator(static_cast<node_pointer>(
static_cast<node_pointer>(n.node_->group_prev_)->next_));
}
}
std::size_t count(key_type const& k) const
{
node_pointer n = this->find_node(k);
if (!n) return 0;
iterator n = this->find_node(k);
if (!n.node_) return 0;
std::size_t count = 0;
node_pointer it = n;
std::size_t x = 0;
node_pointer it = n.node_;
do {
it = static_cast<node_pointer>(it->group_prev_);
++count;
} while(it != n);
++x;
} while(it != n.node_);
return count;
return x;
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
iterator n = this->find_node(k);
return std::make_pair(
iterator(n), iterator(n ?
n, n.node_ ? iterator(
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_) :
n));
static_cast<node_pointer>(n.node_->group_prev_)->next_
)) : n);
}
// Equality
@@ -274,14 +334,14 @@ namespace boost { namespace unordered { namespace detail {
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(node_pointer n1 = this->get_start(); n1;)
for(iterator n1 = this->get_start(); n1.node_;)
{
node_pointer n2 = other.find_matching_node(n1);
if (!n2) return false;
node_pointer end1 = static_cast<node_pointer>(
static_cast<node_pointer>(n1->group_prev_)->next_);
node_pointer end2 = static_cast<node_pointer>(
static_cast<node_pointer>(n2->group_prev_)->next_);
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(static_cast<node_pointer>(
static_cast<node_pointer>(n1.node_->group_prev_)->next_));
iterator end2(static_cast<node_pointer>(
static_cast<node_pointer>(n2.node_->group_prev_)->next_));
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -291,25 +351,24 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if (n1->value() != n2->value())
break;
if (*n1 != *n2) break;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(node_pointer n1a = n1, n2a = n2;;)
for(iterator n1a = n1, n2a = n2;;)
{
n1a = static_cast<node_pointer>(n1a->next_);
n2a = static_cast<node_pointer>(n2a->next_);
++n1a;
++n2a;
if (n1a == end1)
{
@@ -320,50 +379,50 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
node_pointer start = n1;
for(;n1 != end2; n1 = static_cast<node_pointer>(n1->next_))
iterator start = n1;
for(;n1 != end1; ++n1)
{
value_type const& v = n1->value();
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches || matches != 1 + count_equal(
static_cast<node_pointer>(n1->next_), end1, v))
return false;
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
}
return true;
}
static bool find(node_pointer n, node_pointer end, value_type const& v)
static bool find(iterator n, iterator end, value_type const& v)
{
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v)
for(;n != end; ++n)
if (*n == v)
return true;
return false;
}
static std::size_t count_equal(node_pointer n, node_pointer end,
static std::size_t count_equal(iterator n, iterator end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v) ++count;
for(;n != end; ++n)
if (*n == v) ++count;
return count;
}
#else
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if(!extractor::compare_mapped(
n1->value(), n2->value()))
if(!extractor::compare_mapped(*n1, *n2))
return false;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
@@ -385,35 +444,37 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = static_cast<link_pointer>(n);
}
inline node_pointer add_node(
inline iterator add_node(
node_constructor& a,
std::size_t hash,
node_pointer pos)
std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
n->hash_ = hash;
if(pos) {
this->add_after_node(n, pos);
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
std::size_t next_bucket =
static_cast<node_pointer>(n->next_)->hash_ %
this->bucket_count_;
if (next_bucket != hash % this->bucket_count_) {
std::size_t next_bucket = policy::to_bucket(
this->bucket_count_,
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket !=
policy::to_bucket(this->bucket_count_, key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
bucket_pointer b = this->get_bucket(
policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(
this->get_bucket(policy::to_bucket(this->bucket_count_,
static_cast<node_pointer>(start_node->next_)->hash_
% this->bucket_count_)->next_ = n;
))->next_ = n;
}
b->next_ = start_node;
@@ -427,46 +488,54 @@ namespace boost { namespace unordered { namespace detail {
}
}
++this->size_;
return n;
return iterator(n);
}
node_pointer emplace_impl(node_constructor& a)
iterator emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
node_pointer position = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a, hash, position);
return this->add_node(a, key_hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
this->add_node(a, hash,
this->find_node(hash, k));
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
node_pointer emplace(boost::unordered::detail::emplace_args1<
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return this->begin();
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
node_pointer emplace(BOOST_UNORDERED_EMPLACE_ARGS)
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl(a);
return iterator(emplace_impl(a));
}
////////////////////////////////////////////////////////////////////////
@@ -521,11 +590,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_;
bucket_pointer bucket = this->get_bucket(bucket_index);
std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
bucket_pointer this_bucket = this->get_bucket(bucket_index);
previous_pointer prev = bucket->next_;
previous_pointer prev = this_bucket->next_;
if (!prev) return 0;
for (;;)
@@ -533,9 +603,10 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (node_hash % this->bucket_count_ != bucket_index)
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return 0;
if (node_hash == hash &&
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
@@ -548,37 +619,39 @@ namespace boost { namespace unordered { namespace detail {
static_cast<node_pointer>(pos->group_prev_)->next_;
node_pointer end = static_cast<node_pointer>(end1);
prev->next_ = end1;
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
this->fix_buckets(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
}
node_pointer erase(node_pointer r)
iterator erase(c_iterator r)
{
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
previous_pointer prev = unlink_node(*this_bucket, r.node_);
this->fix_buckets(bucket, prev, next);
this->fix_buckets(this_bucket, prev, next.node_);
this->delete_node(r);
return next;
}
node_pointer erase_range(node_pointer r1, node_pointer r2)
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return r2;
if (r1 == r2) return iterator(r2.node_);
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
*this->get_bucket(bucket_index), r1.node_, r2.node_);
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
this->delete_nodes(r1, r2);
return r2;
return iterator(r2.node_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
@@ -695,31 +768,31 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
iterator n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
static_cast<node_pointer>(n.node_->group_prev_)->next_
));
a.construct_node();
a.construct_value2(n->value());
a.construct_value2(*n);
node_pointer first_node = a.release();
node_pointer end = first_node;
first_node->hash_ = hash;
first_node->hash_ = key_hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
for (++n; n != group_end; ++n)
{
a.construct_node();
a.construct_value2(n->value());
a.construct_value2(*n);
end = a.release();
end->hash_ = hash;
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -742,31 +815,31 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
iterator n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
static_cast<node_pointer>(n.node_->group_prev_)->next_
));
a.construct_node();
a.construct_value2(boost::move(n->value()));
a.construct_value2(boost::move(*n));
node_pointer first_node = a.release();
node_pointer end = first_node;
first_node->hash_ = hash;
first_node->hash_ = key_hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
for(++n; n != group_end; ++n)
{
a.construct_node();
a.construct_value2(boost::move(n->value()));
a.construct_value2(boost::move(*n));
end = a.release();
end->hash_ = hash;
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -807,7 +880,8 @@ namespace boost { namespace unordered { namespace detail {
static previous_pointer place_in_bucket(buckets& dst,
previous_pointer prev, node_pointer end)
{
bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
bucket_pointer b = dst.get_bucket(policy::to_bucket(
dst.bucket_count_, end->hash_));
if (!b->next_) {
b->next_ = static_cast<node_pointer>(prev);
+6 -21
View File
@@ -51,25 +51,17 @@ namespace detail {
return v;
}
#if BOOST_UNORDERED_USE_RV_REF
static key_type const& extract(BOOST_RV_REF(key_type) v)
{
return v;
}
#endif
static no_key extract()
{
return no_key();
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
@@ -106,13 +98,6 @@ namespace detail {
return v;
}
// TODO: Why does this cause errors?
//
//static key_type const& extract(BOOST_RV_REF(key_type) v)
//{
// return v;
//}
template <class Second>
static key_type const& extract(std::pair<key_type, Second> const& v)
{
@@ -126,7 +111,7 @@ namespace detail {
return v.first;
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class Arg1, class... Args>
static key_type const& extract(key_type const& k,
Arg1 const&, Args const&...)
@@ -165,12 +150,12 @@ namespace detail {
}
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&, T2&&) \
namespace_::tuple<> const&, BOOST_FWD_REF(T2)) \
{ \
return no_key(); \
} \
@@ -178,7 +163,7 @@ namespace detail {
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k, T2&&) \
namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
@@ -206,7 +191,7 @@ namespace detail {
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
#endif
-30
View File
@@ -10,41 +10,11 @@
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
namespace boost
{
namespace unordered
{
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
struct piecewise_construct_t {};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
}
+43 -276
View File
@@ -11,251 +11,8 @@
#include <boost/unordered/detail/util.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/iterator.hpp>
#include <cmath>
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
// Iterators
//
// all no throw
template <typename NodePointer, typename Value> struct iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value> struct c_iterator;
template <typename NodePointer, typename Value> struct l_iterator;
template <typename ConstNodePointer, typename NodePointer,
typename Value> struct cl_iterator;
// Local Iterators
//
// all no throw
template <typename NodePointer, typename Value>
struct l_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename ConstNodePointer, typename NodePointer2,
typename Value2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef NodePointer node_pointer;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
l_iterator() : ptr_() {}
l_iterator(node_pointer x, std::size_t b, std::size_t c)
: ptr_(x), bucket_(b), bucket_count_(c) {}
Value& operator*() const {
return ptr_->value();
}
Value* operator->() const {
return ptr_->value_ptr();
}
l_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
ptr_ = node_pointer();
return *this;
}
l_iterator operator++(int) {
l_iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(l_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(l_iterator x) const {
return ptr_ != x.ptr_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value>
struct cl_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
<NodePointer, Value>;
private:
typedef NodePointer node_pointer;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
cl_iterator() : ptr_() {}
cl_iterator(node_pointer x, std::size_t b, std::size_t c) :
ptr_(x), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
NodePointer, Value> const& x) :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
Value const&
operator*() const {
return ptr_->value();
}
Value const* operator->() const {
return ptr_->value_ptr();
}
cl_iterator& operator++() {
ptr_ = static_cast<node_pointer>(ptr_->next_);
if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
ptr_ = node_pointer();
return *this;
}
cl_iterator operator++(int) {
cl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ == y.ptr_;
}
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ != y.ptr_;
}
};
template <typename NodePointer, typename Value>
struct iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
NodePointer, Value&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename ConstNodePointer, typename NodePointer2,
typename Value2>
friend struct boost::unordered::iterator_detail::c_iterator;
private:
#endif
typedef NodePointer node_pointer;
node_pointer node_;
public:
iterator() : node_() {}
explicit iterator(node_pointer const& x) : node_(x) {}
Value& operator*() const {
return node_->value();
}
Value* operator->() const {
return &node_->value();
}
iterator& operator++() {
node_ = node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
iterator operator++(int) {
iterator tmp(node_);
node_ = node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
bool operator==(iterator const& x) const {
return node_ == x.node_;
}
bool operator!=(iterator const& x) const {
return node_ != x.node_;
}
};
template <typename ConstNodePointer, typename NodePointer, typename Value>
struct c_iterator
: public boost::iterator<
std::forward_iterator_tag, Value, std::ptrdiff_t,
ConstNodePointer, Value const&>
{
friend struct boost::unordered::iterator_detail::iterator<
NodePointer, Value>;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename K, typename T, typename H, typename P, typename A>
friend class boost::unordered::unordered_map;
template <typename K, typename T, typename H, typename P, typename A>
friend class boost::unordered::unordered_multimap;
template <typename T, typename H, typename P, typename A>
friend class boost::unordered::unordered_set;
template <typename T, typename H, typename P, typename A>
friend class boost::unordered::unordered_multiset;
private:
#endif
typedef NodePointer node_pointer;
node_pointer node_;
public:
c_iterator() : node_() {}
explicit c_iterator(node_pointer const& x) : node_(x) {}
c_iterator(boost::unordered::iterator_detail::iterator<
NodePointer, Value> const& x) : node_(x.node_) {}
Value const& operator*() const {
return node_->value();
}
Value const* operator->() const {
return &node_->value();
}
c_iterator& operator++() {
node_ = static_cast<node_pointer>(node_->next_);
return *this;
}
c_iterator operator++(int) {
c_iterator tmp(node_);
node_ = node_ = static_cast<node_pointer>(node_->next_);
return tmp;
}
friend bool operator==(c_iterator const& x, c_iterator const& y) {
return x.node_ == y.node_;
}
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
return x.node_ != y.node_;
}
};
}}}
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
@@ -302,7 +59,8 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::buckets<
typename Types::allocator,
typename Types::bucket,
typename Types::node>,
typename Types::node,
typename Types::policy>,
boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal>
@@ -318,6 +76,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename Types::value_type value_type;
typedef typename Types::table table_impl;
typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy;
typedef boost::unordered::detail::functions<
typename Types::hasher,
@@ -326,22 +85,15 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::buckets<
typename Types::allocator,
typename Types::bucket,
typename Types::node> buckets;
typename Types::node,
typename Types::policy> buckets;
typedef typename buckets::node_allocator node_allocator;
typedef typename buckets::node_allocator_traits node_allocator_traits;
typedef typename buckets::node_pointer node_pointer;
typedef typename buckets::const_node_pointer const_node_pointer;
typedef boost::unordered::iterator_detail::
iterator<node_pointer, value_type> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node_pointer, value_type> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<const_node_pointer, node_pointer, value_type>
cl_iterator;
typedef typename table::iterator iterator;
// Members
@@ -384,7 +136,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t min_buckets_for_size(std::size_t size) const
{
BOOST_ASSERT(this->mlf_ != 0);
BOOST_ASSERT(this->mlf_ >= minimum_max_load_factor);
using namespace std;
@@ -395,7 +147,7 @@ namespace boost { namespace unordered { namespace detail {
// Or from rehash post-condition:
// count > size / mlf_
return boost::unordered::detail::next_prime(
return policy::new_bucket_count(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_))) + 1);
@@ -408,7 +160,7 @@ namespace boost { namespace unordered { namespace detail {
hasher const& hf,
key_equal const& eq,
node_allocator const& a) :
buckets(a, boost::unordered::detail::next_prime(num_buckets)),
buckets(a, policy::new_bucket_count(num_buckets)),
functions(hf, eq),
mlf_(1.0f),
max_load_(0)
@@ -458,9 +210,9 @@ namespace boost { namespace unordered { namespace detail {
// Iterators
node_pointer begin() const {
iterator begin() const {
return !this->buckets_ ?
node_pointer() : this->get_start();
iterator() : this->get_start();
}
// Assignment
@@ -586,36 +338,41 @@ namespace boost { namespace unordered { namespace detail {
return extractor::extract(x);
}
std::size_t hash(key_type const& k) const
{
return policy::apply_hash(this->hash_function(), k);
}
// Find Node
template <typename Key, typename Hash, typename Pred>
node_pointer generic_find_node(
iterator generic_find_node(
Key const& k,
Hash const& hash_function,
Hash const& hf,
Pred const& eq) const
{
if (!this->size_) return node_pointer();
if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
find_node_impl(hash_function(k), k, eq);
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
node_pointer find_node(
std::size_t hash,
iterator find_node(
std::size_t key_hash,
key_type const& k) const
{
if (!this->size_) return node_pointer();
if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
find_node_impl(hash, k, this->key_eq());
find_node_impl(key_hash, k, this->key_eq());
}
node_pointer find_node(key_type const& k) const
iterator find_node(key_type const& k) const
{
if (!this->size_) return node_pointer();
if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
find_node_impl(this->hash_function()(k), k, this->key_eq());
find_node_impl(this->hash(k), k, this->key_eq());
}
node_pointer find_matching_node(node_pointer n) const
iterator find_matching_node(iterator n) const
{
// TODO: Does this apply to C++11?
//
@@ -623,13 +380,14 @@ namespace boost { namespace unordered { namespace detail {
// when different hash functions are used. So I can't use the hash
// value from the node here.
return find_node(get_key(n->value()));
return find_node(get_key(*n));
}
// Reserve and rehash
void reserve_for_insert(std::size_t);
void rehash(std::size_t);
void reserve(std::size_t);
};
////////////////////////////////////////////////////////////////////////////
@@ -645,7 +403,9 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets();
this->max_load_ = this->calculate_max_load();
}
else if(size >= max_load_) {
// According to the standard this should be 'size >= max_load_',
// but I think this is better, defect report filed.
else if(size > max_load_) {
std::size_t num_buckets
= this->min_buckets_for_size((std::max)(size,
this->size_ + (this->size_ >> 1)));
@@ -660,16 +420,16 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise.
template <typename Types>
void table<Types>::rehash(std::size_t min_buckets)
inline void table<Types>::rehash(std::size_t min_buckets)
{
using namespace std;
if(!this->size_) {
if(this->buckets_) this->delete_buckets();
this->bucket_count_ = next_prime(min_buckets);
this->bucket_count_ = policy::new_bucket_count(min_buckets);
}
else {
min_buckets = next_prime((std::max)(min_buckets,
min_buckets = policy::new_bucket_count((std::max)(min_buckets,
boost::unordered::detail::double_to_size(floor(
static_cast<double>(this->size_) /
static_cast<double>(mlf_))) + 1));
@@ -680,6 +440,13 @@ namespace boost { namespace unordered { namespace detail {
}
}
}
template <typename Types>
inline void table<Types>::reserve(std::size_t num_elements)
{
rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(num_elements) / this->mlf_)));
}
}}}
#endif
+183 -117
View File
@@ -12,35 +12,60 @@
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/emplace_args.hpp>
#include <boost/unordered/detail/extract_key.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T> struct node;
template <typename A, typename T> struct unique_node;
template <typename T> struct ptr_node;
template <typename Types> struct table_impl;
template <typename A, typename T>
struct node :
struct unique_node :
boost::unordered::detail::node_base<
typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type::pointer
>,
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, node<A, T> >::type::pointer link_pointer;
A, unique_node<A, T> >::type::pointer link_pointer;
typedef boost::unordered::detail::node_base<link_pointer> node_base;
link_pointer next_;
std::size_t hash_;
node() :
next_(),
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
explicit 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());
}
unique_node(unique_node const&) {
BOOST_ASSERT(false);
}
#else
unique_node() :
node_base(),
hash_(0)
{}
#endif
void init(link_pointer)
{
}
private:
unique_node& operator=(unique_node const&);
};
template <typename T>
@@ -49,18 +74,41 @@ 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>
explicit 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());
}
ptr_node(ptr_node const&) {
BOOST_ASSERT(false);
}
#else
ptr_node() :
bucket_base(),
hash_(0)
{}
#endif
void init(link_pointer)
{
}
private:
ptr_node& operator=(ptr_node const&);
};
// If the allocator uses raw pointers use ptr_node
@@ -69,7 +117,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_node2
{
typedef boost::unordered::detail::node<A, T> node;
typedef boost::unordered::detail::unique_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
@@ -111,42 +159,46 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename H, typename P>
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, H, P> types;
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef value_type key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename H, typename P>
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, H, P> types;
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<A> traits;
typedef typename traits::value_type value_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -154,6 +206,8 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
@@ -163,6 +217,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::buckets buckets;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
@@ -175,6 +230,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
typedef std::pair<iterator, bool> emplace_return;
@@ -210,44 +266,46 @@ namespace boost { namespace unordered { namespace detail {
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
std::size_t hash,
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
if (hash == node_hash)
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return iterator();
}
n = static_cast<node_pointer>(n->next_);
++n;
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k) ? 1 : 0;
return this->find_node(k).node_ ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
node_pointer it = this->find_node(k);
if (it) return it->value();
iterator it = this->find_node(k);
if (it.node_) return *it;
}
boost::throw_exception(
@@ -257,9 +315,10 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n),
iterator(n ? static_cast<node_pointer>(n->next_) : n));
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
}
// equals
@@ -269,17 +328,15 @@ namespace boost { namespace unordered { namespace detail {
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(node_pointer n1 = this->get_start(); n1;
n1 = static_cast<node_pointer>(n1->next_))
for(iterator n1 = this->get_start(); n1.node_; ++n1)
{
node_pointer n2 = other.find_matching_node(n1);
iterator n2 = other.find_matching_node(n1);
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if(!n2 || n1->value() != n2->value())
if (!n2.node_ || *n1 != *n2)
return false;
#else
if(!n2 || !extractor::compare_mapped(
n1->value(), n2->value()))
if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
return false;
#endif
}
@@ -289,23 +346,24 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline node_pointer add_node(
inline iterator add_node(
node_constructor& a,
std::size_t hash)
std::size_t key_hash)
{
node_pointer n = a.release();
n->hash_ = hash;
n->hash_ = key_hash;
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
bucket_pointer b = this->get_bucket(
policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(
static_cast<node_pointer>(start_node->next_)->hash_ %
this->bucket_count_)->next_ = n;
this->get_bucket(policy::to_bucket(this->bucket_count_,
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
}
b->next_ = start_node;
@@ -319,54 +377,57 @@ namespace boost { namespace unordered { namespace detail {
}
++this->size_;
return n;
return iterator(n);
}
value_type& operator[](key_type const& k)
{
typedef typename value_type::second_type mapped_type;
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos) return pos->value();
if (pos.node_) return *pos;
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_node();
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
a.construct_value(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple());
#else
a.construct_value(
boost::unordered::detail::create_emplace_args(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
#endif
a.construct_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
this->reserve_for_insert(this->size_ + 1);
return add_node(a, hash)->value();
return *add_node(a, key_hash);
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
# if defined(BOOST_NO_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(this->begin()), false);
return emplace_return(this->begin(), false);
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_impl(
extractor::extract(args.a0, args.a1),
@@ -374,7 +435,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
@@ -387,10 +448,10 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos) return emplace_return(iterator(pos), false);
if (pos.node_) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
@@ -401,21 +462,21 @@ namespace boost { namespace unordered { namespace detail {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(iterator(this->add_node(a, hash)), true);
return emplace_return(this->add_node(a, key_hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos) return emplace_return(iterator(pos), false);
if (pos.node_) return emplace_return(pos, false);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(iterator(this->add_node(a, hash)), true);
return emplace_return(this->add_node(a, key_hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
@@ -471,12 +532,12 @@ namespace boost { namespace unordered { namespace detail {
void insert_range_empty(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
{
std::size_t hash = this->hash_function()(k);
std::size_t key_hash = this->hash(k);
a.construct_node();
a.construct_value2(*i);
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
this->add_node(a, hash);
this->add_node(a, key_hash);
}
template <class InputIt>
@@ -484,19 +545,19 @@ namespace boost { namespace unordered { namespace detail {
InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (!pos) {
if (!pos.node_) {
a.construct_node();
a.construct_value2(*i);
if(this->size_ + 1 >= this->max_load_)
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
// Nothing after this point can throw.
this->add_node(a, hash);
this->add_node(a, key_hash);
}
}
@@ -521,11 +582,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_;
bucket_pointer bucket = this->get_bucket(bucket_index);
std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, key_hash);
bucket_pointer this_bucket = this->get_bucket(bucket_index);
previous_pointer prev = bucket->next_;
previous_pointer prev = this_bucket->next_;
if (!prev) return 0;
for (;;)
@@ -533,9 +595,10 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (node_hash % this->bucket_count_ != bucket_index)
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return 0;
if (node_hash == hash &&
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
@@ -545,37 +608,39 @@ namespace boost { namespace unordered { namespace detail {
node_pointer pos = static_cast<node_pointer>(prev->next_);
node_pointer end = static_cast<node_pointer>(pos->next_);
prev->next_ = pos->next_;
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
this->fix_buckets(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
}
node_pointer erase(node_pointer r)
iterator erase(c_iterator r)
{
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
previous_pointer prev = unlink_node(*this_bucket, r.node_);
this->fix_buckets(bucket, prev, next);
this->fix_buckets(this_bucket, prev, next.node_);
this->delete_node(r);
return next;
}
node_pointer erase_range(node_pointer r1, node_pointer r2)
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return r2;
if (r1 == r2) return iterator(r2.node_);
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
std::size_t bucket_index =
policy::to_bucket(this->bucket_count_, r1.node_->hash_);
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
*this->get_bucket(bucket_index), r1.node_, r2.node_);
this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
this->delete_nodes(r1, r2);
return r2;
return iterator(r2.node_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
@@ -608,18 +673,18 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
iterator n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
while(n.node_) {
a.construct_node();
a.construct_value2(n->value());
a.construct_value2(*n);
node_pointer node = a.release();
node->hash_ = n->hash_;
node->hash_ = n.node_->hash_;
prev->next_ = static_cast<link_pointer>(node);
++dst.size_;
n = static_cast<node_pointer>(n->next_);
++n;
prev = place_in_bucket(dst, prev);
}
@@ -639,18 +704,18 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
iterator n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
while (n.node_) {
a.construct_node();
a.construct_value2(boost::move(n->value()));
a.construct_value2(boost::move(*n));
node_pointer node = a.release();
node->hash_ = n->hash_;
node->hash_ = n.node_->hash_;
prev->next_ = static_cast<link_pointer>(node);
++dst.size_;
n = static_cast<node_pointer>(n->next_);
++n;
prev = place_in_bucket(dst, prev);
}
@@ -687,7 +752,8 @@ namespace boost { namespace unordered { namespace detail {
previous_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
bucket_pointer b = dst.get_bucket(
buckets::to_bucket(dst.bucket_count_, n->hash_));
if (!b->next_) {
b->next_ = prev;
+1 -1
View File
@@ -56,7 +56,7 @@ namespace boost { namespace unordered { namespace detail {
// primes
#define BOOST_UNORDERED_PRIMES \
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
+312 -112
View File
@@ -14,14 +14,13 @@
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
#endif
@@ -41,7 +40,9 @@ namespace unordered
template <class K, class T, class H, class P, class A>
class unordered_map
{
#if defined(BOOST_UNORDERED_USE_MOVE)
BOOST_COPYABLE_AND_MOVABLE(unordered_map)
#endif
public:
@@ -54,15 +55,9 @@ namespace unordered
private:
typedef typename boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
allocator_traits;
typedef boost::unordered::detail::map<value_allocator, K, H, P>
types;
typedef boost::unordered::detail::map<A, K, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
public:
@@ -84,7 +79,7 @@ namespace unordered
private:
table table_;
public:
// constructors
@@ -121,16 +116,23 @@ 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&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -145,6 +147,7 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
{
table_.assign(x.table_);
@@ -156,8 +159,23 @@ 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_0X_HDR_INITIALIZER_LIST)
#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_CXX11_HDR_INITIALIZER_LIST)
unordered_map& operator=(std::initializer_list<value_type>);
#endif
@@ -184,12 +202,12 @@ namespace unordered
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
@@ -204,7 +222,7 @@ namespace unordered
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
@@ -214,20 +232,115 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(std::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...).first);
return table_.emplace(boost::forward<Args>(args)...).first;
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
// doesn't have a default constructor.
std::pair<iterator, bool> emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return this->emplace(boost::move(v));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return this->emplace_hint(hint, boost::move(v));
}
#endif
template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
).first;
}
template <typename A0, typename A1>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
).first;
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
).first;
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
@@ -251,39 +364,18 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)).first); \
)).first; \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
std::pair<iterator, bool> emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return this->emplace(boost::move(v));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return this->emplace_hint(hint, boost::move(v));
}
#endif
#endif
std::pair<iterator, bool> insert(value_type const& x)
@@ -308,7 +400,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -372,7 +464,8 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
}
local_iterator begin(size_type n)
@@ -421,6 +514,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<K,T,H,P,A>(
@@ -433,8 +527,9 @@ namespace unordered
template <class K, class T, class H, class P, class A>
class unordered_multimap
{
#if defined(BOOST_UNORDERED_USE_MOVE)
BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
#endif
public:
typedef K key_type;
@@ -446,15 +541,9 @@ namespace unordered
private:
typedef typename boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
allocator_traits;
typedef boost::unordered::detail::multimap<value_allocator, K, H, P>
types;
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
public:
@@ -513,16 +602,23 @@ 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&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -537,6 +633,7 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap& operator=(
BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
{
@@ -549,8 +646,23 @@ 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_0X_HDR_INITIALIZER_LIST)
#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_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
@@ -577,12 +689,12 @@ namespace unordered
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
@@ -597,7 +709,7 @@ namespace unordered
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
@@ -607,20 +719,115 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(Args&&... args)
iterator emplace(BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
return table_.emplace(boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
// doesn't have a default constructor.
iterator emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return this->emplace(boost::move(v));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return this->emplace_hint(hint, boost::move(v));
}
#endif
template <typename A0>
iterator emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0, typename A1>
iterator emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
@@ -629,11 +836,11 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
))); \
)); \
} \
\
template < \
@@ -644,39 +851,18 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
))); \
)); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
iterator emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return iterator(this->emplace(boost::move(v)));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return iterator(this->emplace_hint(hint, boost::move(v)));
}
#endif
#endif
iterator insert(value_type const& x)
@@ -701,7 +887,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -761,7 +947,8 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
}
local_iterator begin(size_type n)
@@ -810,6 +997,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<K,T,H,P,A>(
@@ -899,7 +1087,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -941,7 +1129,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -954,7 +1142,7 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class K, class T, class H, class P, class A>
@@ -969,7 +1157,7 @@ namespace unordered
unordered_map<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class K, class T, class H, class P, class A>
@@ -1027,14 +1215,14 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1046,7 +1234,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1058,7 +1246,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1113,6 +1301,12 @@ namespace unordered
table_.rehash(n);
}
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_map<K,T,H,P,A> const& m1,
@@ -1226,7 +1420,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1268,7 +1462,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1281,7 +1475,7 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class K, class T, class H, class P, class A>
@@ -1296,7 +1490,7 @@ namespace unordered
unordered_multimap<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class K, class T, class H, class P, class A>
@@ -1333,14 +1527,14 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1352,7 +1546,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1364,7 +1558,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1419,6 +1613,12 @@ namespace unordered
table_.rehash(n);
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_multimap<K,T,H,P,A> const& m1,
@@ -10,12 +10,23 @@
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
namespace unordered
{
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_map<K, T, H, P, A> const&,
unordered_map<K, T, H, P, A> const&);
@@ -26,6 +37,13 @@ namespace boost
inline void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class K,
class T,
class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
+313 -112
View File
@@ -14,14 +14,13 @@
#endif
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
#endif
@@ -41,7 +40,9 @@ namespace unordered
template <class T, class H, class P, class A>
class unordered_set
{
#if defined(BOOST_UNORDERED_USE_MOVE)
BOOST_COPYABLE_AND_MOVABLE(unordered_set)
#endif
public:
typedef T key_type;
@@ -52,15 +53,9 @@ namespace unordered
private:
typedef typename boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
allocator_traits;
typedef boost::unordered::detail::set<value_allocator, H, P>
types;
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
public:
@@ -119,16 +114,23 @@ 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&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -143,6 +145,7 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
{
table_.assign(x.table_);
@@ -154,8 +157,23 @@ 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_0X_HDR_INITIALIZER_LIST)
#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_CXX11_HDR_INITIALIZER_LIST)
unordered_set& operator=(std::initializer_list<value_type>);
#endif
@@ -182,12 +200,12 @@ namespace unordered
iterator begin()
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
@@ -202,7 +220,7 @@ namespace unordered
const_iterator cbegin() const
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
@@ -212,20 +230,115 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(std::forward<Args>(args)...);
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...).first);
return table_.emplace(boost::forward<Args>(args)...).first;
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
// doesn't have a default constructor.
std::pair<iterator, bool> emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return this->emplace(boost::move(v));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return this->emplace_hint(hint, boost::move(v));
}
#endif
template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
).first;
}
template <typename A0, typename A1>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
).first;
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
).first;
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
@@ -249,39 +362,18 @@ namespace unordered
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)).first); \
)).first; \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
std::pair<iterator, bool> emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
return this->emplace(boost::move(v));
}
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
value_type v = value_type()
)
{
return iterator(this->emplace_hint(hint, boost::move(v)));
}
#endif
#endif
std::pair<iterator, bool> insert(value_type const& x)
@@ -307,7 +399,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -357,7 +449,8 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
}
local_iterator begin(size_type n)
@@ -406,6 +499,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<T,H,P,A>(
@@ -418,7 +512,9 @@ namespace unordered
template <class T, class H, class P, class A>
class unordered_multiset
{
#if defined(BOOST_UNORDERED_USE_MOVE)
BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
#endif
public:
typedef T key_type;
@@ -429,15 +525,9 @@ namespace unordered
private:
typedef typename boost::unordered::detail::rebind_wrap<
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
allocator_traits;
typedef boost::unordered::detail::multiset<value_allocator, H, P>
types;
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
public:
@@ -496,16 +586,23 @@ 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&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -520,6 +617,7 @@ namespace unordered
// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset& operator=(
BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
{
@@ -532,8 +630,23 @@ 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_0X_HDR_INITIALIZER_LIST)
#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_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
@@ -590,57 +703,26 @@ namespace unordered
// emplace
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(Args&&... args)
iterator emplace(BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return iterator(table_.emplace(std::forward<Args>(args)...));
return table_.emplace(boost::forward<Args>(args)...);
}
#else
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
))); \
} \
\
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return iterator(table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
))); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
// doesn't have a default constructor.
iterator emplace(
boost::unordered::detail::empty_emplace
= boost::unordered::detail::empty_emplace(),
@@ -660,6 +742,111 @@ namespace unordered
#endif
template <typename A0>
iterator emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
}
template <typename A0, typename A1>
iterator emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace(
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
);
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)); \
} \
\
template < \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)); \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#endif
iterator insert(value_type const& x)
@@ -685,7 +872,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -735,7 +922,8 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table::to_bucket(table_.bucket_count_,
table_.hash(k));
}
local_iterator begin(size_type n)
@@ -784,6 +972,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<T,H,P,A>(
@@ -873,7 +1062,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -915,7 +1104,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -928,7 +1117,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class T, class H, class P, class A>
@@ -943,7 +1132,7 @@ namespace unordered
unordered_set<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class T, class H, class P, class A>
@@ -980,7 +1169,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -992,7 +1181,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1038,6 +1227,12 @@ namespace unordered
table_.rehash(n);
}
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class T, class H, class P, class A>
inline bool operator==(
unordered_set<T,H,P,A> const& m1,
@@ -1151,7 +1346,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1193,7 +1388,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1206,7 +1401,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class T, class H, class P, class A>
@@ -1221,7 +1416,7 @@ namespace unordered
unordered_multiset<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class T, class H, class P, class A>
@@ -1258,7 +1453,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -1270,7 +1465,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1316,6 +1511,12 @@ namespace unordered
table_.rehash(n);
}
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class T, class H, class P, class A>
inline bool operator==(
unordered_multiset<T,H,P,A> const& m1,
@@ -10,12 +10,22 @@
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost
{
namespace unordered
{
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T, class H, class P, class A>
inline bool operator==(unordered_set<T, H, P, A> const&,
unordered_set<T, H, P, A> const&);
@@ -26,6 +36,12 @@ namespace boost
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class T,
class H = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
+1 -3
View File
@@ -3,8 +3,6 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(12847);
test::seed_t initialize_seed(12847);
template <class T>
struct self_assign_base : public test::exception_base
@@ -3,15 +3,13 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/input_iterator.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(91274);
test::seed_t initialize_seed(91274);
struct objects
{
+2
View File
@@ -3,8 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include "../objects/exception.hpp"
typedef boost::unordered_set<
+1 -3
View File
@@ -3,14 +3,12 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(73041);
test::seed_t initialize_seed(73041);
template <class T>
struct copy_test1 : public test::exception_base
+1 -3
View File
@@ -3,14 +3,12 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
test::seed_t seed(835193);
test::seed_t initialize_seed(835193);
template <class T>
struct erase_test_base : public test::exception_base
+8 -10
View File
@@ -3,8 +3,6 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <boost/utility.hpp>
#include <cmath>
test::seed_t seed(747373);
test::seed_t initialize_seed(747373);
template <class T>
struct insert_test_base : public test::exception_base
@@ -34,7 +32,7 @@ struct insert_test_base : public test::exception_base
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::exception::detail::tracker.count_allocations);
strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
@@ -51,7 +49,7 @@ struct emplace_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.emplace(*it);
}
}
@@ -69,7 +67,7 @@ struct insert_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
}
@@ -85,7 +83,7 @@ struct insert_test2 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
@@ -113,7 +111,7 @@ struct insert_test4 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
@@ -152,7 +150,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
@@ -176,7 +174,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
+1 -3
View File
@@ -3,8 +3,6 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <iostream>
test::seed_t seed(3298597);
test::seed_t initialize_seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
+1 -3
View File
@@ -3,8 +3,6 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(9387);
test::seed_t initialize_seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
-84
View File
@@ -1,84 +0,0 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER
#include <cstddef>
#include <cstdlib>
#include <boost/limits.hpp>
#include <new>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace test
{
template <class T>
struct malloc_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef malloc_allocator<U> other; };
malloc_allocator() {}
template <class Y> malloc_allocator(malloc_allocator<Y> const&) {}
malloc_allocator(malloc_allocator const&) {}
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
pointer allocate(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(T)));
if(!ptr) throw std::bad_alloc();
return ptr;
}
pointer allocate(size_type n, void const* u) { return allocate(n); }
void deallocate(pointer p, size_type) {
using namespace std;
free(p);
}
void construct(pointer p, T const& t) { new(p) T(t); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const&) const { return true; }
bool operator!=(malloc_allocator const&) const { return false; }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void deallocate(T* p, size_type) {
using namespace std;
free(p);
}
char* _Charalloc(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(char)));
if(!ptr) throw std::bad_alloc();
return (char*) ptr;
}
#endif
};
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#endif
+4 -4
View File
@@ -6,7 +6,7 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
@@ -18,19 +18,19 @@ namespace test
template <class T2>
static void equals(T2)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
}
+8 -16
View File
@@ -52,30 +52,22 @@ namespace test {
}
};
template <class T>
struct counted_object
{
static object_count count_;
counted_object() { count_.construct(); }
counted_object(counted_object const&) { count_.construct(); }
~counted_object() { count_.destruct(); }
};
template <class T> object_count counted_object<T>::count_;
struct globally_counted_object
: counted_object<globally_counted_object> {};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count& global_object_count = globally_counted_object::count_;
object_count global_object_count;
}
struct counted_object
{
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
struct check_instances {
int instances;
+2 -6
View File
@@ -13,7 +13,6 @@
#include <cmath>
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#include "./allocator.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -29,16 +28,13 @@ namespace test
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
// Boost.Test was reporting memory leaks for std::set on g++-3.3.
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>,
test::malloc_allocator<key_type> > found_;
std::set<key_type, std::less<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while(it != end) {
// First test that the current key has not occured before, required
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
+3 -3
View File
@@ -219,14 +219,14 @@ namespace test
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator start, const_iterator end) {
void erase(const_iterator i, const_iterator j) {
node** ptr = &data_.first_;
while(*ptr != start.ptr_) {
while(*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != end.ptr_) {
while(*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
+6 -52
View File
@@ -8,10 +8,8 @@
#include <memory>
#include <map>
#include <boost/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include "../helpers/test.hpp"
namespace test
@@ -53,30 +51,10 @@ namespace test
}
};
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
Alloc> type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_memory_type_gen<int> {
typedef std::map<memory_area, memory_track, memory_area_compare>
type;
};
#endif
template <class Alloc = std::allocator<int> >
struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<Alloc,
std::pair<memory_area const, memory_track> >::type
allocator_type;
typedef BOOST_DEDUCED_TYPENAME
allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> >
> allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
@@ -139,7 +117,7 @@ namespace test
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag, bool check_tag_ = true)
{
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
@@ -177,33 +155,9 @@ namespace test
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker<std::allocator<int> > tracker;
test::detail::memory_tracker tracker;
}
}
template <int Value>
struct bool_type {
enum { value = (Value ? true : false) };
};
struct true_type {
enum { value = true };
};
struct false_type {
enum { value = false };
};
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
int selected_count(convert_from_anything)
{
return 0;
}
}
#endif
+10 -49
View File
@@ -8,72 +8,33 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test
{
/*
struct unordered_set_type { char x[100]; };
struct unordered_multiset_type { char x[200]; };
struct unordered_map_type { char x[300]; };
struct unordered_multimap_type { char x[400]; };
template <class V, class H, class P, class A>
unordered_set_type container_type(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
unordered_multiset_type container_type(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_map_type container_type(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_multimap_type container_type(
boost::unordered_multimap<K, M, H, P, A> const*);
*/
template <class Container>
struct is_set
: public boost::is_same<
BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type> {};
template <class Container>
struct is_map
: public boost::mpl::not_<is_set<Container> > {};
struct yes_type { char x[100]; };
struct no_type { char x[200]; };
template <class V, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(yes_type));
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class Container>
struct has_equivalent_keys
template <class V, class H, class P, class A>
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class K, class M, class H, class P, class A>
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
+10
View File
@@ -0,0 +1,10 @@
// Copyright 2012 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Include this after the boost headers, but before other test headers.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+6 -4
View File
@@ -8,7 +8,7 @@
#include "./list.hpp"
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/detail/select_type.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
@@ -81,10 +81,12 @@ namespace test
template <class X>
struct unordered_generator_base
: public boost::mpl::if_<
test::is_set<X>,
: public boost::detail::if_true<
test::is_set<X>::value
>::BOOST_NESTED_TEMPLATE then<
test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
test::unordered_generator_map<X>
>
{
};
-1
View File
@@ -8,7 +8,6 @@
#include <boost/config.hpp>
#include <iterator>
#include "./metafunctions.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
+45 -63
View File
@@ -13,9 +13,6 @@
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
#include "../objects/fwd.hpp"
#include "./metafunctions.hpp"
@@ -25,21 +22,17 @@
namespace test
{
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<
std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
template <typename X>
struct equals_to_compare
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type>
type;
};
template <class X>
struct equals_to_compare
: public boost::mpl::eval_if<
boost::is_same<X, test::equal_to>,
boost::mpl::identity<test::less>,
equals_to_compare2<X>
>
template <>
struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
template <class X1, class X2>
@@ -67,51 +60,40 @@ namespace test
values2.begin(), test::equivalent));
}
template <class X>
struct ordered_set : public
boost::mpl::if_<
test::has_unique_keys<X>,
std::set<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>,
std::multiset<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>
> {};
template <typename X>
struct ordered_base;
template <class X>
struct ordered_map : public
boost::mpl::if_<
test::has_unique_keys<X>,
std::map<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>,
std::multimap<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_set<V, H, P, A> >
{
typedef std::set<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
struct ordered_base : public
boost::mpl::eval_if<
test::is_set<X>,
test::ordered_set<X>,
test::ordered_map<X>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
{
typedef std::map<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
{
typedef std::multimap<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
class ordered : public ordered_base<X>::type
@@ -124,8 +106,8 @@ namespace test
: base()
{}
explicit ordered(key_compare const& compare)
: base(compare)
explicit ordered(key_compare const& kc)
: base(kc)
{}
void compare(X const& x)
@@ -143,10 +125,10 @@ namespace test
}
template <class It>
void insert_range(It begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
}
}
};
+21 -5
View File
@@ -21,7 +21,8 @@ namespace test
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
@@ -31,7 +32,8 @@ namespace test
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
@@ -168,10 +170,10 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<typename... Args> void construct(T* p, Args&&... args) {
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<typename... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(std::forward<Args>(args)...);
new(p) T(boost::forward<Args>(args)...);
}
#endif
@@ -291,6 +293,20 @@ namespace test
return x.tag_ == y.tag_;
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
inline int selected_count(convert_from_anything)
{
return 0;
}
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
+14 -23
View File
@@ -13,21 +13,12 @@
#include <boost/limits.hpp>
#include <new>
#include "../helpers/fwd.hpp"
#include "../helpers/allocator.hpp"
#include "../helpers/memory.hpp"
namespace test
{
namespace exception
{
namespace detail
{
namespace
{
test::detail::memory_tracker<test::malloc_allocator<int> > tracker;
}
}
class object;
class hash;
class equal_to;
@@ -259,7 +250,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator default constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
@@ -267,7 +258,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator template copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
allocator(allocator const& x) : tag_(x.tag_)
@@ -275,11 +266,11 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
~allocator() {
detail::tracker.allocator_unref();
test::detail::tracker.allocator_unref();
}
allocator& operator=(allocator const& x) {
@@ -317,7 +308,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -333,7 +324,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -343,7 +334,7 @@ namespace exception
{
//::operator delete((void*) p);
if(p) {
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std;
free(p);
}
@@ -354,21 +345,21 @@ namespace exception
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(t);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(std::forward<Args>(args)...);
new(p) T(boost::forward<Args>(args)...);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
+7 -7
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 void_const_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
@@ -367,9 +367,9 @@ namespace minimal
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
new((void*)p) T(std::forward<Args>(args)...);
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
}
#endif
@@ -439,9 +439,9 @@ namespace minimal
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
new((void*)p) T(std::forward<Args>(args)...);
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
}
#endif
+114 -17
View File
@@ -22,11 +22,14 @@ namespace test
class hash;
class less;
class equal_to;
template <class T> class allocator;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*);
implicitly_convertible generate(implicitly_convertible const*);
class object : private globally_counted_object
inline void ignore_variable(void const*) {}
class object : private counted_object
{
friend class hash;
friend class equal_to;
@@ -64,7 +67,7 @@ namespace test
}
};
class implicitly_convertible : private globally_counted_object
class implicitly_convertible : private counted_object
{
int tag1_, tag2_;
public:
@@ -183,13 +186,100 @@ namespace test
}
};
// allocator1 and allocator2 are pretty similar.
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs
template <class T>
class allocator
class allocator1
{
public:
int tag_;
typedef T value_type;
template <class U> struct rebind { typedef allocator1<U> other; };
explicit allocator1(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator1(allocator1<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator1(allocator1 const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator1()
{
detail::tracker.allocator_unref();
}
T* allocate(std::size_t n) {
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
T* allocate(std::size_t n, void const* u)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(T* p, std::size_t n)
{
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
::operator delete((void*) p);
}
void construct(T* p, T const& t) {
// Don't count constructions here as it isn't always called.
//detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
void destroy(T* p) {
//detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
// Work around MSVC buggy unused parameter warning.
ignore_variable(&p);
}
bool operator==(allocator1 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator1 const& x) const
{
return tag_ != x.tag_;
}
enum {
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
template <class T>
class allocator2
{
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
# else
template <class> friend class allocator;
template <class> friend class allocator2;
# endif
int tag_;
public:
@@ -201,26 +291,26 @@ namespace test
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
template <class U> struct rebind { typedef allocator2<U> other; };
explicit allocator(int t = 0) : tag_(t)
explicit allocator2(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x)
template <class Y> allocator2(allocator2<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator(allocator const& x)
allocator2(allocator2 const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator()
~allocator2()
{
detail::tracker.allocator_unref();
}
@@ -259,10 +349,10 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(std::forward<Args>(args)...);
new(p) T(boost::forward<Args>(args)...);
}
#endif
@@ -275,12 +365,12 @@ namespace test
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator const& x) const
bool operator==(allocator2 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator const& x) const
bool operator!=(allocator2 const& x) const
{
return tag_ != x.tag_;
}
@@ -294,7 +384,14 @@ namespace test
};
template <class T>
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y,
bool equivalent_impl(allocator1<T> const& x, allocator1<T> const& y,
test::derived_type)
{
return x == y;
}
template <class T>
bool equivalent_impl(allocator2<T> const& x, allocator2<T> const& y,
test::derived_type)
{
return x == y;
+20 -5
View File
@@ -9,13 +9,12 @@ project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
#<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
;
test-suite unordered
@@ -50,4 +49,20 @@ test-suite unordered
[ run equality_tests.cpp ]
[ run equality_deprecated.cpp ]
[ run swap_tests.cpp ]
[ run compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
+46 -22
View File
@@ -3,10 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/limits.hpp>
// Boilerplate
@@ -90,11 +90,16 @@ void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
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*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
@@ -123,11 +128,16 @@ void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
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*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
@@ -164,11 +174,11 @@ void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
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*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
@@ -186,6 +196,20 @@ struct ptr
T& operator*() const { return *value_; }
};
template <>
struct ptr<void>
{
void* value_;
ptr(void* v) : value_(v) {}
};
template <>
struct ptr<const void>
{
void const* value_;
ptr(void const* v) : value_(v) {}
};
template <typename T>
struct allocator3
{
@@ -209,11 +233,11 @@ void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, unsigned short>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, ptr<int> >));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
+17 -14
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 seed(96785);
test::seed_t initialize_seed(96785);
template <class T>
void assign_tests1(T*,
@@ -114,18 +114,22 @@ void assign_tests2(T*,
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -178,6 +182,7 @@ UNORDERED_AUTO_TEST(check_traits)
}
UNORDERED_TEST(assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
(test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
@@ -193,7 +198,7 @@ UNORDERED_TEST(assign_tests2, (
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -208,9 +213,7 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
+12 -1
View File
@@ -4,29 +4,40 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <string>
namespace at_tests {
UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
x["one"] = 1;
x["two"] = 2;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl;
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
try {
x.at("three");
BOOST_ERROR("Should have thrown.");
}
catch(std::out_of_range) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
+18 -13
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
#include "../objects/test.hpp"
@@ -20,7 +21,7 @@
namespace bucket_tests {
test::seed_t seed(54635);
test::seed_t initialize_seed(54635);
template <class X>
void tests(X* = 0, test::random_generator generator = test::default_generator)
@@ -67,20 +68,24 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(test_multimap)))
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multimap;
UNORDERED_TEST(tests, ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)))
}
+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"
+38 -42
View File
@@ -16,12 +16,12 @@
#pragma warning(pop)
#endif
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#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;
@@ -54,42 +54,38 @@ void container_test(X& r, T const&)
// value_type
BOOST_MPL_ASSERT((boost::is_same<T, value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
boost::function_requires<boost::CopyConstructibleConcept<X> >();
// reference_type / const_reference_type
BOOST_MPL_ASSERT((boost::is_same<T&, reference>));
BOOST_MPL_ASSERT((boost::is_same<T const&, const_reference>));
BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
// iterator
boost::function_requires<boost::InputIteratorConcept<iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, iterator_value_type>));
BOOST_MPL_ASSERT((boost::is_convertible<iterator, const_iterator>));
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
// const_iterator
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, const_iterator_value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
// difference_type
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_integer>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
iterator_difference_type>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>));
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
iterator_difference_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>::value));
// size_type
BOOST_MPL_ASSERT_NOT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_integer>));
BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer);
// size_type can represent any non-negative value type of difference_type
// I'm not sure about either of these tests...
@@ -183,7 +179,7 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_MPL_ASSERT((boost::is_same<value_type, key_type>));
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
}
template <class X, class Key, class T>
@@ -192,8 +188,8 @@ void unordered_map_test(X& r, Key const& k, T const& v)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_MPL_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >));
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
r.insert(std::pair<Key const, T>(k, v));
@@ -312,36 +308,36 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
//boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
test::check_return_type<std::size_t>::equals(hf(k));
BOOST_MPL_ASSERT((boost::is_same<Pred, key_equal>));
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
test::check_return_type<bool>::convertible(eq(k, k));
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<local_iterator_category,
iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_category,
iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>::value));
boost::function_requires<
boost::InputIteratorConcept<const_local_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
X(10, hf, eq);
X a(10, hf, eq);
+20 -16
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -17,7 +18,7 @@
namespace constructor_tests {
test::seed_t seed(356730);
test::seed_t initialize_seed(356730);
template <class T>
void constructor_tests1(T*,
@@ -317,7 +318,7 @@ void constructor_tests2(T*,
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::cerr<<"Initializer list construct 1\n";
@@ -401,24 +402,28 @@ void map_constructor_test(T* = 0,
test::check_equivalent_keys(x);
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(constructor_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
@@ -428,10 +433,10 @@ UNORDERED_TEST(constructor_tests2,
)
UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
((test_map_std_alloc)(test_map)(test_multimap))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -442,8 +447,7 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
+7 -6
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -15,7 +16,7 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
test::seed_t seed(9063);
test::seed_t initialize_seed(9063);
namespace copy_tests
{
@@ -154,16 +155,16 @@ void copy_construct_tests2(T* ptr,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
+2 -1
View File
@@ -6,9 +6,10 @@
#define BOOST_UNORDERED_DEPRECATED_EQUALITY
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
+10 -2
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
@@ -149,6 +150,14 @@ namespace equality_tests
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
);
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
@@ -167,7 +176,6 @@ namespace equality_tests
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+2 -1
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
#include <map>
+4 -3
View File
@@ -7,8 +7,9 @@
// hairy with several tricky edge cases - so explicitly test each one.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include <set>
@@ -52,10 +53,10 @@ struct collision2_hash
typedef boost::unordered_multimap<int, int,
collision_hash, std::equal_to<int>,
test::allocator<std::pair<int const, int> > > collide_map;
test::allocator1<std::pair<int const, int> > > collide_map;
typedef boost::unordered_multimap<int, int,
collision2_hash, std::equal_to<int>,
test::allocator<std::pair<int const, int> > > collide_map2;
test::allocator2<std::pair<int const, int> > > collide_map2;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
+7 -6
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -20,7 +21,7 @@
namespace erase_tests
{
test::seed_t seed(85638);
test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*,
@@ -195,16 +196,16 @@ void erase_tests1(Container*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+7 -6
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -16,7 +17,7 @@
namespace find_tests
{
test::seed_t seed(78937);
test::seed_t initialize_seed(78937);
template <class X>
void find_tests1(X*, test::random_generator generator = test::default_generator)
@@ -141,16 +142,16 @@ void find_compatible_keys_test(X*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+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; };
+32 -27
View File
@@ -4,36 +4,36 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <utility>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <utility>
namespace x
{
struct D { boost::unordered_map<D, D> x; };
}
namespace test
namespace incomplete_test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T>
struct malloc_allocator;
template <class T> struct allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > map;
allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > multimap;
allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
malloc_allocator<value> > set;
allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
malloc_allocator<value> > multiset;
allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
@@ -48,12 +48,17 @@ namespace test
bool operator()(T const&, T const&) const { return true; }
};
}
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T>
struct allocator : std::allocator<T> {
allocator() {}
#include "../helpers/allocator.hpp"
template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
@@ -61,19 +66,19 @@ namespace test
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
malloc_allocator<std::pair<struct1 const, struct1> > > x;
allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
malloc_allocator<std::pair<struct2 const, struct2> > > x;
allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
malloc_allocator<struct3> > x;
allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
malloc_allocator<struct4> > x;
allocator<struct4> > x;
};
// Now define the value type.
@@ -82,15 +87,15 @@ namespace test
// Create some instances.
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
test::struct4 c4;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
@@ -112,7 +117,7 @@ namespace test
void use_types()
{
test::value x;
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
@@ -144,5 +149,5 @@ int main() {
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
test::use_types();
incomplete_test::use_types();
}
+2 -1
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <iostream>
+26 -19
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -20,7 +21,7 @@
namespace insert_tests {
test::seed_t seed(243432);
test::seed_t initialize_seed(243432);
template <class X>
void unique_insert_tests1(X*,
@@ -409,43 +410,50 @@ void map_insert_range_test2(X*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(unique_insert_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_insert_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(insert_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
UNORDERED_TEST(unique_emplace_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_emplace_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
#endif
@@ -456,17 +464,16 @@ UNORDERED_TEST(map_tests,
)
UNORDERED_TEST(map_insert_range_test1,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
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,
+3 -2
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/limits.hpp>
#include "../helpers/random_values.hpp"
@@ -19,7 +20,7 @@
namespace load_factor_tests
{
test::seed_t seed(783656);
test::seed_t initialize_seed(783656);
template <class X>
void set_load_factor_tests(X* = 0)
+16 -10
View File
@@ -3,10 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include "../objects/test.hpp"
template <class Tp>
@@ -41,17 +41,23 @@ void test_simple_allocator()
typedef boost::unordered::detail::allocator_traits<
SimpleAllocator<T> > traits;
BOOST_MPL_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >::value));
BOOST_MPL_ASSERT((boost::is_same<typename traits::value_type, T>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
BOOST_MPL_ASSERT((boost::is_same<typename traits::pointer, T* >));
BOOST_MPL_ASSERT((boost::is_same<typename traits::const_pointer, T const*>));
//BOOST_MPL_ASSERT((boost::is_same<typename traits::void_pointer, void* >));
//BOOST_MPL_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T* >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_pointer, T const*>::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void* >::value));
//BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>::value));
BOOST_MPL_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type, std::size_t>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+50 -20
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -21,7 +22,12 @@
namespace move_tests
{
test::seed_t seed(98624);
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template<class T>
T empty(T*) {
@@ -95,7 +101,7 @@ namespace move_tests
test::object_count count;
T y;
y = create(v, count);
#if defined(BOOST_HAS_NRVO)
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
@@ -156,12 +162,12 @@ namespace move_tests
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 50 : 25));
(test::is_set<T>::value ? 25 : 50));
BOOST_TEST(count.instances == test::global_object_count.instances);
#else
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 100 : 50));
(test::is_set<T>::value ? 50 : 100));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
@@ -195,7 +201,10 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -210,7 +219,9 @@ namespace move_tests
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
#endif
@@ -219,7 +230,10 @@ namespace move_tests
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -240,14 +254,19 @@ namespace move_tests
test::object_count count = test::global_object_count;
y = boost::move(x);
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -272,7 +291,9 @@ namespace move_tests
test::object_count count2 = test::global_object_count;
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move)
{
BOOST_TEST(count1.instances ==
test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
@@ -283,7 +304,10 @@ namespace move_tests
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (allocator_type::is_propagate_on_move) {
if (BOOST_UNORDERED_TEST_MOVING ?
(bool) allocator_type::is_propagate_on_move :
(bool) allocator_type::is_propagate_on_assign)
{
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
else {
@@ -292,18 +316,22 @@ namespace move_tests
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -343,12 +371,14 @@ boost::unordered_multimap<test::object, test::object,
using test::generate_collisions;
UNORDERED_TEST(move_construct_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
)
)
UNORDERED_TEST(move_assign_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
(test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
+78 -2
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
@@ -14,7 +15,7 @@
namespace rehash_tests
{
test::seed_t seed(2974);
test::seed_t initialize_seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
@@ -99,6 +100,75 @@ void rehash_test1(X* = 0,
tracker.compare(x);
}
template <class X>
void reserve_test1(X* = 0,
test::random_generator generator = test::default_generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 1; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
// For the current standard this should reserve i+1, I've
// submitted a defect report and will assume it's a defect
// for now.
x.reserve(i);
// Insert an element before the range insert, otherwise there are
// no iterators to invalidate in the range insert, and it can
// rehash.
typename test::random_values<X>::iterator it = v.begin();
x.insert(*it);
++it;
std::size_t bucket_count = x.bucket_count();
x.insert(it, v.end());
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
template <class X>
void reserve_test2(X* = 0,
test::random_generator generator = test::default_generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int i = 0; i < 2000; i += i < 50 ? 1 : 13)
{
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
x.reserve(i);
std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
{
x.insert(*it);
}
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
@@ -116,6 +186,12 @@ UNORDERED_TEST(rehash_empty_test3,
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
}
+2 -1
View File
@@ -6,9 +6,10 @@
// This test checks the runtime requirements of containers.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <cstdlib>
#include <algorithm>
+17 -11
View File
@@ -4,12 +4,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/config.hpp>
#include <algorithm>
#include <iterator>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -24,7 +25,7 @@
namespace swap_tests
{
test::seed_t seed(783472);
test::seed_t initialize_seed(783472);
template <class X>
void swap_test_impl(X& x1, X& x2)
@@ -147,18 +148,22 @@ void swap_tests2(X* ptr = 0,
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -208,6 +213,7 @@ UNORDERED_AUTO_TEST(check_traits)
}
UNORDERED_TEST(swap_tests1, (
(test_map_std_alloc)
(test_set)(test_multiset)(test_map)(test_multimap)
(test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
(test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
+7 -6
View File
@@ -1,12 +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"
namespace unnecessary_copy_tests
@@ -243,9 +245,8 @@ namespace unnecessary_copy_tests
// the existing element.
reset();
x.emplace();
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
COPY_COUNT(1); MOVE_COUNT(0);
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_VARIADIC_TEMPLATES) || \
!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
@@ -405,7 +406,7 @@ namespace unnecessary_copy_tests
boost::make_tuple(boost::ref(b.second)));
COPY_COUNT(0); MOVE_COUNT(0);
#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
reset();
x.emplace(boost::unordered::piecewise_construct,