Merge branch 'feature/expand-calls' into develop

Expanding a lot of the call to the implementation methods. While working
on some recent changes, I felt the call chains in error messages were
too long, this reduces that a little. It also should make debugging a
tad easier and I think it makes the methods a little more informative,
as you can see what they're doing without hunting around the
implementation file. Also reduces the number of symbols when compiling,
although I'm not sure if that will make much of a difference.

Does make the code a little long, and duplicated, but I don't think it's
particularly harmful.
This commit is contained in:
Daniel James
2017-04-23 10:09:28 +01:00
3 changed files with 474 additions and 462 deletions

View File

@ -2708,6 +2708,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Data access // Data access
static node_pointer get_node(c_iterator it) { return it.node_; }
bucket_allocator const& bucket_alloc() const { return allocators_.first(); } bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
node_allocator const& node_alloc() const { return allocators_.second(); } node_allocator const& node_alloc() const { return allocators_.second(); }
@ -2758,12 +2760,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
return policy::to_bucket(bucket_count_, hash_value); return policy::to_bucket(bucket_count_, hash_value);
} }
float load_factor() const
{
BOOST_ASSERT(bucket_count_ != 0);
return static_cast<float>(size_) / static_cast<float>(bucket_count_);
}
std::size_t bucket_size(std::size_t index) const std::size_t bucket_size(std::size_t index) const
{ {
node_pointer n = begin(index); node_pointer n = begin(index);
@ -2782,17 +2778,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Load methods // Load methods
std::size_t max_size() const
{
using namespace std;
// size < mlf_ * count
return boost::unordered::detail::double_to_size(
ceil(static_cast<double>(mlf_) *
static_cast<double>(max_bucket_count()))) -
1;
}
void recalculate_max_load() void recalculate_max_load()
{ {
using namespace std; using namespace std;
@ -2868,26 +2853,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
{ {
} }
////////////////////////////////////////////////////////////////////////
// Initialisation.
void init(table const& x)
{
if (x.size_) {
static_cast<table_impl*>(this)->copy_buckets(x);
}
}
void move_init(table& x)
{
if (node_alloc() == x.node_alloc()) {
move_buckets_from(x);
} else if (x.size_) {
// TODO: Could pick new bucket size?
static_cast<table_impl*>(this)->move_buckets(x);
}
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Clear buckets and Create buckets // Clear buckets and Create buckets
// //
@ -3078,17 +3043,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
BOOST_ASSERT(!size_); BOOST_ASSERT(!size_);
} }
void clear()
{
if (!size_)
return;
clear_buckets();
delete_nodes(get_previous_start(), link_pointer());
BOOST_ASSERT(!size_);
}
void destroy_buckets() void destroy_buckets()
{ {
bucket_pointer end = get_bucket(bucket_count_ + 1); bucket_pointer end = get_bucket(bucket_count_ + 1);
@ -3258,13 +3212,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
// Find Node // Find Node
template <typename Key, typename Hash, typename Pred>
node_pointer generic_find_node(
Key const& k, Hash const& hf, Pred const& eq) const
{
return this->find_node_impl(policy::apply_hash(hf, k), k, eq);
}
node_pointer find_node(std::size_t key_hash, const_key_type& k) const node_pointer find_node(std::size_t key_hash, const_key_type& k) const
{ {
return this->find_node_impl(key_hash, k, this->key_eq()); return this->find_node_impl(key_hash, k, this->key_eq());
@ -3393,13 +3340,6 @@ inline void table<Types>::rehash(std::size_t min_buckets)
} }
} }
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) / mlf_)));
}
template <typename Types> template <typename Types>
inline void table<Types>::rehash_impl(std::size_t num_buckets) inline void table<Types>::rehash_impl(std::size_t num_buckets)
{ {
@ -3789,50 +3729,34 @@ struct table_unique : boost::unordered::detail::table<Types>
: table(x, node_allocator_traits::select_on_container_copy_construction( : table(x, node_allocator_traits::select_on_container_copy_construction(
x.node_alloc())) x.node_alloc()))
{ {
this->init(x); if (x.size_) {
this->copy_buckets(x);
}
} }
table_unique(table_unique const& x, node_allocator const& a) : table(x, a) table_unique(table_unique const& x, node_allocator const& a) : table(x, a)
{ {
this->init(x); if (x.size_) {
this->copy_buckets(x);
}
} }
table_unique(table_unique& x, boost::unordered::detail::move_tag m) table_unique(table_unique& x, boost::unordered::detail::move_tag m)
: table(x, m) : table(x, m)
{ {
// The move is done in the base class.
} }
table_unique(table_unique& x, node_allocator const& a, table_unique(table_unique& x, node_allocator const& a,
boost::unordered::detail::move_tag m) boost::unordered::detail::move_tag m)
: table(x, a, m) : table(x, a, m)
{ {
this->move_init(x); if (this->node_alloc() == x.node_alloc()) {
} this->move_buckets_from(x);
} else if (x.size_) {
// Accessors // TODO: Could pick new bucket size?
this->move_buckets(x);
std::size_t count(const_key_type& k) const
{
return this->find_node(k) ? 1 : 0;
}
value_type& at(const_key_type& k) const
{
if (this->size_) {
node_pointer n = this->find_node(k);
if (n)
return n->value();
} }
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
std::pair<iterator, iterator> equal_range(const_key_type& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(
iterator(n), iterator(n ? node_algo::next_node(n) : n));
} }
// equals // equals
@ -3890,81 +3814,6 @@ struct table_unique : boost::unordered::detail::table<Types>
return this->add_node(b.release(), key_hash); return this->add_node(b.release(), key_hash);
} }
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(
c_iterator,
boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
#else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
#endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_CXX11_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),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_hint_impl(hint,
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_hint_impl(hint, extractor::extract(args.a0, args.a1),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
{
return emplace_impl(extractor::extract(args.a0), args);
}
template <typename A0>
iterator emplace_hint(c_iterator hint,
boost::unordered::detail::emplace_args1<A0> const& args)
{
return emplace_hint_impl(hint, extractor::extract(args.a0), args);
}
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE> template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint_impl( iterator emplace_hint_impl(
c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS) c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
@ -4188,12 +4037,6 @@ struct table_unique : boost::unordered::detail::table<Types>
// if hash function throws, or inserting > 1 element, basic exception // if hash function throws, or inserting > 1 element, basic exception
// safety strong otherwise // safety strong otherwise
template <class InputIt> void insert_range(InputIt i, InputIt j)
{
if (i != j)
return insert_range_impl(extractor::extract(*i), i, j);
}
template <class InputIt> template <class InputIt>
void insert_range_impl(const_key_type& k, InputIt i, InputIt j) void insert_range_impl(const_key_type& k, InputIt i, InputIt j)
{ {
@ -4298,22 +4141,6 @@ struct table_unique : boost::unordered::detail::table<Types>
return 1; return 1;
} }
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
node_pointer next = node_algo::next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2)
return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
void erase_nodes(node_pointer i, node_pointer j) void erase_nodes(node_pointer i, node_pointer j)
{ {
std::size_t bucket_index = this->hash_to_bucket(i->hash_); std::size_t bucket_index = this->hash_to_bucket(i->hash_);
@ -4610,39 +4437,34 @@ struct table_equiv : boost::unordered::detail::table<Types>
: table(x, node_allocator_traits::select_on_container_copy_construction( : table(x, node_allocator_traits::select_on_container_copy_construction(
x.node_alloc())) x.node_alloc()))
{ {
this->init(x); if (x.size_) {
copy_buckets(x);
}
} }
table_equiv(table_equiv const& x, node_allocator const& a) : table(x, a) table_equiv(table_equiv const& x, node_allocator const& a) : table(x, a)
{ {
this->init(x); if (x.size_) {
copy_buckets(x);
}
} }
table_equiv(table_equiv& x, boost::unordered::detail::move_tag m) table_equiv(table_equiv& x, boost::unordered::detail::move_tag m)
: table(x, m) : table(x, m)
{ {
// The move is done in the base class.
} }
table_equiv(table_equiv& x, node_allocator const& a, table_equiv(table_equiv& x, node_allocator const& a,
boost::unordered::detail::move_tag m) boost::unordered::detail::move_tag m)
: table(x, a, m) : table(x, a, m)
{ {
this->move_init(x); if (this->node_alloc() == x.node_alloc()) {
} this->move_buckets_from(x);
} else if (x.size_) {
// Accessors // TODO: Could pick new bucket size?
this->move_buckets(x);
std::size_t count(const_key_type& k) const }
{
node_pointer n = this->find_node(k);
return n ? node_algo::count(n, this) : 0;
}
std::pair<iterator, iterator> equal_range(const_key_type& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(
iterator(n), iterator(n ? node_algo::next_group(n, this) : n));
} }
// Equality // Equality
@ -4786,56 +4608,6 @@ struct table_equiv : boost::unordered::detail::table<Types>
return n; return n;
} }
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(
c_iterator,
boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
#else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
#endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_impl(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_hint_impl(
hint, boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
iterator emplace_impl(node_pointer n) iterator emplace_impl(node_pointer n)
{ {
node_tmp a(n, this->node_alloc()); node_tmp a(n, this->node_alloc());
@ -5005,22 +4777,6 @@ struct table_equiv : boost::unordered::detail::table<Types>
return deleted_count; return deleted_count;
} }
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
node_pointer next = node_algo::next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2)
return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
link_pointer erase_nodes(node_pointer i, node_pointer j) link_pointer erase_nodes(node_pointer i, node_pointer j)
{ {
std::size_t bucket_index = this->hash_to_bucket(i->hash_); std::size_t bucket_index = this->hash_to_bucket(i->hash_);

View File

@ -55,6 +55,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
typedef boost::unordered::detail::map<A, K, T, H, P> types; typedef boost::unordered::detail::map<A, K, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits; typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@ -220,7 +222,9 @@ template <class K, class T, class H, class P, class A> class unordered_map
template <class... Args> template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args) std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace(boost::forward<Args>(args)...); return table_.emplace_impl(
table::extractor::extract(boost::forward<Args>(args)...),
boost::forward<Args>(args)...);
} }
#else #else
@ -244,25 +248,33 @@ template <class K, class T, class H, class P, class A> class unordered_map
template <typename A0> template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0) std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0))); table::extractor::extract(boost::forward<A0>(a0)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
std::pair<iterator, bool> emplace( std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1))); table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace( std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1), table::extractor::extract(
boost::forward<A2>(a2))); boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
} }
#endif #endif
@ -272,7 +284,9 @@ template <class K, class T, class H, class P, class A> class unordered_map
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace_hint(hint, boost::forward<Args>(args)...); return table_.emplace_hint_impl(hint,
table::extractor::extract(boost::forward<Args>(args)...),
boost::forward<Args>(args)...);
} }
#else #else
@ -292,28 +306,33 @@ template <class K, class T, class H, class P, class A> class unordered_map
template <typename A0> template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(hint,
hint, boost::unordered::detail::create_emplace_args( table::extractor::extract(boost::forward<A0>(a0)),
boost::forward<A0>(a0))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace_hint( iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1))); boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1), boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::forward<A2>(a2))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
} }
#endif #endif
@ -325,21 +344,32 @@ template <class K, class T, class H, class P, class A> class unordered_map
std::pair<iterator, bool> emplace( \ std::pair<iterator, bool> emplace( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace(boost::unordered::detail::create_emplace_args( \ return table_.emplace_impl( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ table::extractor::extract( \
boost::forward<A0>(a0), boost::forward<A1>(a1)), \
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)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \ iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace_hint( \ return table_.emplace_hint_impl( \
hint, boost::unordered::detail::create_emplace_args( \ hint, table::extractor::extract( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} }
BOOST_PP_REPEAT_FROM_TO( BOOST_UNORDERED_EMPLACE(1, 4, _)
4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_EMPLACE, _) BOOST_UNORDERED_EMPLACE(1, 5, _)
BOOST_UNORDERED_EMPLACE(1, 6, _)
BOOST_UNORDERED_EMPLACE(1, 7, _)
BOOST_UNORDERED_EMPLACE(1, 8, _)
BOOST_UNORDERED_EMPLACE(1, 9, _)
BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE #undef BOOST_UNORDERED_EMPLACE
@ -625,8 +655,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
n, BOOST_UNORDERED_CALL_FORWARD, a))); \ n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} }
BOOST_PP_REPEAT_FROM_TO( BOOST_PP_REPEAT_FROM_TO(4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_TRY_EMPLACE, _) BOOST_UNORDERED_TRY_EMPLACE, _)
#undef BOOST_UNORDERED_TRY_EMPLACE #undef BOOST_UNORDERED_TRY_EMPLACE
@ -808,6 +838,8 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
typedef boost::unordered::detail::multimap<A, K, T, H, P> types; typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits; typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@ -972,7 +1004,9 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args) template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace(boost::forward<Args>(args)...); return iterator(table_.emplace_impl(
boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(), boost::forward<Args>(args)...)));
} }
#else #else
@ -994,24 +1028,33 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0) template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0))); boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)))));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1))); boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)))));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace( iterator emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1), boost::unordered::detail::func::construct_node_from_args(
boost::forward<A2>(a2))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)))));
} }
#endif #endif
@ -1021,7 +1064,9 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace_hint(hint, boost::forward<Args>(args)...); return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(), boost::forward<Args>(args)...)));
} }
#else #else
@ -1041,27 +1086,34 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <typename A0> template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)))));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace_hint( iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0), boost::forward<A1>(a1))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)))));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0), boost::forward<A1>(a1), table_.node_alloc(),
boost::forward<A2>(a2))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)))));
} }
#endif #endif
@ -1072,21 +1124,33 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace(boost::unordered::detail::create_emplace_args( \ return iterator(table_.emplace_impl( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::unordered::detail::func::construct_node_from_args( \
table_.node_alloc(), \
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)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \ iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace_hint( \ return iterator(table_.emplace_hint_impl( \
hint, boost::unordered::detail::create_emplace_args( \ hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::unordered::detail::func::construct_node_from_args( \
table_.node_alloc(), \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
} }
BOOST_PP_REPEAT_FROM_TO( BOOST_UNORDERED_EMPLACE(1, 4, _)
4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_EMPLACE, _) BOOST_UNORDERED_EMPLACE(1, 5, _)
BOOST_UNORDERED_EMPLACE(1, 6, _)
BOOST_UNORDERED_EMPLACE(1, 7, _)
BOOST_UNORDERED_EMPLACE(1, 8, _)
BOOST_UNORDERED_EMPLACE(1, 9, _)
BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE #undef BOOST_UNORDERED_EMPLACE
@ -1307,7 +1371,7 @@ unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
const hasher& hf, const key_equal& eql, const allocator_type& a) const hasher& hf, const key_equal& eql, const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1347,7 +1411,7 @@ unordered_map<K, T, H, P, A>::unordered_map(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, eql, a) hf, eql, a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1373,7 +1437,7 @@ unordered_map<K, T, H, P, A>::unordered_map(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(), : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a) key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1383,7 +1447,7 @@ unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
: table_( : table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a) boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -1396,7 +1460,7 @@ unordered_map<K, T, H, P, A>::unordered_map(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hasher(), key_equal(), a) hasher(), key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1407,7 +1471,7 @@ unordered_map<K, T, H, P, A>::unordered_map(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a) hf, key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1423,8 +1487,8 @@ template <class K, class T, class H, class P, class A>
unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=( unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.clear(); this->clear();
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
return *this; return *this;
} }
@ -1435,7 +1499,13 @@ unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=(
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
std::size_t unordered_map<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT std::size_t unordered_map<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT
{ {
return table_.max_size(); using namespace std;
// size <= mlf_ * count
return boost::unordered::detail::double_to_size(
ceil(static_cast<double>(table_.mlf_) *
static_cast<double>(table_.max_bucket_count()))) -
1;
} }
// modifiers // modifiers
@ -1444,7 +1514,10 @@ template <class K, class T, class H, class P, class A>
template <class InputIt> template <class InputIt>
void unordered_map<K, T, H, P, A>::insert(InputIt first, InputIt last) void unordered_map<K, T, H, P, A>::insert(InputIt first, InputIt last)
{ {
table_.insert_range(first, last); if (first != last) {
table_.insert_range_impl(
table::extractor::extract(*first), first, last);
}
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -1452,7 +1525,7 @@ template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::insert( void unordered_map<K, T, H, P, A>::insert(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1460,14 +1533,22 @@ template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(iterator position) unordered_map<K, T, H, P, A>::erase(iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator position) unordered_map<K, T, H, P, A>::erase(const_iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1481,7 +1562,11 @@ template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator first, const_iterator last) unordered_map<K, T, H, P, A>::erase(const_iterator first, const_iterator last)
{ {
return table_.erase_range(first, last); node_pointer last_node = table::get_node(last);
if (first == last)
return iterator(last_node);
table_.erase_nodes(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1497,7 +1582,10 @@ void unordered_map<K, T, H, P, A>::swap(unordered_map& other)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::clear() BOOST_NOEXCEPT void unordered_map<K, T, H, P, A>::clear() BOOST_NOEXCEPT
{ {
table_.clear(); if (table_.size_) {
table_.clear_buckets();
table_.delete_nodes(table_.get_previous_start(), link_pointer());
}
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1576,7 +1664,8 @@ typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k, unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) CompatibleHash const& hash, CompatiblePredicate const& eq)
{ {
return iterator(table_.generic_find_node(k, hash, eq)); return iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1585,14 +1674,15 @@ typename unordered_map<K, T, H, P, A>::const_iterator
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k, unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator(table_.generic_find_node(k, hash, eq)); return const_iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::size_type typename unordered_map<K, T, H, P, A>::size_type
unordered_map<K, T, H, P, A>::count(const key_type& k) const unordered_map<K, T, H, P, A>::count(const key_type& k) const
{ {
return table_.count(k); return table_.find_node(k) ? 1 : 0;
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1600,7 +1690,9 @@ std::pair<typename unordered_map<K, T, H, P, A>::iterator,
typename unordered_map<K, T, H, P, A>::iterator> typename unordered_map<K, T, H, P, A>::iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) unordered_map<K, T, H, P, A>::equal_range(const key_type& k)
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(
iterator(n), iterator(n ? table::node_algo::next_node(n) : n));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1608,7 +1700,9 @@ std::pair<typename unordered_map<K, T, H, P, A>::const_iterator,
typename unordered_map<K, T, H, P, A>::const_iterator> typename unordered_map<K, T, H, P, A>::const_iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(const_iterator(n),
const_iterator(n ? table::node_algo::next_node(n) : n));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1629,14 +1723,28 @@ template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::mapped_type& typename unordered_map<K, T, H, P, A>::mapped_type&
unordered_map<K, T, H, P, A>::at(const key_type& k) unordered_map<K, T, H, P, A>::at(const key_type& k)
{ {
return table_.at(k).second; if (table_.size_) {
node_pointer n = table_.find_node(k);
if (n)
return n->value().second;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::mapped_type const& typename unordered_map<K, T, H, P, A>::mapped_type const&
unordered_map<K, T, H, P, A>::at(const key_type& k) const unordered_map<K, T, H, P, A>::at(const key_type& k) const
{ {
return table_.at(k).second; if (table_.size_) {
node_pointer n = table_.find_node(k);
if (n)
return n->value().second;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1651,7 +1759,9 @@ unordered_map<K, T, H, P, A>::bucket_size(size_type n) const
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
return table_.load_factor(); BOOST_ASSERT(table_.bucket_count_ != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1669,7 +1779,8 @@ void unordered_map<K, T, H, P, A>::rehash(size_type n)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::reserve(size_type n) void unordered_map<K, T, H, P, A>::reserve(size_type n)
{ {
table_.reserve(n); table_.rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1735,7 +1846,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
const allocator_type& a) const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1776,7 +1887,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, eql, a) hf, eql, a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1802,7 +1913,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(), : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a) key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1812,7 +1923,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
: table_( : table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a) boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -1825,7 +1936,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hasher(), key_equal(), a) hasher(), key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1836,7 +1947,7 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a) hf, key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1852,8 +1963,8 @@ template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>& unordered_multimap<K, T, H, P, A>::operator=( unordered_multimap<K, T, H, P, A>& unordered_multimap<K, T, H, P, A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.clear(); this->clear();
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
return *this; return *this;
} }
@ -1864,7 +1975,13 @@ unordered_multimap<K, T, H, P, A>& unordered_multimap<K, T, H, P, A>::operator=(
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
std::size_t unordered_multimap<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT std::size_t unordered_multimap<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT
{ {
return table_.max_size(); using namespace std;
// size <= mlf_ * count
return boost::unordered::detail::double_to_size(
ceil(static_cast<double>(table_.mlf_) *
static_cast<double>(table_.max_bucket_count()))) -
1;
} }
// modifiers // modifiers
@ -1881,7 +1998,7 @@ template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::insert( void unordered_multimap<K, T, H, P, A>::insert(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1889,14 +2006,22 @@ template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::iterator typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(iterator position) unordered_multimap<K, T, H, P, A>::erase(iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::iterator typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(const_iterator position) unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1911,7 +2036,11 @@ typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase( unordered_multimap<K, T, H, P, A>::erase(
const_iterator first, const_iterator last) const_iterator first, const_iterator last)
{ {
return table_.erase_range(first, last); node_pointer last_node = table::get_node(last);
if (first == last)
return iterator(last_node);
table_.erase_nodes(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1927,7 +2056,10 @@ void unordered_multimap<K, T, H, P, A>::swap(unordered_multimap& other)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::clear() BOOST_NOEXCEPT void unordered_multimap<K, T, H, P, A>::clear() BOOST_NOEXCEPT
{ {
table_.clear(); if (table_.size_) {
table_.clear_buckets();
table_.delete_nodes(table_.get_previous_start(), link_pointer());
}
} }
// observers // observers
@ -2014,7 +2146,8 @@ typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k, unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) CompatibleHash const& hash, CompatiblePredicate const& eq)
{ {
return iterator(table_.generic_find_node(k, hash, eq)); return iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -2023,14 +2156,16 @@ typename unordered_multimap<K, T, H, P, A>::const_iterator
unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k, unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator(table_.generic_find_node(k, hash, eq)); return const_iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::size_type typename unordered_multimap<K, T, H, P, A>::size_type
unordered_multimap<K, T, H, P, A>::count(const key_type& k) const unordered_multimap<K, T, H, P, A>::count(const key_type& k) const
{ {
return table_.count(k); node_pointer n = table_.find_node(k);
return n ? table::node_algo::count(n, &table_) : 0;
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -2038,7 +2173,9 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::iterator,
typename unordered_multimap<K, T, H, P, A>::iterator> typename unordered_multimap<K, T, H, P, A>::iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k)
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(iterator(n),
iterator(n ? table::node_algo::next_group(n, &table_) : n));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -2046,7 +2183,9 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::const_iterator,
typename unordered_multimap<K, T, H, P, A>::const_iterator> typename unordered_multimap<K, T, H, P, A>::const_iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(const_iterator(n),
const_iterator(n ? table::node_algo::next_group(n, &table_) : n));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -2061,7 +2200,9 @@ unordered_multimap<K, T, H, P, A>::bucket_size(size_type n) const
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
return table_.load_factor(); BOOST_ASSERT(table_.bucket_count_ != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -2079,7 +2220,8 @@ void unordered_multimap<K, T, H, P, A>::rehash(size_type n)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::reserve(size_type n) void unordered_multimap<K, T, H, P, A>::reserve(size_type n)
{ {
table_.reserve(n); table_.rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>

View File

@ -53,6 +53,8 @@ template <class T, class H, class P, class A> class unordered_set
typedef boost::unordered::detail::set<A, T, H, P> types; typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits; typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@ -218,7 +220,9 @@ template <class T, class H, class P, class A> class unordered_set
template <class... Args> template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args) std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace(boost::forward<Args>(args)...); return table_.emplace_impl(
table::extractor::extract(boost::forward<Args>(args)...),
boost::forward<Args>(args)...);
} }
#else #else
@ -242,25 +246,33 @@ template <class T, class H, class P, class A> class unordered_set
template <typename A0> template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0) std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0))); table::extractor::extract(boost::forward<A0>(a0)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
std::pair<iterator, bool> emplace( std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1))); table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace( std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1), table::extractor::extract(
boost::forward<A2>(a2))); boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
} }
#endif #endif
@ -270,7 +282,9 @@ template <class T, class H, class P, class A> class unordered_set
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace_hint(hint, boost::forward<Args>(args)...); return table_.emplace_hint_impl(hint,
table::extractor::extract(boost::forward<Args>(args)...),
boost::forward<Args>(args)...);
} }
#else #else
@ -290,28 +304,33 @@ template <class T, class H, class P, class A> class unordered_set
template <typename A0> template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(hint,
hint, boost::unordered::detail::create_emplace_args( table::extractor::extract(boost::forward<A0>(a0)),
boost::forward<A0>(a0))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace_hint( iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1))); boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace_hint( return table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, table::extractor::extract(
boost::forward<A0>(a0), boost::forward<A1>(a1), boost::forward<A0>(a0), boost::forward<A1>(a1)),
boost::forward<A2>(a2))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
} }
#endif #endif
@ -323,20 +342,31 @@ template <class T, class H, class P, class A> class unordered_set
std::pair<iterator, bool> emplace( \ std::pair<iterator, bool> emplace( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace(boost::unordered::detail::create_emplace_args( \ return table_.emplace_impl( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ table::extractor::extract( \
boost::forward<A0>(a0), boost::forward<A1>(a1)), \
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)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \ iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace_hint( \ return table_.emplace_hint_impl( \
hint, boost::unordered::detail::create_emplace_args( \ hint, table::extractor::extract( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} }
BOOST_PP_REPEAT_FROM_TO(4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_EMPLACE(1, 4, _)
BOOST_UNORDERED_EMPLACE(1, 5, _)
BOOST_UNORDERED_EMPLACE(1, 6, _)
BOOST_UNORDERED_EMPLACE(1, 7, _)
BOOST_UNORDERED_EMPLACE(1, 8, _)
BOOST_UNORDERED_EMPLACE(1, 9, _)
BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
BOOST_UNORDERED_EMPLACE, _) BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE #undef BOOST_UNORDERED_EMPLACE
@ -534,6 +564,8 @@ template <class T, class H, class P, class A> class unordered_multiset
typedef boost::unordered::detail::multiset<A, T, H, P> types; typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits; typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@ -695,9 +727,12 @@ template <class T, class H, class P, class A> class unordered_multiset
// emplace // emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args) template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace(boost::forward<Args>(args)...); return iterator(table_.emplace_impl(
boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(), boost::forward<Args>(args)...)));
} }
#else #else
@ -719,24 +754,33 @@ template <class T, class H, class P, class A> class unordered_multiset
template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0) template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0))); boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)))));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1))); boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)))));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace( iterator emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace(boost::unordered::detail::create_emplace_args( return iterator(table_.emplace_impl(
boost::forward<A0>(a0), boost::forward<A1>(a1), boost::unordered::detail::func::construct_node_from_args(
boost::forward<A2>(a2))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)))));
} }
#endif #endif
@ -746,7 +790,9 @@ template <class T, class H, class P, class A> class unordered_multiset
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ {
return table_.emplace_hint(hint, boost::forward<Args>(args)...); return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::func::construct_node_from_args(
table_.node_alloc(), boost::forward<Args>(args)...)));
} }
#else #else
@ -766,28 +812,34 @@ template <class T, class H, class P, class A> class unordered_multiset
template <typename A0> template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)))));
} }
template <typename A0, typename A1> template <typename A0, typename A1>
iterator emplace_hint( iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0), boost::forward<A1>(a1))); table_.node_alloc(),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)))));
} }
template <typename A0, typename A1, typename A2> template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
return table_.emplace_hint( return iterator(table_.emplace_hint_impl(
hint, boost::unordered::detail::create_emplace_args( hint, boost::unordered::detail::func::construct_node_from_args(
boost::forward<A0>(a0), boost::forward<A1>(a1), table_.node_alloc(),
boost::forward<A2>(a2))); boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)))));
} }
#endif #endif
@ -798,20 +850,32 @@ template <class T, class H, class P, class A> class unordered_multiset
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace(boost::unordered::detail::create_emplace_args( \ return iterator(table_.emplace_impl( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::unordered::detail::func::construct_node_from_args( \
table_.node_alloc(), \
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)> \ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \ iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \ { \
return table_.emplace_hint( \ return iterator(table_.emplace_hint_impl( \
hint, boost::unordered::detail::create_emplace_args( \ hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ boost::unordered::detail::func::construct_node_from_args( \
table_.node_alloc(), \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
} }
BOOST_PP_REPEAT_FROM_TO(4, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_EMPLACE(1, 4, _)
BOOST_UNORDERED_EMPLACE(1, 5, _)
BOOST_UNORDERED_EMPLACE(1, 6, _)
BOOST_UNORDERED_EMPLACE(1, 7, _)
BOOST_UNORDERED_EMPLACE(1, 8, _)
BOOST_UNORDERED_EMPLACE(1, 9, _)
BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
BOOST_UNORDERED_EMPLACE, _) BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE #undef BOOST_UNORDERED_EMPLACE
@ -1006,7 +1070,7 @@ unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
const hasher& hf, const key_equal& eql, const allocator_type& a) const hasher& hf, const key_equal& eql, const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1046,7 +1110,7 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, eql, a) hf, eql, a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1071,7 +1135,7 @@ unordered_set<T, H, P, A>::unordered_set(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(), : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a) key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1081,7 +1145,7 @@ unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
: table_( : table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a) boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -1093,7 +1157,7 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hasher(), key_equal(), a) hasher(), key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1103,7 +1167,7 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a) hf, key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1119,8 +1183,8 @@ template <class T, class H, class P, class A>
unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=( unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.clear(); this->clear();
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
return *this; return *this;
} }
@ -1131,7 +1195,13 @@ unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
std::size_t unordered_set<T, H, P, A>::max_size() const BOOST_NOEXCEPT std::size_t unordered_set<T, H, P, A>::max_size() const BOOST_NOEXCEPT
{ {
return table_.max_size(); using namespace std;
// size < mlf_ * count
return boost::unordered::detail::double_to_size(
ceil(static_cast<double>(table_.mlf_) *
static_cast<double>(table_.max_bucket_count()))) -
1;
} }
// modifiers // modifiers
@ -1140,14 +1210,17 @@ template <class T, class H, class P, class A>
template <class InputIt> template <class InputIt>
void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last) void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
{ {
table_.insert_range(first, last); if (first != last) {
table_.insert_range_impl(
table::extractor::extract(*first), first, last);
}
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::insert(std::initializer_list<value_type> list) void unordered_set<T, H, P, A>::insert(std::initializer_list<value_type> list)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1155,7 +1228,11 @@ template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase( typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
const_iterator position) const_iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1169,7 +1246,11 @@ template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase( typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
const_iterator first, const_iterator last) const_iterator first, const_iterator last)
{ {
return table_.erase_range(first, last); node_pointer last_node = table::get_node(last);
if (first == last)
return iterator(last_node);
table_.erase_nodes(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1185,13 +1266,10 @@ void unordered_set<T, H, P, A>::swap(unordered_set& other)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::clear() BOOST_NOEXCEPT void unordered_set<T, H, P, A>::clear() BOOST_NOEXCEPT
{ {
table_.clear(); if (table_.size_) {
} table_.clear_buckets();
table_.delete_nodes(table_.get_previous_start(), link_pointer());
template <class T, class H, class P, class A> }
void unordered_multiset<T, H, P, A>::clear() BOOST_NOEXCEPT
{
table_.clear();
} }
// observers // observers
@ -1263,14 +1341,15 @@ typename unordered_set<T, H, P, A>::const_iterator
unordered_set<T, H, P, A>::find(CompatibleKey const& k, unordered_set<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator(table_.generic_find_node(k, hash, eq)); return const_iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::size_type unordered_set<T, H, P, A>::count( typename unordered_set<T, H, P, A>::size_type unordered_set<T, H, P, A>::count(
const key_type& k) const const key_type& k) const
{ {
return table_.count(k); return table_.find_node(k) ? 1 : 0;
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1278,7 +1357,9 @@ std::pair<typename unordered_set<T, H, P, A>::const_iterator,
typename unordered_set<T, H, P, A>::const_iterator> typename unordered_set<T, H, P, A>::const_iterator>
unordered_set<T, H, P, A>::equal_range(const key_type& k) const unordered_set<T, H, P, A>::equal_range(const key_type& k) const
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(const_iterator(n),
const_iterator(n ? table::node_algo::next_node(n) : n));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1293,7 +1374,9 @@ unordered_set<T, H, P, A>::bucket_size(size_type n) const
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
return table_.load_factor(); BOOST_ASSERT(table_.bucket_count_ != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1311,7 +1394,8 @@ void unordered_set<T, H, P, A>::rehash(size_type n)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::reserve(size_type n) void unordered_set<T, H, P, A>::reserve(size_type n)
{ {
table_.reserve(n); table_.rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1376,7 +1460,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
const allocator_type& a) const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1417,7 +1501,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, eql, a) hf, eql, a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1443,7 +1527,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(), : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a) key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1453,7 +1537,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
: table_( : table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a) boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{ {
table_.insert_range(f, l); this->insert(f, l);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -1466,7 +1550,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hasher(), key_equal(), a) hasher(), key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1477,7 +1561,7 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
boost::unordered::detail::initial_size(list.begin(), list.end(), n), boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a) hf, key_equal(), a)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1493,8 +1577,8 @@ template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=( unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.clear(); this->clear();
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
return *this; return *this;
} }
@ -1505,7 +1589,13 @@ unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
std::size_t unordered_multiset<T, H, P, A>::max_size() const BOOST_NOEXCEPT std::size_t unordered_multiset<T, H, P, A>::max_size() const BOOST_NOEXCEPT
{ {
return table_.max_size(); using namespace std;
// size < mlf_ * count
return boost::unordered::detail::double_to_size(
ceil(static_cast<double>(table_.mlf_) *
static_cast<double>(table_.max_bucket_count()))) -
1;
} }
// modifiers // modifiers
@ -1522,7 +1612,7 @@ template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::insert( void unordered_multiset<T, H, P, A>::insert(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
{ {
table_.insert_range(list.begin(), list.end()); this->insert(list.begin(), list.end());
} }
#endif #endif
@ -1530,7 +1620,11 @@ template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::iterator typename unordered_multiset<T, H, P, A>::iterator
unordered_multiset<T, H, P, A>::erase(const_iterator position) unordered_multiset<T, H, P, A>::erase(const_iterator position)
{ {
return table_.erase(position); node_pointer node = table::get_node(position);
BOOST_ASSERT(node);
node_pointer next = table::node_algo::next_node(node);
table_.erase_nodes(node, next);
return iterator(next);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1544,7 +1638,11 @@ template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::iterator typename unordered_multiset<T, H, P, A>::iterator
unordered_multiset<T, H, P, A>::erase(const_iterator first, const_iterator last) unordered_multiset<T, H, P, A>::erase(const_iterator first, const_iterator last)
{ {
return table_.erase_range(first, last); node_pointer last_node = table::get_node(last);
if (first == last)
return iterator(last_node);
table_.erase_nodes(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1557,6 +1655,15 @@ void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
table_.swap(other.table_); table_.swap(other.table_);
} }
template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::clear() BOOST_NOEXCEPT
{
if (table_.size_) {
table_.clear_buckets();
table_.delete_nodes(table_.get_previous_start(), link_pointer());
}
}
// observers // observers
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1634,14 +1741,16 @@ typename unordered_multiset<T, H, P, A>::const_iterator
unordered_multiset<T, H, P, A>::find(CompatibleKey const& k, unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator(table_.generic_find_node(k, hash, eq)); return const_iterator(
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::size_type typename unordered_multiset<T, H, P, A>::size_type
unordered_multiset<T, H, P, A>::count(const key_type& k) const unordered_multiset<T, H, P, A>::count(const key_type& k) const
{ {
return table_.count(k); node_pointer n = table_.find_node(k);
return n ? table::node_algo::count(n, &table_) : 0;
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1649,7 +1758,9 @@ std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
typename unordered_multiset<T, H, P, A>::const_iterator> typename unordered_multiset<T, H, P, A>::const_iterator>
unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
{ {
return table_.equal_range(k); node_pointer n = table_.find_node(k);
return std::make_pair(const_iterator(n),
const_iterator(n ? table::node_algo::next_group(n, &table_) : n));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1664,7 +1775,9 @@ unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
return table_.load_factor(); BOOST_ASSERT(table_.bucket_count_ != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1682,7 +1795,8 @@ void unordered_multiset<T, H, P, A>::rehash(size_type n)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::reserve(size_type n) void unordered_multiset<T, H, P, A>::reserve(size_type n)
{ {
table_.reserve(n); table_.rehash(static_cast<std::size_t>(
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>