summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-28 16:01:05 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-28 16:01:05 +0000
commit802d83c31a1be0063de7ee1e328c44635e592330 (patch)
tree8c058c4b504e6a5cbf998753e6c41978cf0ba81f /libstdc++-v3
parent7899be63a386ee42db6177cb40d68d9f03e078ab (diff)
downloadgcc-802d83c31a1be0063de7ee1e328c44635e592330.tar.gz
2010-10-28 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/44436 (partial) * include/bits/hashtable.h (_Hashtable<>::insert(value_type&&), insert(_Pair&&), insert(const_iterator, value_type&&), insert(const_iterator, _Pair&&)): Add. (_M_allocate_node, _M_insert, _M_insert_bucket): Templatize. * include/bits/hashtable_policy.h (__detail::_Select1st): Add; use it throughout. (_Map_base<>::operator[](_Key&&)): Add. * include/bits/unordered_map.h: Use __detail::_Select1st throughout. * include/debug/unordered_map: Update. * include/debug/unordered_set: Likewise. * include/profile/unordered_map: Likewise. * include/profile/unordered_set: Likewise. * testsuite/util/testsuite_rvalref.h (struct hash<rvalstruct>): Add; minor tweaks throughout, use deleted special members. * testsuite/23_containers/unordered_map/insert/map_single_move-1.cc: New. * testsuite/23_containers/unordered_map/insert/map_single_move-2.cc: Likewise. * testsuite/23_containers/unordered_map/insert/array_syntax_move.cc: Likewise. * testsuite/23_containers/unordered_multimap/insert/ multimap_single_move-1.cc: Likewise. * testsuite/23_containers/unordered_multimap/insert/ multimap_single_move-2.cc: Likewise. * testsuite/23_containers/unordered_set/insert/set_single_move.cc: Likewise. * testsuite/23_containers/unordered_multiset/insert/ multiset_single_move.cc: Likewise. * testsuite/23_containers/unordered_map/insert/array_syntax.cc: Minor cosmetic changes. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166030 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog35
-rw-r--r--libstdc++-v3/include/bits/hashtable.h295
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h53
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h20
-rw-r--r--libstdc++-v3/include/debug/unordered_map36
-rw-r--r--libstdc++-v3/include/debug/unordered_set24
-rw-r--r--libstdc++-v3/include/profile/unordered_map51
-rw-r--r--libstdc++-v3/include/profile/unordered_set40
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc21
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc59
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc76
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc79
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc80
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc80
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc71
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc69
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_rvalref.h56
17 files changed, 959 insertions, 186 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 05bfcbdf27c..8b5b94aaec7 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,38 @@
+2010-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/44436 (partial)
+ * include/bits/hashtable.h (_Hashtable<>::insert(value_type&&),
+ insert(_Pair&&), insert(const_iterator, value_type&&),
+ insert(const_iterator, _Pair&&)): Add.
+ (_M_allocate_node, _M_insert, _M_insert_bucket): Templatize.
+ * include/bits/hashtable_policy.h (__detail::_Select1st): Add; use
+ it throughout.
+ (_Map_base<>::operator[](_Key&&)): Add.
+ * include/bits/unordered_map.h: Use __detail::_Select1st throughout.
+ * include/debug/unordered_map: Update.
+ * include/debug/unordered_set: Likewise.
+ * include/profile/unordered_map: Likewise.
+ * include/profile/unordered_set: Likewise.
+ * testsuite/util/testsuite_rvalref.h (struct hash<rvalstruct>): Add;
+ minor tweaks throughout, use deleted special members.
+ * testsuite/23_containers/unordered_map/insert/map_single_move-1.cc:
+ New.
+ * testsuite/23_containers/unordered_map/insert/map_single_move-2.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_map/insert/array_syntax_move.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multimap/insert/
+ multimap_single_move-1.cc: Likewise.
+ * testsuite/23_containers/unordered_multimap/insert/
+ multimap_single_move-2.cc: Likewise.
+ * testsuite/23_containers/unordered_set/insert/set_single_move.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multiset/insert/
+ multiset_single_move.cc: Likewise.
+
+ * testsuite/23_containers/unordered_map/insert/array_syntax.cc:
+ Minor cosmetic changes.
+
2010-10-27 Jason Merrill <jason@redhat.com>
* include/std/type_traits (is_literal_type): New.
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index dd8c1c22349..343a12267fd 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -178,9 +178,10 @@ namespace std
size_type _M_begin_bucket_index; // First non-empty bucket.
size_type _M_element_count;
_RehashPolicy _M_rehash_policy;
-
- _Node*
- _M_allocate_node(const value_type& __v);
+
+ template<typename... _Args>
+ _Node*
+ _M_allocate_node(_Args&&... __args);
void
_M_deallocate_node(_Node* __n);
@@ -360,11 +361,27 @@ namespace std
std::pair<const_iterator, const_iterator>
equal_range(const key_type& __k) const;
- private: // Find, insert and erase helper functions
- // ??? This dispatching is a workaround for the fact that we don't
- // have partial specialization of member templates; it would be
- // better to just specialize insert on __unique_keys. There may be a
- // cleaner workaround.
+ private:
+ // Find, insert and erase helper functions
+ _Node*
+ _M_find_node(_Node*, const key_type&,
+ typename _Hashtable::_Hash_code_type) const;
+
+ template<typename _Pair>
+ iterator
+ _M_insert_bucket(_Pair&&, size_type,
+ typename _Hashtable::_Hash_code_type);
+
+ template<typename _Pair>
+ std::pair<iterator, bool>
+ _M_insert(_Pair&&, std::true_type);
+
+ template<typename _Pair>
+ iterator
+ _M_insert(_Pair&&, std::false_type);
+
+ public:
+ // Insert and erase
typedef typename std::conditional<__unique_keys,
std::pair<iterator, bool>,
iterator>::type
@@ -376,30 +393,39 @@ namespace std
>::type
_Insert_Conv_Type;
- _Node*
- _M_find_node(_Node*, const key_type&,
- typename _Hashtable::_Hash_code_type) const;
-
- iterator
- _M_insert_bucket(const value_type&, size_type,
- typename _Hashtable::_Hash_code_type);
-
- std::pair<iterator, bool>
- _M_insert(const value_type&, std::true_type);
+ _Insert_Return_Type
+ insert(const value_type& __v)
+ { return _M_insert(__v, std::integral_constant<bool, __unique_keys>()); }
iterator
- _M_insert(const value_type&, std::false_type);
+ insert(const_iterator, const value_type& __v)
+ { return _Insert_Conv_Type()(insert(__v)); }
- public:
- // Insert and erase
_Insert_Return_Type
- insert(const value_type& __v)
- { return _M_insert(__v, std::integral_constant<bool,
- __unique_keys>()); }
+ insert(value_type&& __v)
+ { return _M_insert(std::move(__v),
+ std::integral_constant<bool, __unique_keys>()); }
iterator
- insert(const_iterator, const value_type& __v)
- { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
+ insert(const_iterator, value_type&& __v)
+ { return _Insert_Conv_Type()(insert(std::move(__v))); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<!__constant_iterators
+ && std::is_convertible<_Pair,
+ value_type>::value>::type>
+ _Insert_Return_Type
+ insert(_Pair&& __v)
+ { return _M_insert(std::forward<_Pair>(__v),
+ std::integral_constant<bool, __unique_keys>()); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<!__constant_iterators
+ && std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __v)
+ { return _Insert_Conv_Type()(insert(std::forward<_Pair>(__v))); }
template<typename _InputIterator>
void
@@ -438,26 +464,27 @@ namespace std
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::_Node*
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_allocate_node(const value_type& __v)
- {
- _Node* __n = _M_node_allocator.allocate(1);
- __try
- {
- _M_node_allocator.construct(__n, __v);
- __n->_M_next = 0;
- return __n;
- }
- __catch(...)
- {
- _M_node_allocator.deallocate(__n, 1);
- __throw_exception_again;
- }
- }
+ template<typename... _Args>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::_Node*
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_allocate_node(_Args&&... __args)
+ {
+ _Node* __n = _M_node_allocator.allocate(1);
+ __try
+ {
+ _M_node_allocator.construct(__n, std::forward<_Args>(__args)...);
+ __n->_M_next = 0;
+ return __n;
+ }
+ __catch(...)
+ {
+ _M_node_allocator.deallocate(__n, 1);
+ __throw_exception_again;
+ }
+ }
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
@@ -871,111 +898,117 @@ namespace std
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert_bucket(const value_type& __v, size_type __n,
- typename _Hashtable::_Hash_code_type __code)
- {
- std::pair<bool, std::size_t> __do_rehash
- = _M_rehash_policy._M_need_rehash(_M_bucket_count,
- _M_element_count, 1);
+ template<typename _Pair>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert_bucket(_Pair&& __v, size_type __n,
+ typename _Hashtable::_Hash_code_type __code)
+ {
+ std::pair<bool, std::size_t> __do_rehash
+ = _M_rehash_policy._M_need_rehash(_M_bucket_count,
+ _M_element_count, 1);
- // Allocate the new node before doing the rehash so that we don't
- // do a rehash if the allocation throws.
- _Node* __new_node = _M_allocate_node(__v);
+ if (__do_rehash.first)
+ {
+ const key_type& __k = this->_M_extract(__v);
+ __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
+ }
- __try
- {
- if (__do_rehash.first)
- {
- const key_type& __k = this->_M_extract(__v);
- __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
+ // Allocate the new node before doing the rehash so that we don't
+ // do a rehash if the allocation throws.
+ _Node* __new_node = _M_allocate_node(std::forward<_Pair>(__v));
+
+ __try
+ {
+ if (__do_rehash.first)
_M_rehash(__do_rehash.second);
- }
- __new_node->_M_next = _M_buckets[__n];
- this->_M_store_code(__new_node, __code);
- _M_buckets[__n] = __new_node;
- ++_M_element_count;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
- return iterator(__new_node, _M_buckets + __n);
- }
- __catch(...)
- {
- _M_deallocate_node(__new_node);
- __throw_exception_again;
- }
- }
+ __new_node->_M_next = _M_buckets[__n];
+ this->_M_store_code(__new_node, __code);
+ _M_buckets[__n] = __new_node;
+ ++_M_element_count;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
+ return iterator(__new_node, _M_buckets + __n);
+ }
+ __catch(...)
+ {
+ _M_deallocate_node(__new_node);
+ __throw_exception_again;
+ }
+ }
// Insert v if no element with its key is already present.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- std::pair<typename _Hashtable<_Key, _Value, _Allocator,
- _ExtractKey, _Equal, _H1,
- _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator, bool>
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert(const value_type& __v, std::true_type)
- {
- const key_type& __k = this->_M_extract(__v);
- typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
- size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
-
- if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
- return std::make_pair(iterator(__p, _M_buckets + __n), false);
- return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
- }
+ template<typename _Pair>
+ std::pair<typename _Hashtable<_Key, _Value, _Allocator,
+ _ExtractKey, _Equal, _H1,
+ _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator, bool>
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert(_Pair&& __v, std::true_type)
+ {
+ const key_type& __k = this->_M_extract(__v);
+ typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
+ size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+
+ if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
+ return std::make_pair(iterator(__p, _M_buckets + __n), false);
+ return std::make_pair(_M_insert_bucket(std::forward<_Pair>(__v),
+ __n, __code), true);
+ }
// Insert v unconditionally.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert(const value_type& __v, std::false_type)
- {
- std::pair<bool, std::size_t> __do_rehash
- = _M_rehash_policy._M_need_rehash(_M_bucket_count,
- _M_element_count, 1);
- if (__do_rehash.first)
- _M_rehash(__do_rehash.second);
+ template<typename _Pair>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert(_Pair&& __v, std::false_type)
+ {
+ std::pair<bool, std::size_t> __do_rehash
+ = _M_rehash_policy._M_need_rehash(_M_bucket_count,
+ _M_element_count, 1);
+ if (__do_rehash.first)
+ _M_rehash(__do_rehash.second);
- const key_type& __k = this->_M_extract(__v);
- typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
- size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+ const key_type& __k = this->_M_extract(__v);
+ typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
+ size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- // First find the node, avoid leaking new_node if compare throws.
- _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
- _Node* __new_node = _M_allocate_node(__v);
+ // First find the node, avoid leaking new_node if compare throws.
+ _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
+ _Node* __new_node = _M_allocate_node(std::forward<_Pair>(__v));
- if (__prev)
- {
- __new_node->_M_next = __prev->_M_next;
- __prev->_M_next = __new_node;
- }
- else
- {
- __new_node->_M_next = _M_buckets[__n];
- _M_buckets[__n] = __new_node;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
- }
- this->_M_store_code(__new_node, __code);
+ if (__prev)
+ {
+ __new_node->_M_next = __prev->_M_next;
+ __prev->_M_next = __new_node;
+ }
+ else
+ {
+ __new_node->_M_next = _M_buckets[__n];
+ _M_buckets[__n] = __new_node;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
+ }
+ this->_M_store_code(__new_node, __code);
- ++_M_element_count;
- return iterator(__new_node, _M_buckets + __n);
- }
+ ++_M_element_count;
+ return iterator(__new_node, _M_buckets + __n);
+ }
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 694d0ffdeb4..3d76839f7f0 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -56,6 +56,14 @@ namespace __detail
return __distance_fw(__first, __last, _Tag());
}
+ struct _Select1st
+ {
+ template<typename _Pair>
+ const typename _Pair::first_type&
+ operator()(const _Pair& __pair) const
+ { return __pair.first; }
+ };
+
// Auxiliary types used for all instantiations of _Hashtable: nodes
// and iterators.
@@ -497,25 +505,28 @@ namespace __detail
// the form pair<T1, T2> and a key extraction policy that returns the
// first part of the pair, the hashtable gets a mapped_type typedef.
// If it satisfies those criteria and also has unique keys, then it
- // also gets an operator[].
+ // also gets an operator[].
template<typename _Key, typename _Value, typename _Ex, bool __unique,
typename _Hashtable>
struct _Map_base { };
template<typename _Key, typename _Pair, typename _Hashtable>
- struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
+ struct _Map_base<_Key, _Pair, _Select1st, false, _Hashtable>
{
typedef typename _Pair::second_type mapped_type;
};
template<typename _Key, typename _Pair, typename _Hashtable>
- struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
+ struct _Map_base<_Key, _Pair, _Select1st, true, _Hashtable>
{
typedef typename _Pair::second_type mapped_type;
mapped_type&
operator[](const _Key& __k);
+ mapped_type&
+ operator[](_Key&& __k);
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 761. unordered_map needs an at() member function.
mapped_type&
@@ -526,9 +537,9 @@ namespace __detail
};
template<typename _Key, typename _Pair, typename _Hashtable>
- typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
+ typename _Map_base<_Key, _Pair, _Select1st,
true, _Hashtable>::mapped_type&
- _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
+ _Map_base<_Key, _Pair, _Select1st, true, _Hashtable>::
operator[](const _Key& __k)
{
_Hashtable* __h = static_cast<_Hashtable*>(this);
@@ -545,10 +556,30 @@ namespace __detail
}
template<typename _Key, typename _Pair, typename _Hashtable>
- typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
+ typename _Map_base<_Key, _Pair, _Select1st,
+ true, _Hashtable>::mapped_type&
+ _Map_base<_Key, _Pair, _Select1st, true, _Hashtable>::
+ operator[](_Key&& __k)
+ {
+ _Hashtable* __h = static_cast<_Hashtable*>(this);
+ typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
+ std::size_t __n = __h->_M_bucket_index(__k, __code,
+ __h->_M_bucket_count);
+
+ typename _Hashtable::_Node* __p =
+ __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ if (!__p)
+ return __h->_M_insert_bucket(std::make_pair(std::move(__k),
+ mapped_type()),
+ __n, __code)->second;
+ return (__p->_M_v).second;
+ }
+
+ template<typename _Key, typename _Pair, typename _Hashtable>
+ typename _Map_base<_Key, _Pair, _Select1st,
true, _Hashtable>::mapped_type&
- _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
- at(const _Key& __k)
+ _Map_base<_Key, _Pair, _Select1st, true, _Hashtable>::
+ at(const _Key& __k)
{
_Hashtable* __h = static_cast<_Hashtable*>(this);
typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
@@ -563,10 +594,10 @@ namespace __detail
}
template<typename _Key, typename _Pair, typename _Hashtable>
- const typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
+ const typename _Map_base<_Key, _Pair, _Select1st,
true, _Hashtable>::mapped_type&
- _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
- at(const _Key& __k) const
+ _Map_base<_Key, _Pair, _Select1st, true, _Hashtable>::
+ at(const _Key& __k) const
{
const _Hashtable* __h = static_cast<const _Hashtable*>(this);
typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 08058c1a94f..efd61319152 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -41,14 +41,14 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
bool __cache_hash_code = false>
class __unordered_map
: public _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc,
- std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
+ __detail::_Select1st, _Pred,
_Hash, __detail::_Mod_range_hashing,
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy,
__cache_hash_code, false, true>
{
typedef _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc,
- std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
+ __detail::_Select1st, _Pred,
_Hash, __detail::_Mod_range_hashing,
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy,
@@ -69,7 +69,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
template<typename _InputIterator>
@@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
__unordered_map(initializer_list<value_type> __l,
@@ -91,7 +91,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
: _Base(__l.begin(), __l.end(), __n, __hf,
__detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
__unordered_map&
@@ -111,7 +111,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
class __unordered_multimap
: public _Hashtable<_Key, std::pair<const _Key, _Tp>,
_Alloc,
- std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
+ __detail::_Select1st, _Pred,
_Hash, __detail::_Mod_range_hashing,
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy,
@@ -119,7 +119,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
{
typedef _Hashtable<_Key, std::pair<const _Key, _Tp>,
_Alloc,
- std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
+ __detail::_Select1st, _Pred,
_Hash, __detail::_Mod_range_hashing,
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy,
@@ -140,7 +140,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
@@ -152,7 +152,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
__unordered_multimap(initializer_list<value_type> __l,
@@ -163,7 +163,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
: _Base(__l.begin(), __l.end(), __n, __hf,
__detail::_Mod_range_hashing(),
__detail::_Default_ranged_hash(),
- __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
+ __eql, __detail::_Select1st(), __a)
{ }
__unordered_multimap&
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 2e2f9122ee0..6f37e040a26 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -190,6 +190,28 @@ namespace __debug
return iterator(__res.first, this);
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ std::pair<iterator, bool>
+ insert(_Pair&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::forward<_Pair>(__obj));
+ return std::make_pair(iterator(__res.first, this), __res.second);
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::forward<_Pair>(__obj));
+ return iterator(__res.first, this);
+ }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
@@ -444,6 +466,20 @@ namespace __debug
insert(const_iterator, const value_type& __obj)
{ return iterator(_Base::insert(__obj), this); }
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(_Pair&& __obj)
+ { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __obj)
+ { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index ea90c675476..1d42905e236 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -190,6 +190,22 @@ namespace __debug
return iterator(__res.first, this);
}
+ std::pair<iterator, bool>
+ insert(value_type&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::move(__obj));
+ return std::make_pair(iterator(__res.first, this), __res.second);
+ }
+
+ iterator
+ insert(const_iterator, value_type&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::move(__obj));
+ return iterator(__res.first, this);
+ }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
@@ -440,6 +456,14 @@ namespace __debug
insert(const_iterator, const value_type& __obj)
{ return iterator(_Base::insert(__obj), this); }
+ iterator
+ insert(value_type&& __obj)
+ { return iterator(_Base::insert(std::move(__obj)), this); }
+
+ iterator
+ insert(const_iterator, value_type&& __obj)
+ { return iterator(_Base::insert(std::move(__obj)), this); }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map
index 2dec1f2a268..18563d87508 100644
--- a/libstdc++-v3/include/profile/unordered_map
+++ b/libstdc++-v3/include/profile/unordered_map
@@ -191,6 +191,31 @@ namespace __profile
return __res;
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ std::pair<iterator, bool>
+ insert(_Pair&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res
+ = _Base::insert(std::forward<_Pair>(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
@@ -420,11 +445,35 @@ namespace __profile
insert(const_iterator __iter, const value_type& __v)
{
size_type __old_size = _Base::bucket_count();
- iterator __res =_Base::insert(__iter, __v);
+ iterator __res = _Base::insert(__iter, __v);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(_Pair&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(std::forward<_Pair>(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set
index 2dade092024..f46cf5c8bdd 100644
--- a/libstdc++-v3/include/profile/unordered_set
+++ b/libstdc++-v3/include/profile/unordered_set
@@ -174,7 +174,7 @@ namespace __profile
std::pair<iterator, bool>
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
+ size_type __old_size = _Base::bucket_count();
std::pair<iterator, bool> __res = _Base::insert(__obj);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
@@ -189,6 +189,24 @@ namespace __profile
return __res;
}
+ std::pair<iterator, bool>
+ insert(value_type&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ iterator
+ insert(const_iterator __iter, value_type&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
@@ -406,13 +424,31 @@ namespace __profile
iterator
insert(const_iterator __iter, const value_type& __v)
- {
+ {
size_type __old_size = _Base::bucket_count();
iterator __res = _Base::insert(__iter, __v);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
}
+ iterator
+ insert(value_type&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ iterator
+ insert(const_iterator __iter, value_type&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
index 11fddbb39dd..91f58799a58 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
@@ -29,25 +29,24 @@ void test01()
bool test __attribute__((unused)) = true;
typedef std::unordered_map<std::string, int> Map;
- typedef std::pair<const std::string, int> Pair;
Map m;
- VERIFY(m.empty());
+ VERIFY( m.empty() );
m["red"] = 17;
- VERIFY(m.size() == 1);
- VERIFY(m.begin()->first == "red");
- VERIFY(m.begin()->second == 17);
- VERIFY(m["red"] == 17);
+ VERIFY( m.size() == 1 );
+ VERIFY( m.begin()->first == "red" );
+ VERIFY( m.begin()->second == 17 );
+ VERIFY( m["red"] == 17 );
m["blue"] = 9;
- VERIFY(m.size() == 2);
- VERIFY(m["blue"] == 9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m["blue"] == 9 );
m["red"] = 5;
- VERIFY(m.size() == 2);
- VERIFY(m["red"] == 5);
- VERIFY(m["blue"] == 9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m["red"] == 5 );
+ VERIFY( m["blue"] == 9 );
}
int main()
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc
new file mode 100644
index 00000000000..b0729e32712
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc
@@ -0,0 +1,59 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Array version of insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m[rvalstruct(1)] = rvalstruct(17);
+ VERIFY( m.size() == 1 );
+ VERIFY( (m.begin()->first).val == 1 );
+ VERIFY( (m.begin()->second).val == 17 );
+ VERIFY( m[rvalstruct(1)].val == 17 );
+
+ m[rvalstruct(2)] = rvalstruct(9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m[rvalstruct(2)].val == 9 );
+
+ m[rvalstruct(1)] = rvalstruct(5);
+ VERIFY( m.size() == 2 );
+ VERIFY( m[rvalstruct(1)].val == 5 );
+ VERIFY( m[rvalstruct(2)].val == 9 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc
new file mode 100644
index 00000000000..45186ce459b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc
@@ -0,0 +1,76 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty());
+
+ std::pair<Map::iterator, bool> p = m.insert(Pair(1, rvalstruct(3)));
+ VERIFY( p.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( p.first == m.begin() );
+ VERIFY( p.first->first == 1 );
+ VERIFY( (p.first->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ std::pair<Map::iterator, bool> p1 = m.insert(Pair(2, rvalstruct(3)));
+ std::pair<Map::iterator, bool> p2 = m.insert(Pair(2, rvalstruct(7)));
+
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( p1.first->first == 2 );
+ VERIFY( (p2.first->second).val == 3 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc
new file mode 100644
index 00000000000..76b6bba0077
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc
@@ -0,0 +1,79 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty());
+
+ std::pair<Map::iterator, bool> p = m.insert(Pair(rvalstruct(1),
+ rvalstruct(3)));
+ VERIFY( p.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( p.first == m.begin() );
+ VERIFY( (p.first->first).val == 1 );
+ VERIFY( (p.first->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ std::pair<Map::iterator, bool> p1 = m.insert(Pair(rvalstruct(2),
+ rvalstruct(3)));
+ std::pair<Map::iterator, bool> p2 = m.insert(Pair(rvalstruct(2),
+ rvalstruct(7)));
+
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( (p1.first->first).val == 2 );
+ VERIFY( (p2.first->second).val == 3 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc
new file mode 100644
index 00000000000..4c933069c46
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc
@@ -0,0 +1,80 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ Map::iterator i = m.insert(Pair(1, rvalstruct(3)));
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( i == m.begin() );
+ VERIFY( i->first == 1 );
+ VERIFY( (i->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m.insert(Pair(2, rvalstruct(3)));
+ m.insert(Pair(2, rvalstruct(7)));
+
+ VERIFY( m.size() == 2 );
+ VERIFY( std::distance(m.begin(), m.end()) == 2 );
+
+ Map::iterator i1 = m.begin();
+ Map::iterator i2 = i1;
+ ++i2;
+
+ VERIFY( i1->first == 2 );
+ VERIFY( i2->first == 2 );
+ VERIFY( ((i1->second).val == 3 && (i2->second).val == 7)
+ || ((i1->second).val == 7 && (i2->second).val == 3) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc
new file mode 100644
index 00000000000..e9008b46156
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc
@@ -0,0 +1,80 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ Map::iterator i = m.insert(Pair(rvalstruct(1), rvalstruct(3)));
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( i == m.begin() );
+ VERIFY( (i->first).val == 1 );
+ VERIFY( (i->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m.insert(Pair(rvalstruct(2), rvalstruct(3)));
+ m.insert(Pair(rvalstruct(2), rvalstruct(7)));
+
+ VERIFY( m.size() == 2 );
+ VERIFY( std::distance(m.begin(), m.end()) == 2 );
+
+ Map::iterator i1 = m.begin();
+ Map::iterator i2 = i1;
+ ++i2;
+
+ VERIFY( (i1->first).val == 2 );
+ VERIFY( (i2->first).val == 2 );
+ VERIFY( ((i1->second).val == 3 && (i2->second).val == 7)
+ || ((i1->second).val == 7 && (i2->second).val == 3) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
new file mode 100644
index 00000000000..14b8e16817a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
@@ -0,0 +1,71 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_set>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multiset<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ Set::iterator i = s.insert(rvalstruct(1));
+ VERIFY( s.size() == 1 );
+ VERIFY( std::distance(s.begin(), s.end()) == 1 );
+ VERIFY( i == s.begin() );
+ VERIFY( (*i).val == 1 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multiset<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ s.insert(rvalstruct(2));
+ Set::iterator i = s.insert(rvalstruct(2));
+ VERIFY( s.size() == 2 );
+ VERIFY( std::distance(s.begin(), s.end()) == 2 );
+ VERIFY( (*i).val == 2 );
+
+ Set::iterator i2 = s.begin();
+ ++i2;
+ VERIFY( i == s.begin() || i == i2 );
+ VERIFY( (*(s.begin())).val == 2 && (*i2).val == 2 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc
new file mode 100644
index 00000000000..0b9ad173b0f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc
@@ -0,0 +1,69 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_set>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_set<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ std::pair<Set::iterator, bool> p = s.insert(rvalstruct(1));
+ VERIFY( p.second );
+ VERIFY( s.size() == 1 );
+ VERIFY( std::distance(s.begin(), s.end()) == 1 );
+ VERIFY( p.first == s.begin() );
+ VERIFY( (*p.first).val == 1 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_set<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ std::pair<Set::iterator, bool> p1 = s.insert(rvalstruct(2));
+ std::pair<Set::iterator, bool> p2 = s.insert(rvalstruct(2));
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( s.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( (*p1.first).val == 2 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_rvalref.h b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
index b44d6ddd12d..5610b77cc43 100644
--- a/libstdc++-v3/testsuite/util/testsuite_rvalref.h
+++ b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
@@ -1,7 +1,8 @@
// -*- C++ -*-
// Testing utilities for the rvalue reference.
//
-// Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -27,35 +28,30 @@
namespace __gnu_test
{
- // This class is designed to test libstdc++'s template-based rvalue
- // reference support. It should fail at compile-time if there is an attempt
- // to copy it (although see note just below).
- class rvalstruct
+ // This class is designed to test libstdc++'s template-based rvalue
+ // reference support. It should fail at compile-time if there is an
+ // attempt to copy it.
+ struct rvalstruct
{
- bool
- operator=(const rvalstruct&);
-
- rvalstruct(const rvalstruct&);
-
- public:
int val;
bool valid;
- rvalstruct() : valid(false)
+ rvalstruct() : val(0), valid(true)
{ }
rvalstruct(int inval) : val(inval), valid(true)
{ }
-
+
rvalstruct&
operator=(int newval)
{
- VERIFY(valid == false);
- val = newval;
+ val = newval;
valid = true;
return *this;
}
+ rvalstruct(const rvalstruct&) = delete;
+
rvalstruct(rvalstruct&& in)
{
VERIFY(in.valid == true);
@@ -65,6 +61,9 @@ namespace __gnu_test
}
rvalstruct&
+ operator=(const rvalstruct&) = delete;
+
+ rvalstruct&
operator=(rvalstruct&& in)
{
VERIFY(in.valid == true);
@@ -75,11 +74,11 @@ namespace __gnu_test
}
};
- bool
+ inline bool
operator==(const rvalstruct& lhs, const rvalstruct& rhs)
{ return lhs.val == rhs.val; }
- bool
+ inline bool
operator<(const rvalstruct& lhs, const rvalstruct& rhs)
{ return lhs.val < rhs.val; }
@@ -156,15 +155,15 @@ namespace __gnu_test
int copycounter::copycount = 0;
- bool
+ inline bool
operator==(const copycounter& lhs, const copycounter& rhs)
{ return lhs.val == rhs.val; }
- bool
+ inline bool
operator<(const copycounter& lhs, const copycounter& rhs)
{ return lhs.val < rhs.val; }
- void
+ inline void
swap(copycounter& lhs, copycounter& rhs)
{
VERIFY(lhs.valid && rhs.valid);
@@ -175,4 +174,21 @@ namespace __gnu_test
} // namespace __gnu_test
+namespace std
+{
+ template<typename _Tp> struct hash;
+
+ /// std::hash specialization for type_index.
+ template<>
+ struct hash<__gnu_test::rvalstruct>
+ {
+ typedef size_t result_type;
+ typedef __gnu_test::rvalstruct argument_type;
+
+ size_t
+ operator()(const __gnu_test::rvalstruct& __rvs) const
+ { return __rvs.val; }
+ };
+}
+
#endif // _GLIBCXX_TESTSUITE_TR1_H