Commit b3abc9d8 by François Dumont

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
parent 2b778c9d
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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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);
} }
......
...@@ -19,7 +19,7 @@ ...@@ -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 @@ ...@@ -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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment