forked from boostorg/unordered
Cherrypick some unordered container changes from sandbox. Not including
anything which depends on the new move library. ------------------------------------------------------------------------ r52746 | danieljames | 2009-05-03 11:12:30 +0100 (Sun, 03 May 2009) | 1 line Merge latest unordered container changes. ------------------------------------------------------------------------ r52747 | danieljames | 2009-05-03 11:15:35 +0100 (Sun, 03 May 2009) | 4 lines Put the C++0x emplace implementations before the non-C++0x versions. I'm going to change the non-C++0x to be macro heavy emulations of the C++0x versions, so this will put the readable version first. ------------------------------------------------------------------------ r52748 | danieljames | 2009-05-03 11:15:44 +0100 (Sun, 03 May 2009) | 1 line Refactor the unordered implementation a tad, to make implementing emplace less painful. ------------------------------------------------------------------------ [SVN r52884]
This commit is contained in:
@ -181,9 +181,7 @@ namespace boost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
void construct_preamble()
|
||||||
template <typename... Args>
|
|
||||||
void construct(Args&&... args)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!node_);
|
BOOST_ASSERT(!node_);
|
||||||
node_constructed_ = false;
|
node_constructed_ = false;
|
||||||
@ -194,6 +192,13 @@ namespace boost {
|
|||||||
allocators_.node_alloc_.construct(node_, node());
|
allocators_.node_alloc_.construct(node_, node());
|
||||||
node_constructed_ = true;
|
node_constructed_ = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||||
|
template <typename... Args>
|
||||||
|
void construct(Args&&... args)
|
||||||
|
{
|
||||||
|
construct_preamble();
|
||||||
new(node_->address()) value_type(std::forward<Args>(args)...);
|
new(node_->address()) value_type(std::forward<Args>(args)...);
|
||||||
value_constructed_ = true;
|
value_constructed_ = true;
|
||||||
}
|
}
|
||||||
@ -201,15 +206,7 @@ namespace boost {
|
|||||||
template <typename V>
|
template <typename V>
|
||||||
void construct(V const& v)
|
void construct(V const& v)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!node_);
|
construct_preamble();
|
||||||
node_constructed_ = false;
|
|
||||||
value_constructed_ = false;
|
|
||||||
|
|
||||||
node_ = allocators_.node_alloc_.allocate(1);
|
|
||||||
|
|
||||||
allocators_.node_alloc_.construct(node_, node());
|
|
||||||
node_constructed_ = true;
|
|
||||||
|
|
||||||
new(node_->address()) value_type(v);
|
new(node_->address()) value_type(v);
|
||||||
value_constructed_ = true;
|
value_constructed_ = true;
|
||||||
}
|
}
|
||||||
@ -1599,36 +1596,7 @@ namespace boost {
|
|||||||
|
|
||||||
#if BOOST_UNORDERED_EQUIVALENT_KEYS
|
#if BOOST_UNORDERED_EQUIVALENT_KEYS
|
||||||
|
|
||||||
#if !(defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL))
|
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||||
// Insert (equivalent key containers)
|
|
||||||
|
|
||||||
// if hash function throws, basic exception safety
|
|
||||||
// strong otherwise
|
|
||||||
iterator_base emplace(value_type const& v)
|
|
||||||
{
|
|
||||||
// Create the node before rehashing in case it throws an
|
|
||||||
// exception (need strong safety in such a case).
|
|
||||||
node_constructor a(data_.allocators_);
|
|
||||||
a.construct(v);
|
|
||||||
|
|
||||||
return emplace_impl(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert (equivalent key containers)
|
|
||||||
|
|
||||||
// if hash function throws, basic exception safety
|
|
||||||
// strong otherwise
|
|
||||||
iterator_base emplace_hint(iterator_base const& it, value_type const& v)
|
|
||||||
{
|
|
||||||
// Create the node before rehashing in case it throws an
|
|
||||||
// exception (need strong safety in such a case).
|
|
||||||
node_constructor a(data_.allocators_);
|
|
||||||
a.construct(v);
|
|
||||||
|
|
||||||
return emplace_hint_impl(it, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Emplace (equivalent key containers)
|
// Emplace (equivalent key containers)
|
||||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||||
@ -1646,7 +1614,7 @@ namespace boost {
|
|||||||
return emplace_impl(a);
|
return emplace_impl(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert (equivalent key containers)
|
// Emplace (equivalent key containers)
|
||||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||||
|
|
||||||
// if hash function throws, basic exception safety
|
// if hash function throws, basic exception safety
|
||||||
@ -1662,6 +1630,36 @@ namespace boost {
|
|||||||
return emplace_hint_impl(it, a);
|
return emplace_hint_impl(it, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Emplace (equivalent key containers)
|
||||||
|
|
||||||
|
// if hash function throws, basic exception safety
|
||||||
|
// strong otherwise
|
||||||
|
iterator_base emplace(value_type const& v)
|
||||||
|
{
|
||||||
|
// Create the node before rehashing in case it throws an
|
||||||
|
// exception (need strong safety in such a case).
|
||||||
|
node_constructor a(data_.allocators_);
|
||||||
|
a.construct(v);
|
||||||
|
|
||||||
|
return emplace_impl(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emplace (equivalent key containers)
|
||||||
|
|
||||||
|
// if hash function throws, basic exception safety
|
||||||
|
// strong otherwise
|
||||||
|
iterator_base emplace_hint(iterator_base const& it, value_type const& v)
|
||||||
|
{
|
||||||
|
// Create the node before rehashing in case it throws an
|
||||||
|
// exception (need strong safety in such a case).
|
||||||
|
node_constructor a(data_.allocators_);
|
||||||
|
a.construct(v);
|
||||||
|
|
||||||
|
return emplace_hint_impl(it, a);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iterator_base emplace_impl(node_constructor& a)
|
iterator_base emplace_impl(node_constructor& a)
|
||||||
@ -1689,13 +1687,13 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
// equal can throw, but with no effects
|
// equal can throw, but with no effects
|
||||||
if (it == data_.end() || !equal(extract_key(a.get()->value()), *it)) {
|
if (it == data_.end() || !equal(extract_key(a.get()->value()), *it)) {
|
||||||
// Use the standard insert if the iterator doesn't point
|
// Use the standard emplace if the iterator doesn't point
|
||||||
// to a matching key.
|
// to a matching key.
|
||||||
return emplace_impl(a);
|
return emplace_impl(a);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Find the first node in the group - so that the node
|
// Find the first node in the group - so that the node
|
||||||
// will be inserted at the end of the group.
|
// will be added at the end of the group.
|
||||||
|
|
||||||
link_ptr start(it.node_);
|
link_ptr start(it.node_);
|
||||||
while(data_.prev_in_group(start)->next_ == start)
|
while(data_.prev_in_group(start)->next_ == start)
|
||||||
@ -1803,64 +1801,10 @@ namespace boost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL))
|
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||||
|
|
||||||
// Insert (unique keys)
|
// Emplace (unique keys)
|
||||||
|
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||||
// if hash function throws, basic exception safety
|
|
||||||
// strong otherwise
|
|
||||||
std::pair<iterator_base, bool> emplace(value_type const& v)
|
|
||||||
{
|
|
||||||
// No side effects in this initial code
|
|
||||||
key_type const& k = extract_key(v);
|
|
||||||
size_type hash_value = hash_function()(k);
|
|
||||||
bucket_ptr bucket = data_.bucket_ptr_from_hash(hash_value);
|
|
||||||
link_ptr pos = find_iterator(bucket, k);
|
|
||||||
|
|
||||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
|
||||||
// Found an existing key, return it (no throw).
|
|
||||||
return std::pair<iterator_base, bool>(
|
|
||||||
iterator_base(bucket, pos), false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Doesn't already exist, add to bucket.
|
|
||||||
// Side effects only in this block.
|
|
||||||
|
|
||||||
// Create the node before rehashing in case it throws an
|
|
||||||
// exception (need strong safety in such a case).
|
|
||||||
node_constructor a(data_.allocators_);
|
|
||||||
a.construct(v);
|
|
||||||
|
|
||||||
// reserve has basic exception safety if the hash function
|
|
||||||
// throws, strong otherwise.
|
|
||||||
if(reserve_for_insert(size() + 1))
|
|
||||||
bucket = data_.bucket_ptr_from_hash(hash_value);
|
|
||||||
|
|
||||||
// Nothing after this point can throw.
|
|
||||||
|
|
||||||
link_ptr n = data_.link_node_in_bucket(a, bucket);
|
|
||||||
|
|
||||||
return std::pair<iterator_base, bool>(
|
|
||||||
iterator_base(bucket, n), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert (unique keys)
|
|
||||||
|
|
||||||
// if hash function throws, basic exception safety
|
|
||||||
// strong otherwise
|
|
||||||
iterator_base emplace_hint(iterator_base const& it, value_type const& v)
|
|
||||||
{
|
|
||||||
if(it != data_.end() && equal(extract_key(v), *it))
|
|
||||||
return it;
|
|
||||||
else
|
|
||||||
return emplace(v).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Insert (unique keys)
|
|
||||||
// (I'm using an overloaded insert for both 'insert' and 'emplace')
|
|
||||||
//
|
//
|
||||||
// TODO:
|
// TODO:
|
||||||
// For sets: create a local key without creating the node?
|
// For sets: create a local key without creating the node?
|
||||||
@ -1876,6 +1820,20 @@ namespace boost {
|
|||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert (unique keys)
|
||||||
|
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||||
|
// I'm just ignoring hints here for now.
|
||||||
|
|
||||||
|
// if hash function throws, basic exception safety
|
||||||
|
// strong otherwise
|
||||||
|
template<typename... Args>
|
||||||
|
iterator_base emplace_hint(iterator_base const&, Args&&... args)
|
||||||
|
{
|
||||||
|
return emplace_impl(
|
||||||
|
extract_key(std::forward<Args>(args)...),
|
||||||
|
std::forward<Args>(args)...).first;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
std::pair<iterator_base, bool> emplace_impl(key_type const& k, Args&&... args)
|
std::pair<iterator_base, bool> emplace_impl(key_type const& k, Args&&... args)
|
||||||
{
|
{
|
||||||
@ -1917,7 +1875,66 @@ namespace boost {
|
|||||||
// It will be discarded if it isn't used
|
// It will be discarded if it isn't used
|
||||||
node_constructor a(data_.allocators_);
|
node_constructor a(data_.allocators_);
|
||||||
a.construct(std::forward<Args>(args)...);
|
a.construct(std::forward<Args>(args)...);
|
||||||
|
return emplace_impl_with_node(a);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Emplace (unique keys)
|
||||||
|
|
||||||
|
// if hash function throws, basic exception safety
|
||||||
|
// strong otherwise
|
||||||
|
std::pair<iterator_base, bool> emplace(value_type const& v)
|
||||||
|
{
|
||||||
|
// No side effects in this initial code
|
||||||
|
key_type const& k = extract_key(v);
|
||||||
|
size_type hash_value = hash_function()(k);
|
||||||
|
bucket_ptr bucket = data_.bucket_ptr_from_hash(hash_value);
|
||||||
|
link_ptr pos = find_iterator(bucket, k);
|
||||||
|
|
||||||
|
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||||
|
// Found an existing key, return it (no throw).
|
||||||
|
return std::pair<iterator_base, bool>(
|
||||||
|
iterator_base(bucket, pos), false);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Doesn't already exist, add to bucket.
|
||||||
|
// Side effects only in this block.
|
||||||
|
|
||||||
|
// Create the node before rehashing in case it throws an
|
||||||
|
// exception (need strong safety in such a case).
|
||||||
|
node_constructor a(data_.allocators_);
|
||||||
|
a.construct(v);
|
||||||
|
|
||||||
|
// reserve has basic exception safety if the hash function
|
||||||
|
// throws, strong otherwise.
|
||||||
|
if(reserve_for_insert(size() + 1))
|
||||||
|
bucket = data_.bucket_ptr_from_hash(hash_value);
|
||||||
|
|
||||||
|
// Nothing after this point can throw.
|
||||||
|
|
||||||
|
link_ptr n = data_.link_node_in_bucket(a, bucket);
|
||||||
|
|
||||||
|
return std::pair<iterator_base, bool>(
|
||||||
|
iterator_base(bucket, n), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emplace (unique keys)
|
||||||
|
|
||||||
|
// if hash function throws, basic exception safety
|
||||||
|
// strong otherwise
|
||||||
|
iterator_base emplace_hint(iterator_base const& it, value_type const& v)
|
||||||
|
{
|
||||||
|
if(it != data_.end() && equal(extract_key(v), *it))
|
||||||
|
return it;
|
||||||
|
else
|
||||||
|
return emplace(v).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::pair<iterator_base, bool> emplace_impl_with_node(node_constructor& a)
|
||||||
|
{
|
||||||
// No side effects in this initial code
|
// No side effects in this initial code
|
||||||
key_type const& k = extract_key(a.get()->value());
|
key_type const& k = extract_key(a.get()->value());
|
||||||
size_type hash_value = hash_function()(k);
|
size_type hash_value = hash_function()(k);
|
||||||
@ -1941,18 +1958,6 @@ namespace boost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert (unique keys)
|
|
||||||
// (I'm using an overloaded insert for both 'insert' and 'emplace')
|
|
||||||
|
|
||||||
// if hash function throws, basic exception safety
|
|
||||||
// strong otherwise
|
|
||||||
template<typename... Args>
|
|
||||||
iterator_base emplace_hint(iterator_base const&, Args&&... args)
|
|
||||||
{
|
|
||||||
// Life is complicated - just call the normal implementation.
|
|
||||||
return emplace(std::forward<Args>(args)...).first;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Insert from iterators (unique keys)
|
// Insert from iterators (unique keys)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user