mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Merge branch 'develop'
This commit is contained in:
@ -14,23 +14,31 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// Some of these includes are required for other detail headers.
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
#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/type_traits/add_lvalue_reference.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <cmath>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
#include <tuple>
|
||||
@ -808,6 +816,18 @@ namespace boost { namespace unordered { namespace detail { namespace func {
|
||||
# endif
|
||||
|
||||
#else
|
||||
template <typename Alloc, typename T>
|
||||
inline void call_construct(Alloc&, T* address)
|
||||
{
|
||||
new ((void*) address) T();
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T, typename A0>
|
||||
inline void call_construct(Alloc&, T* address,
|
||||
BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
new ((void*) address) T(boost::forward<A0>(a0));
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_value_impl(Alloc&, T* x) {
|
||||
@ -1053,74 +1073,182 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
// Node construction
|
||||
|
||||
template <typename Allocator>
|
||||
struct array_constructor
|
||||
template <typename NodeAlloc>
|
||||
struct node_constructor
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
|
||||
typedef typename traits::pointer pointer;
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
typedef typename node_allocator_traits::value_type node;
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
typedef typename node::value_type value_type;
|
||||
|
||||
Allocator& alloc_;
|
||||
pointer ptr_;
|
||||
pointer constructed_;
|
||||
std::size_t length_;
|
||||
node_allocator& alloc_;
|
||||
node_pointer node_;
|
||||
bool node_constructed_;
|
||||
|
||||
array_constructor(Allocator& a)
|
||||
: alloc_(a), ptr_(), constructed_(), length_(0)
|
||||
node_constructor(node_allocator& n) :
|
||||
alloc_(n),
|
||||
node_(),
|
||||
node_constructed_(false)
|
||||
{
|
||||
constructed_ = pointer();
|
||||
ptr_ = pointer();
|
||||
}
|
||||
|
||||
~array_constructor() {
|
||||
if (ptr_) {
|
||||
for(pointer p = ptr_; p != constructed_; ++p) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*p));
|
||||
}
|
||||
~node_constructor();
|
||||
|
||||
traits::deallocate(alloc_, ptr_, length_);
|
||||
}
|
||||
}
|
||||
void create_node();
|
||||
|
||||
template <typename V>
|
||||
void construct(V const& v, std::size_t l)
|
||||
// no throw
|
||||
node_pointer release()
|
||||
{
|
||||
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_) {
|
||||
new ((void*) boost::addressof(*constructed_)) V(v);
|
||||
}
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
pointer release()
|
||||
{
|
||||
pointer p(ptr_);
|
||||
ptr_ = pointer();
|
||||
BOOST_ASSERT(node_ && node_constructed_);
|
||||
node_pointer p = node_;
|
||||
node_ = node_pointer();
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
void reclaim(node_pointer p) {
|
||||
BOOST_ASSERT(!node_);
|
||||
node_ = p;
|
||||
node_constructed_ = true;
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
}
|
||||
|
||||
array_constructor(array_constructor const&);
|
||||
array_constructor& operator=(array_constructor const&);
|
||||
private:
|
||||
node_constructor(node_constructor const&);
|
||||
node_constructor& operator=(node_constructor const&);
|
||||
};
|
||||
|
||||
template <typename Alloc>
|
||||
node_constructor<Alloc>::~node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (node_constructed_) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*node_));
|
||||
}
|
||||
|
||||
node_allocator_traits::deallocate(alloc_, node_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
void node_constructor<Alloc>::create_node()
|
||||
{
|
||||
BOOST_ASSERT(!node_);
|
||||
node_constructed_ = false;
|
||||
|
||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||
|
||||
new ((void*) boost::addressof(*node_)) node();
|
||||
node_->init(node_);
|
||||
node_constructed_ = true;
|
||||
}
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct node_tmp
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
|
||||
NodeAlloc& alloc_;
|
||||
node_pointer node_;
|
||||
|
||||
explicit node_tmp(node_pointer n, NodeAlloc& a):
|
||||
alloc_(a),
|
||||
node_(n)
|
||||
{
|
||||
}
|
||||
|
||||
~node_tmp();
|
||||
|
||||
// no throw
|
||||
node_pointer release()
|
||||
{
|
||||
node_pointer p = node_;
|
||||
node_ = node_pointer();
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Alloc>
|
||||
node_tmp<Alloc>::~node_tmp()
|
||||
{
|
||||
if (node_) {
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*node_));
|
||||
node_allocator_traits::deallocate(alloc_, node_, 1);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace detail { namespace func {
|
||||
|
||||
// Some nicer construct_value functions, might try to
|
||||
// improve implementation later.
|
||||
|
||||
template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
|
||||
construct_value_generic(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
node_constructor<Alloc> a(alloc);
|
||||
a.create_node();
|
||||
construct_value_impl(alloc, a.node_->value_ptr(),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
return a.release();
|
||||
}
|
||||
|
||||
template <typename Alloc, typename U>
|
||||
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
|
||||
construct_value(Alloc& alloc, BOOST_FWD_REF(U) x)
|
||||
{
|
||||
node_constructor<Alloc> a(alloc);
|
||||
a.create_node();
|
||||
boost::unordered::detail::func::call_construct(
|
||||
alloc, a.node_->value_ptr(), boost::forward<U>(x));
|
||||
return a.release();
|
||||
}
|
||||
|
||||
// TODO: When possible, it might be better to use std::pair's
|
||||
// constructor for std::piece_construct with std::tuple.
|
||||
template <typename Alloc, typename Key>
|
||||
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
|
||||
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
|
||||
{
|
||||
node_constructor<Alloc> a(alloc);
|
||||
a.create_node();
|
||||
boost::unordered::detail::func::call_construct(
|
||||
alloc, boost::addressof(a.node_->value_ptr()->first),
|
||||
boost::forward<Key>(k));
|
||||
boost::unordered::detail::func::call_construct(
|
||||
alloc, boost::addressof(a.node_->value_ptr()->second));
|
||||
return a.release();
|
||||
}
|
||||
|
||||
template <typename Alloc, typename Key, typename Mapped>
|
||||
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
|
||||
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
|
||||
{
|
||||
node_constructor<Alloc> a(alloc);
|
||||
a.create_node();
|
||||
boost::unordered::detail::func::call_construct(
|
||||
alloc, boost::addressof(a.node_->value_ptr()->first),
|
||||
boost::forward<Key>(k));
|
||||
boost::unordered::detail::func::call_construct(
|
||||
alloc, boost::addressof(a.node_->value_ptr()->second),
|
||||
boost::forward<Mapped>(m));
|
||||
return a.release();
|
||||
}
|
||||
}}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@ -14,14 +14,6 @@
|
||||
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/unordered/detail/allocate.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
@ -317,124 +309,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Node construction
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct node_constructor
|
||||
{
|
||||
private:
|
||||
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
typedef typename node_allocator_traits::value_type node;
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
typedef typename node::value_type value_type;
|
||||
|
||||
protected:
|
||||
|
||||
node_allocator& alloc_;
|
||||
node_pointer node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
|
||||
public:
|
||||
|
||||
node_constructor(node_allocator& n) :
|
||||
alloc_(n),
|
||||
node_(),
|
||||
node_constructed_(false),
|
||||
value_constructed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
~node_constructor();
|
||||
|
||||
void construct();
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
void construct_with_value2(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(),
|
||||
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
value_type const& value() const {
|
||||
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
// no throw
|
||||
node_pointer release()
|
||||
{
|
||||
BOOST_ASSERT(node_ && node_constructed_);
|
||||
node_pointer p = node_;
|
||||
node_ = node_pointer();
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
node_constructor(node_constructor const&);
|
||||
node_constructor& operator=(node_constructor const&);
|
||||
};
|
||||
|
||||
template <typename Alloc>
|
||||
node_constructor<Alloc>::~node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
}
|
||||
|
||||
if (node_constructed_) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*node_));
|
||||
}
|
||||
|
||||
node_allocator_traits::deallocate(alloc_, node_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
void node_constructor<Alloc>::construct()
|
||||
{
|
||||
if(!node_) {
|
||||
node_constructed_ = false;
|
||||
value_constructed_ = false;
|
||||
|
||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||
|
||||
new ((void*) boost::addressof(*node_)) node();
|
||||
node_->init(node_);
|
||||
node_constructed_ = true;
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_);
|
||||
|
||||
if (value_constructed_)
|
||||
{
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Node Holder
|
||||
@ -442,11 +316,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Temporary store for nodes. Deletes any that aren't used.
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct node_holder : private node_constructor<NodeAlloc>
|
||||
struct node_holder
|
||||
{
|
||||
private:
|
||||
typedef node_constructor<NodeAlloc> base;
|
||||
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
@ -456,13 +328,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename node::link_pointer link_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
|
||||
node_constructor<NodeAlloc> constructor_;
|
||||
node_pointer nodes_;
|
||||
|
||||
public:
|
||||
|
||||
template <typename Table>
|
||||
explicit node_holder(Table& b) :
|
||||
base(b.node_alloc()),
|
||||
constructor_(b.node_alloc()),
|
||||
nodes_()
|
||||
{
|
||||
if (b.size_) {
|
||||
@ -475,61 +348,71 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
~node_holder();
|
||||
|
||||
void node_for_assignment()
|
||||
node_pointer pop_node()
|
||||
{
|
||||
if (!this->node_ && nodes_) {
|
||||
this->node_ = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
this->node_->init(this->node_);
|
||||
this->node_->next_ = link_pointer();
|
||||
|
||||
this->node_constructed_ = true;
|
||||
this->value_constructed_ = true;
|
||||
}
|
||||
node_pointer n = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
n->init(n);
|
||||
n->next_ = link_pointer();
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void assign_impl(T const& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = v;
|
||||
inline node_pointer copy_of(T const& v) {
|
||||
if (nodes_) {
|
||||
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
|
||||
a.node_->value() = v;
|
||||
return a.release();
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(v);
|
||||
constructor_.create_node();
|
||||
boost::unordered::detail::func::call_construct(
|
||||
constructor_.alloc_, constructor_.node_->value_ptr(), v);
|
||||
return constructor_.release();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void assign_impl(std::pair<T1 const, T2> const& v) {
|
||||
this->construct_with_value2(v);
|
||||
inline node_pointer copy_of(std::pair<T1 const, T2> const& v) {
|
||||
if (nodes_) {
|
||||
constructor_.reclaim(pop_node());
|
||||
}
|
||||
else {
|
||||
constructor_.create_node();
|
||||
}
|
||||
boost::unordered::detail::func::call_construct(
|
||||
constructor_.alloc_, constructor_.node_->value_ptr(), v);
|
||||
return constructor_.release();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_assign_impl(T& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = boost::move(v);
|
||||
inline node_pointer move_copy_of(T& v) {
|
||||
if (nodes_) {
|
||||
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
|
||||
a.node_->value() = boost::move(v);
|
||||
return a.release();
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
constructor_.create_node();
|
||||
boost::unordered::detail::func::call_construct(
|
||||
constructor_.alloc_, constructor_.node_->value_ptr(),
|
||||
boost::move(v));
|
||||
return constructor_.release();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
|
||||
node_pointer copy_of(value_type const& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
assign_impl(v);
|
||||
return base::release();
|
||||
}
|
||||
|
||||
node_pointer move_copy_of(value_type& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
move_assign_impl(v);
|
||||
return base::release();
|
||||
inline node_pointer move_copy_of(std::pair<T1 const, T2>& v) {
|
||||
if (nodes_) {
|
||||
constructor_.reclaim(pop_node());
|
||||
}
|
||||
else {
|
||||
constructor_.create_node();
|
||||
}
|
||||
boost::unordered::detail::func::call_construct(
|
||||
constructor_.alloc_, constructor_.node_->value_ptr(),
|
||||
boost::move(v));
|
||||
return constructor_.release();
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
@ -545,10 +428,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer p = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(p->next_);
|
||||
|
||||
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
|
||||
boost::unordered::detail::func::destroy_value_impl(constructor_.alloc_,
|
||||
p->value_ptr());
|
||||
boost::unordered::detail::func::destroy(boost::addressof(*p));
|
||||
node_allocator_traits::deallocate(this->alloc_, p, 1);
|
||||
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
@ -130,55 +129,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct multiset
|
||||
{
|
||||
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<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 typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
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<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::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
struct grouped_table_impl : boost::unordered::detail::table<Types>
|
||||
{
|
||||
@ -195,6 +145,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::node_tmp node_tmp;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
@ -380,14 +331,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
pos->group_prev_ = n;
|
||||
}
|
||||
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
std::size_t key_hash,
|
||||
iterator pos)
|
||||
{
|
||||
return add_node(a.release(), key_hash, pos);
|
||||
}
|
||||
|
||||
inline iterator add_node(
|
||||
node_pointer n,
|
||||
std::size_t key_hash,
|
||||
@ -432,23 +375,23 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator emplace_impl(node_constructor& a)
|
||||
iterator emplace_impl(node_pointer n)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
node_tmp a(n, this->node_alloc());
|
||||
key_type const& k = this->get_key(a.node_->value());
|
||||
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, key_hash, position);
|
||||
return this->add_node(a.release(), key_hash, position);
|
||||
}
|
||||
|
||||
void emplace_impl_no_rehash(node_constructor& a)
|
||||
void emplace_impl_no_rehash(node_pointer n)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
node_tmp a(n, this->node_alloc());
|
||||
key_type const& k = this->get_key(a.node_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
this->add_node(a, key_hash, this->find_node(key_hash, k));
|
||||
iterator position = this->find_node(key_hash, k);
|
||||
this->add_node(a.release(), key_hash, position);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
@ -472,10 +415,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
|
||||
return iterator(emplace_impl(a));
|
||||
return iterator(emplace_impl(
|
||||
boost::unordered::detail::func::construct_value_generic(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -491,18 +433,18 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
std::size_t distance = std::distance(i, j);
|
||||
if(distance == 1) {
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl(a);
|
||||
emplace_impl(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *i));
|
||||
}
|
||||
else {
|
||||
// Only require basic exception safety here
|
||||
this->reserve_for_insert(this->size_ + distance);
|
||||
|
||||
node_constructor a(this->node_alloc());
|
||||
for (; i != j; ++i) {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl_no_rehash(a);
|
||||
emplace_impl_no_rehash(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -511,10 +453,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void insert_range(I i, I j, typename
|
||||
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
for (; i != j; ++i) {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl(a);
|
||||
emplace_impl(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,17 +570,64 @@ namespace boost { namespace unordered { namespace detail {
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// fill_buckets
|
||||
|
||||
template <class NodeCreator>
|
||||
void fill_buckets(iterator n, NodeCreator& creator)
|
||||
{
|
||||
while (n.node_) {
|
||||
void copy_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
|
||||
iterator pos = this->add_node(creator.create(*n), key_hash, iterator());
|
||||
iterator pos = this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *n), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
this->add_node(creator.create(*n), key_hash, pos);
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *n), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
iterator pos = this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), boost::move(*n)), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), boost::move(*n)), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assign_buckets(table const& src) {
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
iterator pos = this->add_node(holder.copy_of(*n), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
this->add_node(holder.copy_of(*n), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move_assign_buckets(table& src) {
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
iterator pos = this->add_node(holder.move_copy_of(*n), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
this->add_node(holder.move_copy_of(*n), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
61
include/boost/unordered/detail/map.hpp
Normal file
61
include/boost/unordered/detail/map.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
// Copyright (C) 2005-2016 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 <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct map
|
||||
{
|
||||
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<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::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
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<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::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
};
|
||||
|
||||
}}}
|
57
include/boost/unordered/detail/set.hpp
Normal file
57
include/boost/unordered/detail/set.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
// Copyright (C) 2005-2016 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 <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct set
|
||||
{
|
||||
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<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 typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct multiset
|
||||
{
|
||||
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<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 typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
};
|
||||
}}}
|
@ -13,10 +13,6 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/buckets.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <cmath>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
@ -68,70 +64,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
value_base& operator=(value_base const&);
|
||||
};
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct copy_nodes
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
|
||||
node_constructor<NodeAlloc> constructor;
|
||||
|
||||
explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
|
||||
|
||||
typename node_allocator_traits::pointer create(
|
||||
typename node_allocator_traits::value_type::value_type const& v)
|
||||
{
|
||||
constructor.construct_with_value2(v);
|
||||
return constructor.release();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct move_nodes
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
|
||||
node_constructor<NodeAlloc> constructor;
|
||||
|
||||
explicit move_nodes(NodeAlloc& a) : constructor(a) {}
|
||||
|
||||
typename node_allocator_traits::pointer create(
|
||||
typename node_allocator_traits::value_type::value_type& v)
|
||||
{
|
||||
constructor.construct_with_value2(boost::move(v));
|
||||
return constructor.release();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Buckets>
|
||||
struct assign_nodes
|
||||
{
|
||||
node_holder<typename Buckets::node_allocator> holder;
|
||||
|
||||
explicit assign_nodes(Buckets& b) : holder(b) {}
|
||||
|
||||
typename Buckets::node_pointer create(
|
||||
typename Buckets::value_type const& v)
|
||||
{
|
||||
return holder.copy_of(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Buckets>
|
||||
struct move_assign_nodes
|
||||
{
|
||||
node_holder<typename Buckets::node_allocator> holder;
|
||||
|
||||
explicit move_assign_nodes(Buckets& b) : holder(b) {}
|
||||
|
||||
typename Buckets::node_pointer create(
|
||||
typename Buckets::value_type& v)
|
||||
{
|
||||
return holder.move_copy_of(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
struct table :
|
||||
boost::unordered::detail::functions<
|
||||
@ -175,6 +107,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
bucket_pointer;
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
typedef boost::unordered::detail::node_tmp<node_allocator>
|
||||
node_tmp;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node> iterator;
|
||||
@ -391,9 +325,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void init(table const& x)
|
||||
{
|
||||
if (x.size_) {
|
||||
create_buckets(bucket_count_);
|
||||
copy_nodes<node_allocator> node_creator(node_alloc());
|
||||
static_cast<table_impl*>(this)->fill_buckets(x.begin(), node_creator);
|
||||
static_cast<table_impl*>(this)->copy_buckets(x);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,11 +336,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
else if(x.size_) {
|
||||
// TODO: Could pick new bucket size?
|
||||
create_buckets(bucket_count_);
|
||||
|
||||
move_nodes<node_allocator> node_creator(node_alloc());
|
||||
node_holder<node_allocator> nodes(x);
|
||||
static_cast<table_impl*>(this)->fill_buckets(nodes.begin(), node_creator);
|
||||
static_cast<table_impl*>(this)->move_buckets(x);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,34 +345,53 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
void create_buckets(std::size_t new_count)
|
||||
{
|
||||
boost::unordered::detail::array_constructor<bucket_allocator>
|
||||
constructor(bucket_alloc());
|
||||
|
||||
// Creates an extra bucket to act as the start node.
|
||||
constructor.construct(bucket(), new_count + 1);
|
||||
std::size_t length = new_count + 1;
|
||||
bucket_pointer new_buckets = bucket_allocator_traits::allocate(
|
||||
bucket_alloc(), length);
|
||||
bucket_pointer constructed = new_buckets;
|
||||
|
||||
if (buckets_)
|
||||
{
|
||||
// Copy the nodes to the new buckets, including the dummy
|
||||
// node if there is one.
|
||||
(constructor.get() +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
(buckets_ + static_cast<std::ptrdiff_t>(
|
||||
bucket_count_))->next_;
|
||||
destroy_buckets();
|
||||
}
|
||||
else if (bucket::extra_node)
|
||||
{
|
||||
node_constructor a(node_alloc());
|
||||
a.construct();
|
||||
BOOST_TRY {
|
||||
bucket_pointer end = new_buckets
|
||||
+ static_cast<std::ptrdiff_t>(length);
|
||||
for(; constructed != end; ++constructed) {
|
||||
new ((void*) boost::addressof(*constructed)) bucket();
|
||||
}
|
||||
|
||||
(constructor.get() +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
a.release();
|
||||
if (buckets_)
|
||||
{
|
||||
// Copy the nodes to the new buckets, including the dummy
|
||||
// node if there is one.
|
||||
(new_buckets +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
(buckets_ + static_cast<std::ptrdiff_t>(
|
||||
bucket_count_))->next_;
|
||||
destroy_buckets();
|
||||
}
|
||||
else if (bucket::extra_node)
|
||||
{
|
||||
node_constructor a(node_alloc());
|
||||
a.create_node();
|
||||
|
||||
(new_buckets +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
a.release();
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...) {
|
||||
for(bucket_pointer p = new_buckets; p != constructed; ++p) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*p));
|
||||
}
|
||||
|
||||
bucket_allocator_traits::deallocate(bucket_alloc(),
|
||||
new_buckets, length);
|
||||
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
bucket_count_ = new_count;
|
||||
buckets_ = constructor.release();
|
||||
buckets_ = new_buckets;
|
||||
recalculate_max_load();
|
||||
}
|
||||
|
||||
@ -650,11 +597,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
clear_buckets();
|
||||
}
|
||||
|
||||
// assign_nodes takes ownership of the container's elements,
|
||||
// assigning to them if possible, and deleting any that are
|
||||
// left over.
|
||||
assign_nodes<table> node_creator(*this);
|
||||
static_cast<table_impl*>(this)->fill_buckets(x.begin(), node_creator);
|
||||
static_cast<table_impl*>(this)->assign_buckets(x);
|
||||
}
|
||||
|
||||
void assign(table const& x, true_type)
|
||||
@ -679,9 +622,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Finally copy the elements.
|
||||
if (x.size_) {
|
||||
create_buckets(bucket_count_);
|
||||
copy_nodes<node_allocator> node_creator(node_alloc());
|
||||
static_cast<table_impl*>(this)->fill_buckets(x.begin(), node_creator);
|
||||
static_cast<table_impl*>(this)->copy_buckets(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -735,12 +676,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
clear_buckets();
|
||||
}
|
||||
|
||||
// move_assign_nodes takes ownership of the container's
|
||||
// elements, assigning to them if possible, and deleting
|
||||
// any that are left over.
|
||||
move_assign_nodes<table> node_creator(*this);
|
||||
node_holder<node_allocator> nodes(x);
|
||||
static_cast<table_impl*>(this)->fill_buckets(nodes.begin(), node_creator);
|
||||
static_cast<table_impl*>(this)->move_assign_buckets(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
@ -126,54 +125,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P>
|
||||
struct set
|
||||
{
|
||||
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<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 typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct map
|
||||
{
|
||||
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<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::map_extractor<key_type, value_type>
|
||||
extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
struct table_impl : boost::unordered::detail::table<Types>
|
||||
{
|
||||
@ -190,6 +141,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::node_tmp node_tmp;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
@ -307,13 +259,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
// Emplace/Insert
|
||||
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
std::size_t key_hash)
|
||||
{
|
||||
return add_node(a.release(), key_hash);
|
||||
}
|
||||
|
||||
inline iterator add_node(
|
||||
node_pointer n,
|
||||
std::size_t key_hash)
|
||||
@ -346,23 +291,21 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
inline iterator resize_and_add_node(node_pointer n, std::size_t key_hash)
|
||||
{
|
||||
node_tmp b(n, this->node_alloc());
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return this->add_node(b.release(), key_hash);
|
||||
}
|
||||
|
||||
value_type& operator[](key_type const& k)
|
||||
{
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
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_with_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, key_hash);
|
||||
return *this->resize_and_add_node(
|
||||
boost::unordered::detail::func::construct_pair(this->node_alloc(), k),
|
||||
key_hash);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
@ -412,32 +355,17 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
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).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
}
|
||||
|
||||
emplace_return emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
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(this->add_node(a, key_hash), true);
|
||||
if (pos.node_) {
|
||||
return emplace_return(pos, false);
|
||||
}
|
||||
else {
|
||||
return emplace_return(
|
||||
this->resize_and_add_node(
|
||||
boost::unordered::detail::func::construct_value_generic(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
key_hash),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
@ -445,9 +373,21 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
// Don't have a key, so construct the node first in order
|
||||
// to be able to lookup the position.
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
return emplace_impl_with_node(a);
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value_generic(
|
||||
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
this->node_alloc());
|
||||
key_type const& k = this->get_key(b.node_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
if (pos.node_) {
|
||||
return emplace_return(pos, false);
|
||||
}
|
||||
else {
|
||||
return emplace_return(
|
||||
this->resize_and_add_node(b.release(), key_hash),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -466,9 +406,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <class InputIt>
|
||||
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
|
||||
insert_range_impl2(a, k, i, j);
|
||||
insert_range_impl2(k, i, j);
|
||||
|
||||
while(++i != j) {
|
||||
// Note: can't use get_key as '*i' might not be value_type - it
|
||||
@ -479,26 +417,25 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// key here. Could be more efficient if '*i' is expensive. Could
|
||||
// be less efficient if copying the full value_type is
|
||||
// expensive.
|
||||
insert_range_impl2(a, extractor::extract(*i), i, j);
|
||||
insert_range_impl2(extractor::extract(*i), i, j);
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void insert_range_impl2(node_constructor& a, key_type const& k,
|
||||
InputIt i, InputIt j)
|
||||
void insert_range_impl2(key_type const& k, InputIt i, InputIt j)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (!pos.node_) {
|
||||
a.construct_with_value2(*i);
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(this->node_alloc(), *i),
|
||||
this->node_alloc());
|
||||
if(this->size_ + 1 > this->max_load_)
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
|
||||
// Nothing after this point can throw.
|
||||
this->add_node(a, key_hash);
|
||||
this->add_node(b.release(), key_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,8 +445,24 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor a(this->node_alloc());
|
||||
|
||||
do {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl_with_node(a);
|
||||
if (!a.node_) { a.create_node(); }
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, a.node_->value_ptr(), *i);
|
||||
node_tmp b(a.release(), a.alloc_);
|
||||
|
||||
key_type const& k = this->get_key(b.node_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos.node_) {
|
||||
a.reclaim(b.release());
|
||||
}
|
||||
else {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
this->add_node(b.release(), key_hash);
|
||||
}
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
@ -582,11 +535,39 @@ namespace boost { namespace unordered { namespace detail {
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// fill_buckets
|
||||
|
||||
template <class NodeCreator>
|
||||
void fill_buckets(iterator n, NodeCreator& creator)
|
||||
void copy_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), *n), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void move_buckets(table const& src) {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
this->node_alloc(), boost::move(*n)), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void assign_buckets(table const& src)
|
||||
{
|
||||
for (; n.node_; ++n) {
|
||||
this->add_node(creator.create(*n), n.node_->hash_);
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
this->add_node(holder.copy_of(*n), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void move_assign_buckets(table& src)
|
||||
{
|
||||
node_holder<node_allocator> holder(*this);
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
this->add_node(holder.move_copy_of(*n), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/unordered/detail/map.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
|
@ -14,10 +14,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
#include <boost/unordered/detail/util.hpp>
|
||||
#include <boost/unordered/detail/set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
|
Reference in New Issue
Block a user