OSDN Git Service

2010-10-28 Paolo Carlini <paolo.carlini@oracle.com>
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Oct 2010 16:01:05 +0000 (16:01 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Oct 2010 16:01:05 +0000 (16:01 +0000)
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

17 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/hashtable.h
libstdc++-v3/include/bits/hashtable_policy.h
libstdc++-v3/include/bits/unordered_map.h
libstdc++-v3/include/debug/unordered_map
libstdc++-v3/include/debug/unordered_set
libstdc++-v3/include/profile/unordered_map
libstdc++-v3/include/profile/unordered_set
libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_rvalref.h

index 05bfcbd..8b5b94a 100644 (file)
@@ -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.
index dd8c1c2..343a122 100644 (file)
@@ -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,
index 694d0ff..3d76839 100644 (file)
@@ -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);
index 08058c1..efd6131 100644 (file)
@@ -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&
index 2e2f912..6f37e04 100644 (file)
@@ -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); }
index ea90c67..1d42905 100644 (file)
@@ -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); }
index 2dec1f2..18563d8 100644 (file)
@@ -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)
index 2dade09..f46cf5c 100644 (file)
@@ -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)
index 11fddbb..91f5879 100644 (file)
@@ -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 (file)
index 0000000..b0729e3
--- /dev/null
@@ -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 (file)
index 0000000..45186ce
--- /dev/null
@@ -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 (file)
index 0000000..76b6bba
--- /dev/null
@@ -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 (file)
index 0000000..4c93306
--- /dev/null
@@ -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 (file)
index 0000000..e9008b4
--- /dev/null
@@ -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 (file)
index 0000000..14b8e16
--- /dev/null
@@ -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 (file)
index 0000000..0b9ad17
--- /dev/null
@@ -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;
+}
index b44d6dd..5610b77 100644 (file)
@@ -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
 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