mirror of git://gcc.gnu.org/git/gcc.git
hashtable_policy.h (_ReuseOrAllocNode): Use forward pattern.
2013-07-05 François Dumont <fdumont@gcc.gnu.org> * include/bits/hashtable_policy.h (_ReuseOrAllocNode): Use forward pattern. (_MoveReuseOrAllocNode): Remove. (_Insert_base): Take a functor defining how the node is generated. * include/bits/hashtable.h: Adapt. (operator=(initializer_list<value_type>)): Reuse node if any. * testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust dg-error line number. * testsuite/23_containers/unordered_set/ not_default_constructible_hash_neg.cc: Likewise. From-SVN: r200724
This commit is contained in:
parent
2b778c9d57
commit
b3abc9d822
|
|
@ -1,3 +1,16 @@
|
||||||
|
2013-07-05 François Dumont <fdumont@gcc.gnu.org>
|
||||||
|
|
||||||
|
* include/bits/hashtable_policy.h (_ReuseOrAllocNode): Use forward
|
||||||
|
pattern.
|
||||||
|
(_MoveReuseOrAllocNode): Remove.
|
||||||
|
(_Insert_base): Take a functor defining how the node is generated.
|
||||||
|
* include/bits/hashtable.h: Adapt.
|
||||||
|
(operator=(initializer_list<value_type>)): Reuse node if any.
|
||||||
|
* testsuite/23_containers/unordered_set/instantiation_neg.cc:
|
||||||
|
Adjust dg-error line number.
|
||||||
|
* testsuite/23_containers/unordered_set/
|
||||||
|
not_default_constructible_hash_neg.cc: Likewise.
|
||||||
|
|
||||||
2013-07-04 Veres Lajos <vlajos@gmail.com>
|
2013-07-04 Veres Lajos <vlajos@gmail.com>
|
||||||
Jonathan Wakely <jwakely.gcc@gmail.com>
|
Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Equal, _H1, _H2, _Hash,
|
_Equal, _H1, _H2, _Hash,
|
||||||
_RehashPolicy, _Traits>;
|
_RehashPolicy, _Traits>;
|
||||||
|
|
||||||
|
using __reuse_or_alloc_node_type =
|
||||||
|
__detail::_ReuseOrAllocNode<_Key, _Value, _Alloc,
|
||||||
|
_ExtractKey, _Equal, _H1, _H2, _Hash,
|
||||||
|
_RehashPolicy, _Traits>;
|
||||||
|
|
||||||
// Metaprogramming for picking apart hash caching.
|
// Metaprogramming for picking apart hash caching.
|
||||||
template<typename _Cond>
|
template<typename _Cond>
|
||||||
using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
|
using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
|
||||||
|
|
@ -284,7 +289,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
"Cache the hash code or make functors involved in hash code"
|
"Cache the hash code or make functors involved in hash code"
|
||||||
" and bucket index computation copy assignable");
|
" and bucket index computation copy assignable");
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename _Keya, typename _Valuea, typename _Alloca,
|
template<typename _Keya, typename _Valuea, typename _Alloca,
|
||||||
typename _ExtractKeya, typename _Equala,
|
typename _ExtractKeya, typename _Equala,
|
||||||
typename _H1a, typename _H2a, typename _Hasha,
|
typename _H1a, typename _H2a, typename _Hasha,
|
||||||
|
|
@ -308,17 +312,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Keya, typename _Valuea, typename _Alloca,
|
template<typename _Keya, typename _Valuea, typename _Alloca,
|
||||||
typename _ExtractKeya, typename _Equala,
|
typename _ExtractKeya, typename _Equala,
|
||||||
typename _H1a, typename _H2a, typename _Hasha,
|
typename _H1a, typename _H2a, typename _Hasha,
|
||||||
typename _RehashPolicya, typename _Traitsa,
|
typename _RehashPolicya, typename _Traitsa>
|
||||||
bool _IsCopyAssignable>
|
|
||||||
friend struct __detail::_ReuseOrAllocNode;
|
friend struct __detail::_ReuseOrAllocNode;
|
||||||
|
|
||||||
template<typename _Keya, typename _Valuea, typename _Alloca,
|
template<typename _Keya, typename _Valuea, typename _Alloca,
|
||||||
typename _ExtractKeya, typename _Equala,
|
typename _ExtractKeya, typename _Equala,
|
||||||
typename _H1a, typename _H2a, typename _Hasha,
|
typename _H1a, typename _H2a, typename _Hasha,
|
||||||
typename _RehashPolicya, typename _Traitsa,
|
typename _RehashPolicya, typename _Traitsa>
|
||||||
bool _IsMoveAssignable>
|
friend struct __detail::_AllocNode;
|
||||||
friend struct __detail::_MoveReuseOrAllocNode;
|
|
||||||
|
|
||||||
|
public:
|
||||||
using size_type = typename __hashtable_base::size_type;
|
using size_type = typename __hashtable_base::size_type;
|
||||||
using difference_type = typename __hashtable_base::difference_type;
|
using difference_type = typename __hashtable_base::difference_type;
|
||||||
|
|
||||||
|
|
@ -394,9 +397,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_M_begin() const
|
_M_begin() const
|
||||||
{ return static_cast<__node_type*>(_M_before_begin()._M_nxt); }
|
{ return static_cast<__node_type*>(_M_before_begin()._M_nxt); }
|
||||||
|
|
||||||
template<typename _UnaryOp>
|
template<typename _NodeGenerator>
|
||||||
void
|
void
|
||||||
_M_assign(const _Hashtable&, const _UnaryOp&);
|
_M_assign(const _Hashtable&, const _NodeGenerator&);
|
||||||
|
|
||||||
void
|
void
|
||||||
_M_move_assign(_Hashtable&&, std::true_type);
|
_M_move_assign(_Hashtable&&, std::true_type);
|
||||||
|
|
@ -487,8 +490,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Hashtable&
|
_Hashtable&
|
||||||
operator=(initializer_list<value_type> __l)
|
operator=(initializer_list<value_type> __l)
|
||||||
{
|
{
|
||||||
|
__reuse_or_alloc_node_type __roan(_M_begin(), *this);
|
||||||
|
_M_before_begin()._M_nxt = nullptr;
|
||||||
clear();
|
clear();
|
||||||
this->insert(__l.begin(), __l.end());
|
this->_M_insert_range(__l.begin(), __l.end(), __roan);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -701,25 +706,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
iterator
|
iterator
|
||||||
_M_emplace(const_iterator, std::false_type, _Args&&... __args);
|
_M_emplace(const_iterator, std::false_type, _Args&&... __args);
|
||||||
|
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
std::pair<iterator, bool>
|
std::pair<iterator, bool>
|
||||||
_M_insert(_Arg&&, std::true_type);
|
_M_insert(_Arg&&, const _NodeGenerator&, std::true_type);
|
||||||
|
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
iterator
|
iterator
|
||||||
_M_insert(_Arg&& __arg, std::false_type __uk)
|
_M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
|
||||||
{ return _M_insert(cend(), std::forward<_Arg>(__arg), __uk); }
|
std::false_type __uk)
|
||||||
|
{
|
||||||
|
return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen,
|
||||||
|
__uk);
|
||||||
|
}
|
||||||
|
|
||||||
// Insert with hint, not used when keys are unique.
|
// Insert with hint, not used when keys are unique.
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
iterator
|
iterator
|
||||||
_M_insert(const_iterator, _Arg&& __arg, std::true_type __uk)
|
_M_insert(const_iterator, _Arg&& __arg, const _NodeGenerator& __node_gen,
|
||||||
{ return _M_insert(std::forward<_Arg>(__arg), __uk).first; }
|
std::true_type __uk)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
_M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).first;
|
||||||
|
}
|
||||||
|
|
||||||
// Insert with hint when keys are not unique.
|
// Insert with hint when keys are not unique.
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
iterator
|
iterator
|
||||||
_M_insert(const_iterator, _Arg&&, std::false_type);
|
_M_insert(const_iterator, _Arg&&, const _NodeGenerator&, std::false_type);
|
||||||
|
|
||||||
size_type
|
size_type
|
||||||
_M_erase(std::true_type, const key_type&);
|
_M_erase(std::true_type, const key_type&);
|
||||||
|
|
@ -1029,12 +1042,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__hashtable_base::operator=(__ht);
|
__hashtable_base::operator=(__ht);
|
||||||
_M_element_count = __ht._M_element_count;
|
_M_element_count = __ht._M_element_count;
|
||||||
_M_rehash_policy = __ht._M_rehash_policy;
|
_M_rehash_policy = __ht._M_rehash_policy;
|
||||||
__detail::_ReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
|
__reuse_or_alloc_node_type __roan(_M_begin(), *this);
|
||||||
_Equal, _H1, _H2, _Hash,
|
|
||||||
_RehashPolicy, _Traits>
|
|
||||||
__roan(_M_begin(), *this);
|
|
||||||
_M_before_begin()._M_nxt = nullptr;
|
_M_before_begin()._M_nxt = nullptr;
|
||||||
_M_assign(__ht, __roan);
|
_M_assign(__ht,
|
||||||
|
[&__roan](const __node_type* __n)
|
||||||
|
{ return __roan(__n->_M_v()); });
|
||||||
if (__former_buckets)
|
if (__former_buckets)
|
||||||
_M_deallocate_buckets(__former_buckets, __former_bucket_count);
|
_M_deallocate_buckets(__former_buckets, __former_bucket_count);
|
||||||
}
|
}
|
||||||
|
|
@ -1059,11 +1071,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typename _Alloc, typename _ExtractKey, typename _Equal,
|
typename _Alloc, typename _ExtractKey, typename _Equal,
|
||||||
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
||||||
typename _Traits>
|
typename _Traits>
|
||||||
template<typename _UnaryOp>
|
template<typename _NodeGenerator>
|
||||||
void
|
void
|
||||||
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
||||||
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
||||||
_M_assign(const _Hashtable& __ht, const _UnaryOp& __node_getter)
|
_M_assign(const _Hashtable& __ht, const _NodeGenerator& __node_gen)
|
||||||
{
|
{
|
||||||
__bucket_type* __buckets = nullptr;
|
__bucket_type* __buckets = nullptr;
|
||||||
if (!_M_buckets)
|
if (!_M_buckets)
|
||||||
|
|
@ -1077,7 +1089,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
// First deal with the special first node pointed to by
|
// First deal with the special first node pointed to by
|
||||||
// _M_before_begin.
|
// _M_before_begin.
|
||||||
__node_type* __ht_n = __ht._M_begin();
|
__node_type* __ht_n = __ht._M_begin();
|
||||||
__node_type* __this_n = __node_getter(__ht_n);
|
__node_type* __this_n = __node_gen(__ht_n);
|
||||||
this->_M_copy_code(__this_n, __ht_n);
|
this->_M_copy_code(__this_n, __ht_n);
|
||||||
_M_before_begin()._M_nxt = __this_n;
|
_M_before_begin()._M_nxt = __this_n;
|
||||||
_M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin();
|
_M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin();
|
||||||
|
|
@ -1086,7 +1098,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__node_base* __prev_n = __this_n;
|
__node_base* __prev_n = __this_n;
|
||||||
for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
|
for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
|
||||||
{
|
{
|
||||||
__this_n = __node_getter(__ht_n);
|
__this_n = __node_gen(__ht_n);
|
||||||
__prev_n->_M_nxt = __this_n;
|
__prev_n->_M_nxt = __this_n;
|
||||||
this->_M_copy_code(__this_n, __ht_n);
|
this->_M_copy_code(__this_n, __ht_n);
|
||||||
size_type __bkt = _M_bucket_index(__this_n);
|
size_type __bkt = _M_bucket_index(__this_n);
|
||||||
|
|
@ -1181,12 +1193,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__hashtable_base::operator=(std::move(__ht));
|
__hashtable_base::operator=(std::move(__ht));
|
||||||
_M_element_count = __ht._M_element_count;
|
_M_element_count = __ht._M_element_count;
|
||||||
_M_rehash_policy = __ht._M_rehash_policy;
|
_M_rehash_policy = __ht._M_rehash_policy;
|
||||||
__detail::_MoveReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
|
__reuse_or_alloc_node_type __roan(_M_begin(), *this);
|
||||||
_Equal, _H1, _H2, _Hash,
|
|
||||||
_RehashPolicy, _Traits>
|
|
||||||
__mroan(_M_begin(), *this);
|
|
||||||
_M_before_begin()._M_nxt = nullptr;
|
_M_before_begin()._M_nxt = nullptr;
|
||||||
_M_assign(__ht, __mroan);
|
_M_assign(__ht,
|
||||||
|
[&__roan](__node_type* __n)
|
||||||
|
{ return __roan(std::move_if_noexcept(__n->_M_v())); });
|
||||||
__ht.clear();
|
__ht.clear();
|
||||||
}
|
}
|
||||||
__catch(...)
|
__catch(...)
|
||||||
|
|
@ -1534,11 +1545,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__node_base* __prev_p = _M_buckets[__n];
|
__node_base* __prev_p = _M_buckets[__n];
|
||||||
if (!__prev_p)
|
if (!__prev_p)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);
|
|
||||||
for (;; __p = __p->_M_next())
|
for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
|
||||||
|
__p = __p->_M_next())
|
||||||
{
|
{
|
||||||
if (this->_M_equals(__k, __code, __p))
|
if (this->_M_equals(__k, __code, __p))
|
||||||
return __prev_p;
|
return __prev_p;
|
||||||
|
|
||||||
if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
|
if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
|
||||||
break;
|
break;
|
||||||
__prev_p = __p;
|
__prev_p = __p;
|
||||||
|
|
@ -1796,14 +1809,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typename _Alloc, typename _ExtractKey, typename _Equal,
|
typename _Alloc, typename _ExtractKey, typename _Equal,
|
||||||
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
||||||
typename _Traits>
|
typename _Traits>
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
std::pair<typename _Hashtable<_Key, _Value, _Alloc,
|
std::pair<typename _Hashtable<_Key, _Value, _Alloc,
|
||||||
_ExtractKey, _Equal, _H1,
|
_ExtractKey, _Equal, _H1,
|
||||||
_H2, _Hash, _RehashPolicy,
|
_H2, _Hash, _RehashPolicy,
|
||||||
_Traits>::iterator, bool>
|
_Traits>::iterator, bool>
|
||||||
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
||||||
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
||||||
_M_insert(_Arg&& __v, std::true_type)
|
_M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, std::true_type)
|
||||||
{
|
{
|
||||||
const key_type& __k = this->_M_extract()(__v);
|
const key_type& __k = this->_M_extract()(__v);
|
||||||
__hash_code __code = this->_M_hash_code(__k);
|
__hash_code __code = this->_M_hash_code(__k);
|
||||||
|
|
@ -1813,7 +1826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
if (__n)
|
if (__n)
|
||||||
return std::make_pair(iterator(__n), false);
|
return std::make_pair(iterator(__n), false);
|
||||||
|
|
||||||
__n = _M_allocate_node(std::forward<_Arg>(__v));
|
__n = __node_gen(std::forward<_Arg>(__v));
|
||||||
return std::make_pair(_M_insert_unique_node(__bkt, __code, __n), true);
|
return std::make_pair(_M_insert_unique_node(__bkt, __code, __n), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1822,20 +1835,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typename _Alloc, typename _ExtractKey, typename _Equal,
|
typename _Alloc, typename _ExtractKey, typename _Equal,
|
||||||
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
|
||||||
typename _Traits>
|
typename _Traits>
|
||||||
template<typename _Arg>
|
template<typename _Arg, typename _NodeGenerator>
|
||||||
typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
||||||
_H1, _H2, _Hash, _RehashPolicy,
|
_H1, _H2, _Hash, _RehashPolicy,
|
||||||
_Traits>::iterator
|
_Traits>::iterator
|
||||||
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
|
||||||
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
|
||||||
_M_insert(const_iterator __hint, _Arg&& __v, std::false_type)
|
_M_insert(const_iterator __hint, _Arg&& __v,
|
||||||
|
const _NodeGenerator& __node_gen,
|
||||||
|
std::false_type)
|
||||||
{
|
{
|
||||||
// First compute the hash code so that we don't do anything if it
|
// First compute the hash code so that we don't do anything if it
|
||||||
// throws.
|
// throws.
|
||||||
__hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
|
__hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
|
||||||
|
|
||||||
// Second allocate new node so that we don't rehash if it throws.
|
// Second allocate new node so that we don't rehash if it throws.
|
||||||
__node_type* __node = _M_allocate_node(std::forward<_Arg>(__v));
|
__node_type* __node = __node_gen(std::forward<_Arg>(__v));
|
||||||
|
|
||||||
return _M_insert_multi_node(__hint._M_cur, __code, __node);
|
return _M_insert_multi_node(__hint._M_cur, __code, __node);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,90 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ return std::get<0>(std::forward<_Tp>(__x)); }
|
{ return std::get<0>(std::forward<_Tp>(__x)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Functor recycling a pool of nodes and using allocation once the pool is
|
||||||
|
// empty.
|
||||||
|
template<typename _Key, typename _Value, typename _Alloc,
|
||||||
|
typename _ExtractKey, typename _Equal,
|
||||||
|
typename _H1, typename _H2, typename _Hash,
|
||||||
|
typename _RehashPolicy, typename _Traits>
|
||||||
|
struct _ReuseOrAllocNode
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
||||||
|
_Equal, _H1, _H2, _Hash,
|
||||||
|
_RehashPolicy, _Traits>;
|
||||||
|
using __val_alloc_type = typename __hashtable::_Value_alloc_type;
|
||||||
|
using __val_alloc_traits = typename __hashtable::_Value_alloc_traits;
|
||||||
|
using __node_alloc_traits = typename __hashtable::_Node_alloc_traits;
|
||||||
|
using __node_type = typename __hashtable::__node_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_ReuseOrAllocNode(__node_type* __nodes, __hashtable& __h)
|
||||||
|
: _M_nodes(__nodes), _M_h(__h) { }
|
||||||
|
_ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete;
|
||||||
|
|
||||||
|
~_ReuseOrAllocNode()
|
||||||
|
{ _M_h._M_deallocate_nodes(_M_nodes); }
|
||||||
|
|
||||||
|
template<typename _Arg>
|
||||||
|
__node_type*
|
||||||
|
operator()(_Arg&& __arg) const
|
||||||
|
{
|
||||||
|
if (_M_nodes)
|
||||||
|
{
|
||||||
|
__node_type* __node = _M_nodes;
|
||||||
|
_M_nodes = _M_nodes->_M_next();
|
||||||
|
__node->_M_nxt = nullptr;
|
||||||
|
__val_alloc_type __a(_M_h._M_node_allocator());
|
||||||
|
__val_alloc_traits::destroy(__a, __node->_M_valptr());
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
__val_alloc_traits::construct(__a, __node->_M_valptr(),
|
||||||
|
std::forward<_Arg>(__arg));
|
||||||
|
}
|
||||||
|
__catch(...)
|
||||||
|
{
|
||||||
|
__node->~__node_type();
|
||||||
|
__node_alloc_traits::deallocate(_M_h._M_node_allocator(),
|
||||||
|
__node, 1);
|
||||||
|
__throw_exception_again;
|
||||||
|
}
|
||||||
|
return __node;
|
||||||
|
}
|
||||||
|
return _M_h._M_allocate_node(std::forward<_Arg>(__arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable __node_type* _M_nodes;
|
||||||
|
__hashtable& _M_h;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Functor similar to the previous one but without any pool of node to recycle.
|
||||||
|
template<typename _Key, typename _Value, typename _Alloc,
|
||||||
|
typename _ExtractKey, typename _Equal,
|
||||||
|
typename _H1, typename _H2, typename _Hash,
|
||||||
|
typename _RehashPolicy, typename _Traits>
|
||||||
|
struct _AllocNode
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
||||||
|
_Equal, _H1, _H2, _Hash,
|
||||||
|
_RehashPolicy, _Traits>;
|
||||||
|
using __node_type = typename __hashtable::__node_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_AllocNode(__hashtable& __h)
|
||||||
|
: _M_h(__h) { }
|
||||||
|
|
||||||
|
template<typename _Arg>
|
||||||
|
__node_type*
|
||||||
|
operator()(_Arg&& __arg) const
|
||||||
|
{ return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
__hashtable& _M_h;
|
||||||
|
};
|
||||||
|
|
||||||
// Auxiliary types used for all instantiations of _Hashtable nodes
|
// Auxiliary types used for all instantiations of _Hashtable nodes
|
||||||
// and iterators.
|
// and iterators.
|
||||||
|
|
||||||
|
|
@ -597,6 +681,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typename _RehashPolicy, typename _Traits>
|
typename _RehashPolicy, typename _Traits>
|
||||||
struct _Insert_base
|
struct _Insert_base
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
||||||
_Equal, _H1, _H2, _Hash,
|
_Equal, _H1, _H2, _Hash,
|
||||||
_RehashPolicy, _Traits>;
|
_RehashPolicy, _Traits>;
|
||||||
|
|
@ -612,23 +697,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
using __unique_keys = typename __hashtable_base::__unique_keys;
|
using __unique_keys = typename __hashtable_base::__unique_keys;
|
||||||
using __ireturn_type = typename __hashtable_base::__ireturn_type;
|
using __ireturn_type = typename __hashtable_base::__ireturn_type;
|
||||||
|
using __node_gen_type = _AllocNode<_Key, _Value, _Alloc, _ExtractKey,
|
||||||
|
_Equal, _H1, _H2, _Hash,
|
||||||
|
_RehashPolicy, _Traits>;
|
||||||
|
|
||||||
__hashtable&
|
__hashtable&
|
||||||
_M_conjure_hashtable()
|
_M_conjure_hashtable()
|
||||||
{ return *(static_cast<__hashtable*>(this)); }
|
{ return *(static_cast<__hashtable*>(this)); }
|
||||||
|
|
||||||
|
template<typename _InputIterator, typename _NodeGetter>
|
||||||
|
void
|
||||||
|
_M_insert_range(_InputIterator __first, _InputIterator __last,
|
||||||
|
const _NodeGetter&);
|
||||||
|
|
||||||
|
public:
|
||||||
__ireturn_type
|
__ireturn_type
|
||||||
insert(const value_type& __v)
|
insert(const value_type& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = _M_conjure_hashtable();
|
__hashtable& __h = _M_conjure_hashtable();
|
||||||
return __h._M_insert(__v, __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(__v, __node_gen, __unique_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator
|
iterator
|
||||||
insert(const_iterator __hint, const value_type& __v)
|
insert(const_iterator __hint, const value_type& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = _M_conjure_hashtable();
|
__hashtable& __h = _M_conjure_hashtable();
|
||||||
return __h._M_insert(__hint, __v, __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(__hint, __v, __node_gen, __unique_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -637,18 +733,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
template<typename _InputIterator>
|
template<typename _InputIterator>
|
||||||
void
|
void
|
||||||
insert(_InputIterator __first, _InputIterator __last);
|
insert(_InputIterator __first, _InputIterator __last)
|
||||||
|
{
|
||||||
|
__hashtable& __h = _M_conjure_hashtable();
|
||||||
|
__node_gen_type __node_gen(__h);
|
||||||
|
return _M_insert_range(__first, __last, __node_gen);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _Key, typename _Value, typename _Alloc,
|
template<typename _Key, typename _Value, typename _Alloc,
|
||||||
typename _ExtractKey, typename _Equal,
|
typename _ExtractKey, typename _Equal,
|
||||||
typename _H1, typename _H2, typename _Hash,
|
typename _H1, typename _H2, typename _Hash,
|
||||||
typename _RehashPolicy, typename _Traits>
|
typename _RehashPolicy, typename _Traits>
|
||||||
template<typename _InputIterator>
|
template<typename _InputIterator, typename _NodeGetter>
|
||||||
void
|
void
|
||||||
_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
|
_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
|
||||||
_RehashPolicy, _Traits>::
|
_RehashPolicy, _Traits>::
|
||||||
insert(_InputIterator __first, _InputIterator __last)
|
_M_insert_range(_InputIterator __first, _InputIterator __last,
|
||||||
|
const _NodeGetter& __node_gen)
|
||||||
{
|
{
|
||||||
using __rehash_type = typename __hashtable::__rehash_type;
|
using __rehash_type = typename __hashtable::__rehash_type;
|
||||||
using __rehash_state = typename __hashtable::__rehash_state;
|
using __rehash_state = typename __hashtable::__rehash_state;
|
||||||
|
|
@ -667,7 +769,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__h._M_rehash(__do_rehash.second, __saved_state);
|
__h._M_rehash(__do_rehash.second, __saved_state);
|
||||||
|
|
||||||
for (; __first != __last; ++__first)
|
for (; __first != __last; ++__first)
|
||||||
__h._M_insert(*__first, __unique_keys());
|
__h._M_insert(*__first, __node_gen, __unique_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -702,6 +804,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
using __unique_keys = typename __base_type::__unique_keys;
|
using __unique_keys = typename __base_type::__unique_keys;
|
||||||
using __hashtable = typename __base_type::__hashtable;
|
using __hashtable = typename __base_type::__hashtable;
|
||||||
|
using __node_gen_type = typename __base_type::__node_gen_type;
|
||||||
|
|
||||||
using __base_type::insert;
|
using __base_type::insert;
|
||||||
|
|
||||||
|
|
@ -709,14 +812,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
insert(value_type&& __v)
|
insert(value_type&& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = this->_M_conjure_hashtable();
|
__hashtable& __h = this->_M_conjure_hashtable();
|
||||||
return __h._M_insert(std::move(__v), __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(std::move(__v), __node_gen, __unique_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator
|
iterator
|
||||||
insert(const_iterator __hint, value_type&& __v)
|
insert(const_iterator __hint, value_type&& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = this->_M_conjure_hashtable();
|
__hashtable& __h = this->_M_conjure_hashtable();
|
||||||
return __h._M_insert(__hint, std::move(__v), __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(__hint, std::move(__v), __node_gen,
|
||||||
|
__unique_keys());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -739,6 +845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
using __unique_keys = typename __base_type::__unique_keys;
|
using __unique_keys = typename __base_type::__unique_keys;
|
||||||
using __hashtable = typename __base_type::__hashtable;
|
using __hashtable = typename __base_type::__hashtable;
|
||||||
|
using __node_gen_type = typename __base_type::__node_gen_type;
|
||||||
|
|
||||||
using __base_type::insert;
|
using __base_type::insert;
|
||||||
|
|
||||||
|
|
@ -746,14 +853,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
insert(value_type&& __v)
|
insert(value_type&& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = this->_M_conjure_hashtable();
|
__hashtable& __h = this->_M_conjure_hashtable();
|
||||||
return __h._M_insert(std::move(__v), __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(std::move(__v), __node_gen, __unique_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator
|
iterator
|
||||||
insert(const_iterator __hint, value_type&& __v)
|
insert(const_iterator __hint, value_type&& __v)
|
||||||
{
|
{
|
||||||
__hashtable& __h = this->_M_conjure_hashtable();
|
__hashtable& __h = this->_M_conjure_hashtable();
|
||||||
return __h._M_insert(__hint, std::move(__v), __unique_keys());
|
__node_gen_type __node_gen(__h);
|
||||||
|
return __h._M_insert(__hint, std::move(__v), __node_gen,
|
||||||
|
__unique_keys());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1694,120 +1804,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Following are functors recyclicing a pool of nodes and using allocation
|
|
||||||
* once the pool is empty.
|
|
||||||
*/
|
|
||||||
/// Version using copy semantic through the copy constructor.
|
|
||||||
template<typename _Key, typename _Value, typename _Alloc,
|
|
||||||
typename _ExtractKey, typename _Equal,
|
|
||||||
typename _H1, typename _H2, typename _Hash,
|
|
||||||
typename _RehashPolicy, typename _Traits>
|
|
||||||
struct _ReuseOrAllocNode
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
|
||||||
_Equal, _H1, _H2, _Hash,
|
|
||||||
_RehashPolicy, _Traits>;
|
|
||||||
using __val_alloc_type = typename __hashtable::_Value_alloc_type;
|
|
||||||
using __val_alloc_traits = typename __hashtable::_Value_alloc_traits;
|
|
||||||
using __node_alloc_traits = typename __hashtable::_Node_alloc_traits;
|
|
||||||
using __node_type = typename __hashtable::__node_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ReuseOrAllocNode(__node_type* __nodes, __hashtable& __h)
|
|
||||||
: _M_nodes(__nodes), _M_h(__h) { }
|
|
||||||
_ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete;
|
|
||||||
|
|
||||||
~_ReuseOrAllocNode()
|
|
||||||
{ _M_h._M_deallocate_nodes(_M_nodes); }
|
|
||||||
|
|
||||||
__node_type*
|
|
||||||
operator()(const __node_type* __n) const
|
|
||||||
{
|
|
||||||
if (_M_nodes)
|
|
||||||
{
|
|
||||||
__node_type* __node = _M_nodes;
|
|
||||||
_M_nodes = _M_nodes->_M_next();
|
|
||||||
__node->_M_nxt = nullptr;
|
|
||||||
__val_alloc_type __a(_M_h._M_node_allocator());
|
|
||||||
__val_alloc_traits::destroy(__a, __node->_M_valptr());
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
__val_alloc_traits::construct(__a, __node->_M_valptr(),
|
|
||||||
__n->_M_v());
|
|
||||||
}
|
|
||||||
__catch(...)
|
|
||||||
{
|
|
||||||
__node->~__node_type();
|
|
||||||
__node_alloc_traits::deallocate(_M_h._M_node_allocator(),
|
|
||||||
__node, 1);
|
|
||||||
__throw_exception_again;
|
|
||||||
}
|
|
||||||
return __node;
|
|
||||||
}
|
|
||||||
return _M_h._M_allocate_node(__n->_M_v());
|
|
||||||
}
|
|
||||||
|
|
||||||
mutable __node_type* _M_nodes;
|
|
||||||
__hashtable& _M_h;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Version using move semantic through the move constructor.
|
|
||||||
template<typename _Key, typename _Value, typename _Alloc,
|
|
||||||
typename _ExtractKey, typename _Equal,
|
|
||||||
typename _H1, typename _H2, typename _Hash,
|
|
||||||
typename _RehashPolicy, typename _Traits>
|
|
||||||
struct _MoveReuseOrAllocNode
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
|
|
||||||
_Equal, _H1, _H2, _Hash,
|
|
||||||
_RehashPolicy, _Traits>;
|
|
||||||
using __val_alloc_type = typename __hashtable::_Value_alloc_type;
|
|
||||||
using __val_alloc_traits = typename __hashtable::_Value_alloc_traits;
|
|
||||||
using __node_alloc_traits = typename __hashtable::_Node_alloc_traits;
|
|
||||||
using __node_type = typename __hashtable::__node_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_MoveReuseOrAllocNode(__node_type* __nodes, __hashtable& __h)
|
|
||||||
: _M_nodes(__nodes), _M_h(__h) { }
|
|
||||||
_MoveReuseOrAllocNode(const _MoveReuseOrAllocNode&) = delete;
|
|
||||||
|
|
||||||
~_MoveReuseOrAllocNode()
|
|
||||||
{ _M_h._M_deallocate_nodes(_M_nodes); }
|
|
||||||
|
|
||||||
__node_type*
|
|
||||||
operator()(__node_type* __n) const
|
|
||||||
{
|
|
||||||
if (_M_nodes)
|
|
||||||
{
|
|
||||||
__node_type* __node = _M_nodes;
|
|
||||||
_M_nodes = _M_nodes->_M_next();
|
|
||||||
__node->_M_nxt = nullptr;
|
|
||||||
__val_alloc_type __a(_M_h._M_node_allocator());
|
|
||||||
__val_alloc_traits::destroy(__a, __node->_M_valptr());
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
__val_alloc_traits::construct(__a, __node->_M_valptr(),
|
|
||||||
std::move_if_noexcept(__n->_M_v()));
|
|
||||||
}
|
|
||||||
__catch(...)
|
|
||||||
{
|
|
||||||
__node->~__node_type();
|
|
||||||
__node_alloc_traits::deallocate(_M_h._M_node_allocator(),
|
|
||||||
__node, 1);
|
|
||||||
__throw_exception_again;
|
|
||||||
}
|
|
||||||
return __node;
|
|
||||||
}
|
|
||||||
return _M_h._M_allocate_node(std::move_if_noexcept(__n->_M_v()));
|
|
||||||
}
|
|
||||||
|
|
||||||
mutable __node_type* _M_nodes;
|
|
||||||
__hashtable& _M_h;
|
|
||||||
};
|
|
||||||
|
|
||||||
//@} hashtable-detail
|
//@} hashtable-detail
|
||||||
_GLIBCXX_END_NAMESPACE_VERSION
|
_GLIBCXX_END_NAMESPACE_VERSION
|
||||||
} // namespace __detail
|
} // namespace __detail
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// with this library; see the file COPYING3. If not see
|
// with this library; see the file COPYING3. If not see
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-error "with noexcept" "" { target *-*-* } 253 }
|
// { dg-error "with noexcept" "" { target *-*-* } 258 }
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// with this library; see the file COPYING3. If not see
|
// with this library; see the file COPYING3. If not see
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-error "default constructible" "" { target *-*-* } 271 }
|
// { dg-error "default constructible" "" { target *-*-* } 276 }
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue