This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] : Add more move semantics to vector and deque


This fairly lengthy patch adds some move semantics to deque, and a few I
missed on vector. It also adds another element of N1771, the
move_iterator, which wraps an existing iterator so it returns an rvalue
reference, although this is only used in the test-suite.

While this patch is lengthy, it's also all fairly self-explanitory,
although some of it does require being a little careful. The biggest
problem I'm having with this work is trying to preserve as far as
possible the existing semantics on inserting elements of vector and
deque into themselves. This explains why in some cases the testcases
show extra copies being made.

If at some point some "offical decision" is made on the subject, either
for libstdc++-v3 or by the standards committee on which operations
should work and which shouldn't, I'll ensure that as much as should be
defined is defined, and things which aren't defined are caught in debug
mode.

Chris
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/deque.tcc libstdc++-v3/include/bits/deque.tcc
--- libstdc++-v3.so_7.clean/include/bits/deque.tcc	2005-09-10 21:25:14.000000000 +0100
+++ libstdc++-v3/include/bits/deque.tcc	2005-09-16 23:47:01.000000000 +0100
@@ -115,12 +115,12 @@
       const size_type __index = __position - this->_M_impl._M_start;
       if (__index < (size() >> 1))
 	{
-	  std::copy_backward(this->_M_impl._M_start, __position, __next);
+	  std::__move_backward(this->_M_impl._M_start, __position, __next);
 	  pop_front();
 	}
       else
 	{
-	  std::copy(__next, this->_M_impl._M_finish, __position);
+	  std::__move(__next, this->_M_impl._M_finish, __position);
 	  pop_back();
 	}
       return this->_M_impl._M_start + __index;
@@ -144,7 +144,7 @@
 						  - this->_M_impl._M_start);
 	  if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
 	    {
-	      std::copy_backward(this->_M_impl._M_start, __first, __last);
+	      std::__move_backward(this->_M_impl._M_start, __first, __last);
 	      iterator __new_start = this->_M_impl._M_start + __n;
 	      std::_Destroy(this->_M_impl._M_start, __new_start,
 			    _M_get_Tp_allocator());
@@ -154,7 +154,7 @@
 	    }
 	  else
 	    {
-	      std::copy(__last, this->_M_impl._M_finish, __first);
+	      std::__move(__last, this->_M_impl._M_finish, __first);
 	      iterator __new_finish = this->_M_impl._M_finish - __n;
 	      std::_Destroy(__new_finish, this->_M_impl._M_finish,
 			    _M_get_Tp_allocator());
@@ -340,16 +340,19 @@
 
   // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1.
   template <typename _Tp, typename _Alloc>
+  template <typename _Value>
     void
     deque<_Tp, _Alloc>::
-    _M_push_back_aux(const value_type& __t)
+    _M_push_back_aux(const _Value& __t)
     {
-      value_type __t_copy = __t;
+      value_type __t_copy(__t);
       _M_reserve_map_at_back();
       *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
       try
         {
-          this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t_copy);
+	  _Construct_a(this->_M_impl._M_finish._M_cur,
+		       __gnu_cxx::__move(__t_copy),
+		       _M_get_Tp_allocator());
           this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
 					      + 1);
           this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
@@ -363,11 +366,12 @@
 
   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
   template <typename _Tp, typename _Alloc>
+  template <typename _Value>
     void
     deque<_Tp, _Alloc>::
-    _M_push_front_aux(const value_type& __t)
+    _M_push_front_aux(const _Value& __t)
     {
-      value_type __t_copy = __t;
+      value_type __t_copy(__t);
       _M_reserve_map_at_front();
       *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
       try
@@ -375,7 +379,9 @@
           this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
 					     - 1);
           this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
-          this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t_copy);
+	  _Construct_a(this->_M_impl._M_start._M_cur,
+		       __gnu_cxx::__move(__t_copy),
+		       _M_get_Tp_allocator());
         }
       catch(...)
         {
@@ -475,27 +481,27 @@
       value_type __x_copy = __x; // XXX copy
       if (static_cast<size_type>(__index) < size() / 2)
 	{
-	  push_front(front());
-	  iterator __front1 = this->_M_impl._M_start;
+	  push_front(__gnu_cxx::__move(front()));
+	  iterator __front1 = begin();
 	  ++__front1;
 	  iterator __front2 = __front1;
 	  ++__front2;
 	  __pos = this->_M_impl._M_start + __index;
 	  iterator __pos1 = __pos;
 	  ++__pos1;
-	  std::copy(__front2, __pos1, __front1);
+	  std::__move(__front2, __pos1, __front1);
 	}
       else
 	{
-	  push_back(back());
-	  iterator __back1 = this->_M_impl._M_finish;
+	  push_back(__gnu_cxx::__move(back()));
+	  iterator __back1 = end();
 	  --__back1;
 	  iterator __back2 = __back1;
 	  --__back2;
 	  __pos = this->_M_impl._M_start + __index;
-	  std::copy_backward(__pos, __back2, __back1);
+	  std::__move_backward(__pos, __back2, __back1);
 	}
-      *__pos = __x_copy;
+      *__pos = __gnu_cxx::__move(__x_copy);
       return __pos;
     }
 
@@ -518,16 +524,16 @@
 		{
 		  iterator __start_n = (this->_M_impl._M_start
 					+ difference_type(__n));
-		  std::__uninitialized_copy_a(this->_M_impl._M_start,
+		  std::__uninitialized_move_a(this->_M_impl._M_start,
 					      __start_n, __new_start,
 					      _M_get_Tp_allocator());
 		  this->_M_impl._M_start = __new_start;
-		  std::copy(__start_n, __pos, __old_start);
-		  fill(__pos - difference_type(__n), __pos, __x_copy);
+		  std::__move(__start_n, __pos, __old_start);
+		  std::fill(__pos - difference_type(__n), __pos, __x_copy);
 		}
 	      else
 		{
-		  std::__uninitialized_copy_fill(this->_M_impl._M_start,
+		  std::__uninitialized_move_fill(this->_M_impl._M_start,
 						 __pos, __new_start,
 						 this->_M_impl._M_start,
 						 __x_copy,
@@ -556,17 +562,17 @@
 		{
 		  iterator __finish_n = (this->_M_impl._M_finish
 					 - difference_type(__n));
-		  std::__uninitialized_copy_a(__finish_n,
+		  std::__uninitialized_move_a(__finish_n,
 					      this->_M_impl._M_finish,
 					      this->_M_impl._M_finish,
 					      _M_get_Tp_allocator());
 		  this->_M_impl._M_finish = __new_finish;
-		  std::copy_backward(__pos, __finish_n, __old_finish);
+		  std::__move_backward(__pos, __finish_n, __old_finish);
 		  std::fill(__pos, __pos + difference_type(__n), __x_copy);
 		}
 	      else
 		{
-		  std::__uninitialized_fill_copy(this->_M_impl._M_finish,
+		  std::__uninitialized_fill_move(this->_M_impl._M_finish,
 						 __pos + difference_type(__n),
 						 __x_copy, __pos,
 						 this->_M_impl._M_finish,
@@ -605,18 +611,18 @@
 		  {
 		    iterator __start_n = (this->_M_impl._M_start
 					  + difference_type(__n));
-		    std::__uninitialized_copy_a(this->_M_impl._M_start,
+		    std::__uninitialized_move_a(this->_M_impl._M_start,
 						__start_n, __new_start,
 						_M_get_Tp_allocator());
 		    this->_M_impl._M_start = __new_start;
-		    std::copy(__start_n, __pos, __old_start);
+		    std::__move(__start_n, __pos, __old_start);
 		    std::copy(__first, __last, __pos - difference_type(__n));
 		  }
 		else
 		  {
 		    _ForwardIterator __mid = __first;
 		    std::advance(__mid, difference_type(__n) - __elemsbefore);
-		    std::__uninitialized_copy_copy(this->_M_impl._M_start,
+		    std::__uninitialized_move_copy(this->_M_impl._M_start,
 						   __pos, __first, __mid,
 						   __new_start,
 						   _M_get_Tp_allocator());
@@ -644,19 +650,19 @@
 		{
 		  iterator __finish_n = (this->_M_impl._M_finish
 					 - difference_type(__n));
-		  std::__uninitialized_copy_a(__finish_n,
+		  std::__uninitialized_move_a(__finish_n,
 					      this->_M_impl._M_finish,
 					      this->_M_impl._M_finish,
 					      _M_get_Tp_allocator());
 		  this->_M_impl._M_finish = __new_finish;
-		  std::copy_backward(__pos, __finish_n, __old_finish);
+		  std::__move_backward(__pos, __finish_n, __old_finish);
 		  std::copy(__first, __last, __pos);
 		}
               else
 		{
 		  _ForwardIterator __mid = __first;
 		  std::advance(__mid, __elemsafter);
-		  std::__uninitialized_copy_copy(__mid, __last, __pos,
+		  std::__uninitialized_copy_move(__mid, __last, __pos,
 						 this->_M_impl._M_finish,
 						 this->_M_impl._M_finish,
 						 _M_get_Tp_allocator());
@@ -733,13 +739,13 @@
 					 - __new_num_nodes) / 2
 	                 + (__add_at_front ? __nodes_to_add : 0);
 	  if (__new_nstart < this->_M_impl._M_start._M_node)
-	    std::copy(this->_M_impl._M_start._M_node,
-		    this->_M_impl._M_finish._M_node + 1,
-		    __new_nstart);
+	    std::__move(this->_M_impl._M_start._M_node,
+			this->_M_impl._M_finish._M_node + 1,
+			__new_nstart);
 	  else
-	    std::copy_backward(this->_M_impl._M_start._M_node,
-			       this->_M_impl._M_finish._M_node + 1,
-			       __new_nstart + __old_num_nodes);
+	    std::__move_backward(this->_M_impl._M_start._M_node,
+				 this->_M_impl._M_finish._M_node + 1,
+				 __new_nstart + __old_num_nodes);
 	}
       else
 	{
@@ -750,9 +756,9 @@
 	  _Map_pointer __new_map = this->_M_allocate_map(__new_map_size);
 	  __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
 	                 + (__add_at_front ? __nodes_to_add : 0);
-	  std::copy(this->_M_impl._M_start._M_node,
-		    this->_M_impl._M_finish._M_node + 1,
-		    __new_nstart);
+	  std::__move(this->_M_impl._M_start._M_node,
+		      this->_M_impl._M_finish._M_node + 1,
+		      __new_nstart);
 	  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
 
 	  this->_M_impl._M_map = __new_map;
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/moveable.h libstdc++-v3/include/bits/moveable.h
--- libstdc++-v3.so_7.clean/include/bits/moveable.h	2005-09-14 13:48:54.000000000 +0100
+++ libstdc++-v3/include/bits/moveable.h	2005-09-16 23:52:56.000000000 +0100
@@ -35,6 +35,12 @@
 #ifndef _GLIBCXX_MOVEABLE_H
 #define _GLIBCXX_MOVEABLE_H	1
 
+// Would include <iterator>, but we only need iterator_traits and need to
+// avoid cyclic dependancies.
+#include <bits/c++config.h>
+#include <cstddef>
+#include <bits/stl_iterator_base_types.h>
+
 namespace __gnu_cxx
 {
 
@@ -83,6 +89,159 @@
     __move(const _Tp& __in)
     { return __in; }
 
+  /**
+   *  @if maint
+   *  This class takes a range of iterators and wraps them so when they
+   *  are dereferenced they return any rvalue reference instead of a plain
+   *  reference. While you can wrap forward and better classes
+   *  of iterators, the resulting iterators aren't really iterators of that
+   *  type, as operator* returns by value not reference.
+   *  @endif
+   */
+  template <class _Iterator>
+    struct __move_iterator
+    {
+      _Iterator __iterator;
+
+      typedef _Iterator __iterator_type;
+      typedef typename std::iterator_traits<_Iterator>::difference_type
+        difference_type;
+      typedef typename std::iterator_traits<_Iterator>::pointer
+        pointer;
+      typedef typename std::iterator_traits<_Iterator>::value_type
+        value_type;
+      typedef typename std::iterator_traits<_Iterator>::iterator_category
+        iterator_category;
+      typedef typename __move_helper<value_type>::__type reference;
+
+      __move_iterator() 
+      { }
+    
+      explicit __move_iterator(__iterator_type __in) 
+      : __iterator(__in)
+      { }
+    
+      template <class _Tp> 
+	__move_iterator(const __move_iterator<_Tp>& __in)
+	: __iterator(__in)
+	{ }
+
+      __iterator_type 
+      base() const
+      { return __iterator; }
+    
+      reference 
+      operator*() const
+      { return __gnu_cxx::__move(*__iterator); }
+    
+      pointer   
+      operator->() const
+      { return &**this; }
+
+      __move_iterator& 
+      operator++()
+      { ++__iterator; }
+    
+      __move_iterator  
+      operator++(int)
+      { 
+	__move_iterator __tmp(*this);
+	++__iterator;
+	return __tmp;
+      }
+      
+      __move_iterator& 
+      operator--()
+      { --__iterator; }
+    
+      __move_iterator  
+      operator--(int)
+      {
+	__move_iterator __tmp(*this);
+	--__iterator;
+	return __tmp;
+      }
+
+      __move_iterator  
+      operator+(difference_type __distance) const
+      { return __move_iterator(__iterator + __distance); }
+
+      __move_iterator& 
+      operator+=(difference_type __distance)
+      {
+	__iterator += __distance;
+	return *this;
+      }
+    
+      __move_iterator  
+      operator-(difference_type __distance) const
+      { return __move_iterator(__iterator - __distance); }
+    
+      __move_iterator& 
+      operator-=(difference_type __distance)
+      { 
+	__iterator -= __distance;
+	return *this;
+      }
+    
+      reference 
+      operator[](difference_type __distance) const
+      { return __iterator[__distance]; }
+    };
+
+  template <class _Iterator>
+    bool
+    operator==(const __move_iterator<_Iterator>& __lhs,
+	       const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator == __rhs.__iterator; }
+
+  template <class _Iterator>
+    bool
+    operator!=(const __move_iterator<_Iterator>& __lhs,
+	       const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator != __rhs.__iterator; }
+
+  template <class _Iterator>
+    bool
+    operator<(const __move_iterator<_Iterator>& __lhs,
+	      const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator < __rhs.__iterator; }
+
+  template <class _Iterator>
+    bool
+    operator<=(const __move_iterator<_Iterator>& __lhs,
+	       const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator <= __rhs.__iterator; }
+
+  template <class _Iterator>
+    bool
+    operator>(const __move_iterator<_Iterator>& __lhs,
+	      const __move_iterator<_Iterator>& __rhs)
+    { return __rhs.__iterator > __lhs.__iterator; }
+
+  template <class _Iterator>
+    bool
+    operator>=(const __move_iterator<_Iterator>& __lhs,
+	       const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator >= __rhs.__iterator; }
+
+  template <class _Iterator>
+    typename __move_iterator<_Iterator>::difference_type
+    operator-(const __move_iterator<_Iterator>& __lhs,
+	      const __move_iterator<_Iterator>& __rhs)
+    { return __lhs.__iterator - __rhs.__iterator; }
+
+  template <class _Iterator>
+    __move_iterator<_Iterator>
+    operator+(typename __move_iterator<_Iterator>::difference_type __distance,
+	      const __move_iterator<_Iterator>& __iterator)
+    { return __distance + __iterator; }
+
+  template <class _Iterator>
+    __move_iterator<_Iterator>
+    __make_move_iterator(const _Iterator& __iterator)
+    { return __move_iterator<_Iterator>(__iterator); }
+
 } // namespace __gnu_cxx
 
 #endif
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/stl_construct.h libstdc++-v3/include/bits/stl_construct.h
--- libstdc++-v3.so_7.clean/include/bits/stl_construct.h	2005-09-10 21:25:19.000000000 +0100
+++ libstdc++-v3/include/bits/stl_construct.h	2005-09-17 00:00:33.000000000 +0100
@@ -98,27 +98,28 @@
 
   /**
    * @if maint
-   * Should move construct an object in existing memory by invoking the
-   * allocated object's move constructor, but move construction only occurs
-   * in the specialization below.
+   * The purpose of the _Construct_a function is to wrap the fact that only
+   * some allocators can cope with rvalue references. They are stripped off
+   * for allocators that don't understand them.
    * @endif
    */
   template<typename _T1, typename _T2, typename _Allocator>
     inline void
-    _Construct_move_a(_T1* __p, _T2& __value, _Allocator __alloc)
+    _Construct_a(_T1* __p, _T2& __value, _Allocator __alloc)
     { __alloc.construct(__p, __value); }
-
-  /**
-   * @if maint
-   * Move constructs an object in existing memory by invoking an allocated
-   * object's move constructor.
-   * @endif
-   */    
+  
+  template<typename _T1, typename _T2, typename _Allocator>
+    inline void
+    _Construct_a(_T1* __p, __gnu_cxx::__rvalref<_T2> __value,
+		 _Allocator __alloc)
+    { __alloc.construct(__p, __value.__ref); }
+  
   template<typename _T1, typename _T2, typename _Tp>
     inline void
-    _Construct_move_a(_T1* __p, _T2& __value, allocator<_Tp>)
-    { ::new(static_cast<void*>(__p)) _T1(__gnu_cxx::__move(__value)); }
-
+    _Construct_a(_T1* __p, __gnu_cxx::__rvalref<_T2> __value,
+                 allocator<_Tp>)
+    { ::new(static_cast<void*>(__p)) _T1(__value); }
+		 
   /**
    * @if maint
    * Destroy the object pointed to by a pointer type.
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/stl_deque.h libstdc++-v3/include/bits/stl_deque.h
--- libstdc++-v3.so_7.clean/include/bits/stl_deque.h	2005-09-10 21:25:19.000000000 +0100
+++ libstdc++-v3/include/bits/stl_deque.h	2005-09-16 23:16:00.000000000 +0100
@@ -1054,6 +1054,29 @@
       }
 
       /**
+       *  @brief  Add data to the front of the %deque.
+       *  @param  x  Data to be added.
+       *
+       *  This is a typical stack operation.  The function creates an
+       *  element at the front of the %deque and moves the given
+       *  data to it.  Due to the nature of a %deque this operation
+       *  can be done in constant time.
+       */
+      template<typename _Value_type>
+	void
+	push_front(__gnu_cxx::__rvalref<_Value_type> __x)
+	{
+	  if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
+	    {
+	      _Construct_a(this->_M_impl._M_start._M_cur - 1, __x,
+				_M_get_Tp_allocator());
+	      --this->_M_impl._M_start._M_cur;
+	    }
+	  else
+	    _M_push_front_aux(__x);
+	}
+
+      /**
        *  @brief  Add data to the end of the %deque.
        *  @param  x  Data to be added.
        *
@@ -1076,6 +1099,30 @@
       }
 
       /**
+       *  @brief  Add data to the end of the %deque.
+       *  @param  x  Data to be added.
+       *
+       *  This is a typical stack operation.  The function creates an
+       *  element at the end of the %deque and moves the given data
+       *  to it.  Due to the nature of a %deque this operation can be
+       *  done in constant time.
+       */
+      template<typename _Value_type>
+	void
+	push_back(__gnu_cxx::__rvalref<_Value_type> __x)
+	{
+	  if (this->_M_impl._M_finish._M_cur
+	      != this->_M_impl._M_finish._M_last - 1)
+	    {
+	      _Construct_a(this->_M_impl._M_finish._M_cur, __x,
+				_M_get_Tp_allocator());
+	      ++this->_M_impl._M_finish._M_cur;
+	    }
+	  else
+	    _M_push_back_aux(__x);
+        }
+      
+      /**
        *  @brief  Removes first element.
        *
        *  This is a typical stack operation.  It shrinks the %deque by one.
@@ -1357,8 +1404,10 @@
        *  @brief Helper functions for push_* and pop_*.
        *  @endif
        */
-      void _M_push_back_aux(const value_type&);
-      void _M_push_front_aux(const value_type&);
+      template<typename _Value_type>
+	void _M_push_back_aux(const _Value_type&);
+      template<typename _Value_type>
+	void _M_push_front_aux(const _Value_type&);
       void _M_pop_back_aux();
       void _M_pop_front_aux();
       //@}
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/stl_uninitialized.h libstdc++-v3/include/bits/stl_uninitialized.h
--- libstdc++-v3.so_7.clean/include/bits/stl_uninitialized.h	2005-09-10 21:25:20.000000000 +0100
+++ libstdc++-v3/include/bits/stl_uninitialized.h	2005-09-10 21:29:52.000000000 +0100
@@ -429,6 +429,64 @@
 	}
     }
 
+  // __uninitialized_copy_move
+  // Copies [first1, last1) into [result, result + (last1 - first1)), and
+  //  move [first2, last2) into
+  //  [result, result + (last1 - first1) + (last2 - first2)).
+
+  template<typename _InputIterator1, typename _InputIterator2,
+	   typename _ForwardIterator, typename _Allocator>
+    inline _ForwardIterator
+    __uninitialized_copy_move(_InputIterator1 __first1,
+			      _InputIterator1 __last1,
+			      _InputIterator2 __first2,
+			      _InputIterator2 __last2,
+			      _ForwardIterator __result,
+			      _Allocator __alloc)
+    {
+      _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
+							   __result,
+							   __alloc);
+      try
+	{
+	  return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc);
+	}
+      catch(...)
+	{
+	  std::_Destroy(__result, __mid, __alloc);
+	  __throw_exception_again;
+	}
+    }
+    
+  // __uninitialized_move_copy
+  // Moves [first1, last1) into [result, result + (last1 - first1)), and
+  //  copies [first2, last2) into
+  //  [result, result + (last1 - first1) + (last2 - first2)).
+
+  template<typename _InputIterator1, typename _InputIterator2,
+	   typename _ForwardIterator, typename _Allocator>
+    inline _ForwardIterator
+    __uninitialized_move_copy(_InputIterator1 __first1,
+			      _InputIterator1 __last1,
+			      _InputIterator2 __first2,
+			      _InputIterator2 __last2,
+			      _ForwardIterator __result,
+			      _Allocator __alloc)
+    {
+      _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1,
+							   __result,
+							   __alloc);
+      try
+	{
+	  return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
+	}
+      catch(...)
+	{
+	  std::_Destroy(__result, __mid, __alloc);
+	  __throw_exception_again;
+	}
+    }
+
   // __uninitialized_fill_copy
   // Fills [result, mid) with x, and copies [first, last) into
   //  [mid, mid + (last - first)).
@@ -452,6 +510,31 @@
 	}
     }
 
+  // __uninitialized_fill_move
+  // Fills [result, mid) with x, and moves [first, last) into
+  //  [mid, mid + (last - first)).
+  template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
+	   typename _Allocator>
+    inline _ForwardIterator
+    __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid,
+			      const _Tp& __x, _InputIterator __first,
+			      _InputIterator __last,
+			      _Allocator __alloc)
+    {
+      std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
+      try
+	{
+	  return std::__uninitialized_move_a(__first, __last, __mid, __alloc);
+	}
+      catch(...)
+	{
+	  std::_Destroy(__result, __mid, __alloc);
+	  __throw_exception_again;
+	}
+    }
+
+ 
+
   // __uninitialized_copy_fill
   // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and
   //  fills [first2 + (last1 - first1), last2) with x.
@@ -477,6 +560,32 @@
 	}
     }
 
+  // __uninitialized_move_fill
+  // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and
+  //  fills [first2 + (last1 - first1), last2) with x.
+  template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
+	   typename _Allocator>
+    inline void
+    __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1,
+			      _ForwardIterator __first2,
+			      _ForwardIterator __last2, const _Tp& __x,
+			      _Allocator __alloc)
+    {
+      _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1,
+							    __first2,
+							    __alloc);
+      try
+	{
+	  std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
+	}
+      catch(...)
+	{
+	  std::_Destroy(__first2, __mid2, __alloc);
+	  __throw_exception_again;
+	}
+    }
+
+
 } // namespace std
 
 #endif /* _STL_UNINITIALIZED_H */
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/stl_vector.h libstdc++-v3/include/bits/stl_vector.h
--- libstdc++-v3.so_7.clean/include/bits/stl_vector.h	2005-09-10 21:25:20.000000000 +0100
+++ libstdc++-v3/include/bits/stl_vector.h	2005-09-16 22:53:51.000000000 +0100
@@ -641,6 +641,30 @@
       }
 
       /**
+       *  @brief  Add data to the end of the %vector.
+       *  @param  x  Data to be added.
+       *
+       *  This is a typical stack operation.  The function creates an
+       *  element at the end of the %vector and moves the given data
+       *  to it.  Due to the nature of a %vector this operation can be
+       *  done in constant time if the %vector has preallocated space
+       *  available.
+       */
+      template<typename _Value_type>
+	void
+	push_back(__gnu_cxx::__rvalref<_Value_type> __x)
+	{
+	  if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
+	    {
+	       _Construct_a(this->_M_impl._M_finish, __x,
+			    _M_get_Tp_allocator());
+	      ++this->_M_impl._M_finish;
+	    }
+	  else
+	    _M_insert_aux(end(), __x);
+	}
+      
+      /**
        *  @brief  Removes last element.
        *
        *  This is a typical stack operation. It shrinks the %vector by one.
@@ -962,8 +986,9 @@
       _M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
 
       // Called by insert(p,x)
-      void
-      _M_insert_aux(iterator __position, const value_type& __x);
+      template<typename _Value>
+	void
+	_M_insert_aux(iterator __position, const _Value&);
     };
 
 
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/include/bits/vector.tcc libstdc++-v3/include/bits/vector.tcc
--- libstdc++-v3.so_7.clean/include/bits/vector.tcc	2005-09-10 21:25:21.000000000 +0100
+++ libstdc++-v3/include/bits/vector.tcc	2005-09-16 21:18:58.000000000 +0100
@@ -110,7 +110,7 @@
     erase(iterator __position)
     {
       if (__position + 1 != end())
-        std::copy(__position + 1, end(), __position);
+        std::__move(__position + 1, end(), __position);
       --this->_M_impl._M_finish;
       this->_M_impl.destroy(this->_M_impl._M_finish);
       return __position;
@@ -121,7 +121,7 @@
     vector<_Tp, _Alloc>::
     erase(iterator __first, iterator __last)
     {
-      iterator __i(std::copy(__last, end(), __first));
+      iterator __i(std::__move(__last, end(), __first));
       std::_Destroy(__i, end(), _M_get_Tp_allocator());
       this->_M_impl._M_finish = this->_M_impl._M_finish - (__last - __first);
       return __first;
@@ -244,17 +244,19 @@
       }
 
   template<typename _Tp, typename _Alloc>
+  template<typename _Value>
     void
     vector<_Tp, _Alloc>::
-    _M_insert_aux(iterator __position, const _Tp& __x)
+    _M_insert_aux(iterator __position, const _Value& __x)
     {
       if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
 	{
-	  std::_Construct_move_a(this->_M_impl._M_finish,
-	  			 *(this->_M_impl._M_finish - 1),
-	  			 _M_get_Tp_allocator());
+	  value_type __x_copy(__x);
+	  std::_Construct_a(this->_M_impl._M_finish,
+	  		    __gnu_cxx::__move(*(this->_M_impl._M_finish 
+	  				      - 1)),
+	  		    _M_get_Tp_allocator());
 	  ++this->_M_impl._M_finish;
-	  _Tp __x_copy(__x);
 	  std::__move_backward(__position,
 			       iterator(this->_M_impl._M_finish-2),
 			       iterator(this->_M_impl._M_finish-1));
@@ -282,7 +284,7 @@
 					    __position,
 					    __new_start,
 					    _M_get_Tp_allocator());
-	      this->_M_impl.construct(__new_finish.base(), __x);
+	      _Construct_a(__new_finish.base(), __x, _M_get_Tp_allocator());
 	      ++__new_finish;
 	      __new_finish =
 		std::__uninitialized_move_a(__position,
@@ -346,6 +348,7 @@
 	    }
 	  else
 	    {
+	      value_type __x_copy(__x);
 	      const size_type __old_size = size();
 	      if (this->max_size() - __old_size < __n)
 		__throw_length_error(__N("vector::_M_fill_insert"));
@@ -363,7 +366,7 @@
 		    std::__uninitialized_move_a(begin(), __position,
 						__new_start,
 						_M_get_Tp_allocator());
-		  std::__uninitialized_fill_n_a(__new_finish, __n, __x,
+		  std::__uninitialized_fill_n_a(__new_finish, __n, __x_copy,
 						_M_get_Tp_allocator());
 		  __new_finish += __n;
 		  __new_finish =
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/deque/cons/moveable.cc libstdc++-v3/testsuite/23_containers/deque/cons/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/deque/cons/moveable.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/deque/cons/moveable.cc	2005-09-11 16:02:28.000000000 +0100
@@ -0,0 +1,66 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// { dg-do compile }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+using namespace __gnu_cxx;
+
+// Empty constructor doesn't require a CC
+void
+test01()
+{ std::deque<rvalstruct> d; }
+
+
+// Constructing from a range that returns rvalue references doesn't require 
+// a CC
+void
+test02(rvalstruct* begin, rvalstruct* end)
+{ 
+  std::deque<rvalstruct> d(__make_move_iterator(begin),
+			   __make_move_iterator(end));
+}
+
+// Constructing from a input iterator range that returns rvalue references
+// doesn't require a copy constructor either
+void
+test03(input_iterator_wrapper<rvalstruct> begin,
+       input_iterator_wrapper<rvalstruct> end)
+{ 
+  std::deque<rvalstruct> d(__make_move_iterator(begin),
+			   __make_move_iterator(end));
+}
+
+// Neither does destroying one
+void
+test04(std::deque<rvalstruct>* d)
+{ delete d; }
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/deque/modifiers/moveable.cc libstdc++-v3/testsuite/23_containers/deque/modifiers/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/deque/modifiers/moveable.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/deque/modifiers/moveable.cc	2005-09-17 12:07:38.000000000 +0100
@@ -0,0 +1,141 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+
+// Test deque::push_back makes no unneeded copies.
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::deque<copycounter> a;
+  copycounter c(1);
+  copycounter::copycount = 0;
+  for(int i = 0; i < 1000; ++i)
+    a.push_back(c);
+  VERIFY(copycounter::copycount == 1000);
+}
+
+// Test deque::push_front makes no unneeded copies.
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::deque<copycounter> a;
+  copycounter c(1);
+  copycounter::copycount = 0;
+  for(int i = 0; i < 1000; ++i)
+    a.push_front(c);
+  VERIFY(copycounter::copycount == 1000);
+}
+
+// Test deque::insert makes no unneeded copies.
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::deque<copycounter> a(1000);
+  copycounter c(1);
+  copycounter::copycount = 0;
+  a.insert(a.begin(),c);
+  a.insert(a.end(),c);
+  for(int i = 0; i < 500; ++i)
+    a.insert(a.begin() + i, c);
+  VERIFY(copycounter::copycount == 502);
+}
+
+// Test deque::insert(iterator, value, count) makes no unneeded copies
+// when it has to also rellocate the deque's internal buffer.
+void
+test04()
+{
+  bool test __attribute__((unused)) = true;
+
+  copycounter c(1);
+  std::deque<copycounter> a(10, c);
+  copycounter::copycount = 0;
+  a.insert(a.begin(), 20, c);
+  VERIFY(copycounter::copycount == 20);
+  a.insert(a.end(), 50, c);
+  VERIFY(copycounter::copycount == 70);
+  // NOTE : These values are each one higher than might be expected, as
+  // deque::insert(iterator, value, count) copies the value it is given
+  // when it has to move elements in the deque in case that value is
+  // in the deque.
+  
+  // Near the start
+  a.insert(a.begin() + 10, 100, c);
+  VERIFY(copycounter::copycount == 170 + 1);
+  // Near the end
+  a.insert(a.end() - 10, 1000, c);
+  VERIFY(copycounter::copycount == 1170 + 2);
+}
+
+// Test deque::insert(iterator, value, count) makes no unneeded copies
+// when it doesn't have to rellocate the deque's internal buffer.
+void
+test05()
+{
+  bool test __attribute__((unused)) = true;
+  
+  copycounter c(1);
+  std::deque<copycounter> a(10, c);
+  copycounter::copycount = 0;
+  //a.reserve(1000);
+  a.insert(a.begin(), 20, c);
+  VERIFY(copycounter::copycount == 20 );
+  a.insert(a.end(), 50, c);
+  VERIFY(copycounter::copycount == 70 );
+  
+  // NOTE : These values are each one higher than might be expected, as
+  // deque::insert(iterator, value, count) copies the value it is given
+  // when it has to move elements in the deque in case that value is
+  // in the deque.
+  // Near the start
+  a.insert(a.begin() + 10, 100, c);
+  VERIFY(copycounter::copycount == 170 + 1);
+  // Near the end
+  a.insert(a.end() - 10, 200, c);
+  VERIFY(copycounter::copycount == 370 + 2);
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  return 0;
+}
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/deque/modifiers/moveable2.cc libstdc++-v3/testsuite/23_containers/deque/modifiers/moveable2.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/deque/modifiers/moveable2.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/deque/modifiers/moveable2.cc	2005-09-17 00:06:53.000000000 +0100
@@ -0,0 +1,65 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// { dg-do compile }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+
+void
+test01(std::deque<rvalstruct>& d, rvalstruct* begin, rvalstruct* end)
+{
+  d.assign(__gnu_cxx::__make_move_iterator(begin),
+	   __gnu_cxx::__make_move_iterator(end));
+}
+
+// Test deque::insert(iterator, iterator, iterator) makes no unneeded copies.
+void
+test02(std::deque<rvalstruct>& d, rvalstruct* begin, rvalstruct* end)
+{
+  d.insert(d.begin(), __gnu_cxx::__make_move_iterator(begin), 
+	   __gnu_cxx::__make_move_iterator(end));
+}
+
+// Erasing a single iterator
+void
+test03(std::deque<rvalstruct>& d, std::deque<rvalstruct>::iterator i)
+{ d.erase(i); }
+
+// Erasing a range of iterators
+void
+test04(std::deque<rvalstruct>& d, std::deque<rvalstruct>::iterator begin,
+				   std::deque<rvalstruct>::iterator end)
+{ d.erase(begin, end); }
+
+// Clearing a deque
+void
+test05(std::deque<rvalstruct>& d)
+{ d.clear(); }
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/deque/resize/moveable.cc libstdc++-v3/testsuite/23_containers/deque/resize/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/deque/resize/moveable.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/deque/resize/moveable.cc	2005-09-17 12:07:45.000000000 +0100
@@ -0,0 +1,65 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+
+
+// According to n1771, there should be two resizes, with and without
+// parameter. We only have one at present, whose second parameter defaults
+// to a default-constructed object.
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::deque<copycounter> a;
+  copycounter::copycount = 0;
+  a.resize(10);
+  a.resize(98);
+  a.resize(99);
+  a.resize(100);
+  printf("%d\n", copycounter::copycount);
+  VERIFY(copycounter::copycount == 100);
+  a.resize(99);
+  a.resize(0);
+  VERIFY(copycounter::copycount == 100);
+  a.resize(100);
+  VERIFY(copycounter::copycount == 200);
+  a.clear();
+  VERIFY(copycounter::copycount == 200);
+}
+
+
+int main()
+{
+  test01();
+  return 0;
+}
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/vector/cons/moveable.cc libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/vector/cons/moveable.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc	2005-09-11 15:57:14.000000000 +0100
@@ -0,0 +1,64 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// { dg-do compile }
+
+#include <vector>
+#include <testsuite_iterators.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+using namespace __gnu_cxx;
+
+// Empty constructor doesn't require a copy constructor
+void
+test01()
+{ std::vector<rvalstruct> d; }
+
+// Constructing from a range that returns rvalue references doesn't require a
+// copy constructor
+void
+test02(rvalstruct* begin, rvalstruct* end)
+{ 
+  std::vector<rvalstruct> d(__make_move_iterator(begin),
+			    __make_move_iterator(end));
+}
+
+// Constructing from a input iterator range that returns rvalue references
+// doesn't require a copy constructor either
+void
+test03(input_iterator_wrapper<rvalstruct> begin,
+       input_iterator_wrapper<rvalstruct> end)
+{ 
+  std::vector<rvalstruct> d(__make_move_iterator(begin),
+			    __make_move_iterator(end));
+}
+
+// Neither does destroying one
+void
+test04(std::vector<rvalstruct>* d)
+{ delete d; }
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/vector/modifiers/moveable.cc libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/vector/modifiers/moveable.cc	2005-09-09 10:07:20.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc	2005-09-17 12:06:41.000000000 +0100
@@ -77,6 +77,7 @@
 test03()
 {
   bool test __attribute__((unused)) = true;
+  
   copycounter c(1);
   std::vector<copycounter> a(10, c), b(100, c);
   copycounter::copycount = 0;
@@ -95,17 +96,17 @@
 void
 test04()
 {
-bool test __attribute__((unused)) = true;
+  bool test __attribute__((unused)) = true;
 
   copycounter c(1);
   std::vector<copycounter> a(10, c);
   copycounter::copycount = 0;
   a.insert(a.begin(), 20, c);
-  VERIFY(copycounter::copycount == 20);
+  VERIFY(copycounter::copycount == 20 + 1);
   a.insert(a.end(), 50, c);
-  VERIFY(copycounter::copycount == 70);
+  VERIFY(copycounter::copycount == 70 + 2);
   a.insert(a.begin() + 50, 100, c);
-  VERIFY(copycounter::copycount == 170);
+  VERIFY(copycounter::copycount == 170 + 3);
 }
 
 // Test vector::insert(iterator, value, count) makes no unneeded copies
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/vector/modifiers/moveable2.cc libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable2.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/vector/modifiers/moveable2.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable2.cc	2005-09-17 00:04:25.000000000 +0100
@@ -0,0 +1,69 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// { dg-do compile }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+
+void
+test01(std::vector<rvalstruct>& d, rvalstruct* begin, rvalstruct* end)
+{
+  d.assign(__gnu_cxx::__make_move_iterator(begin),
+	   __gnu_cxx::__make_move_iterator(end));
+}
+
+// Test vector::insert(iterator, iterator, iterator) makes no unneeded copies.
+void
+test02(std::vector<rvalstruct>& d, rvalstruct* begin, rvalstruct* end)
+{
+  d.insert(d.begin(), __gnu_cxx::__make_move_iterator(begin), 
+	   __gnu_cxx::__make_move_iterator(end));
+}
+
+// Erasing a single iterator
+void
+test03(std::vector<rvalstruct>& d, std::vector<rvalstruct>::iterator i)
+{ d.erase(i); }
+
+// Erasing a range of iterators
+void
+test04(std::vector<rvalstruct>& d, std::vector<rvalstruct>::iterator begin,
+				   std::vector<rvalstruct>::iterator end)
+{ d.erase(begin, end); }
+
+// Clearing a vector
+void
+test05(std::vector<rvalstruct>& d)
+{ d.clear(); }
+
+
+
+
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/23_containers/vector/resize/moveable.cc libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc
--- libstdc++-v3.so_7.clean/testsuite/23_containers/vector/resize/moveable.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc	2005-09-17 12:08:06.000000000 +0100
@@ -0,0 +1,66 @@
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+using namespace __gnu_test;
+
+// According to n1771, there should be two resizes, with and without
+// parameter. We only have one at present, whose second parameter defaults
+// to a default-constructed object.
+// These values are one higher than might be expected because internally
+// resize calls fill, which copies its input value in case it is already in
+// the vector when the vector isn't moved.
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::vector<copycounter> a;
+  copycounter::copycount = 0;
+  a.resize(10);
+  a.resize(98);
+  a.resize(99);
+  a.resize(100);
+  VERIFY(copycounter::copycount == 100 + 4);
+  a.resize(99);
+  a.resize(0);
+  VERIFY(copycounter::copycount == 100 + 4);
+  a.resize(100);
+  VERIFY(copycounter::copycount == 200 + 5);
+  a.clear();
+  VERIFY(copycounter::copycount == 200 + 5);
+}
+
+
+int main()
+{
+  test01();
+  return 0;
+}
diff -urNx '*CVS*' libstdc++-v3.so_7.clean/testsuite/testsuite_rvalref.h libstdc++-v3/testsuite/testsuite_rvalref.h
--- libstdc++-v3.so_7.clean/testsuite/testsuite_rvalref.h	2005-09-10 21:25:54.000000000 +0100
+++ libstdc++-v3/testsuite/testsuite_rvalref.h	2005-09-17 00:53:54.000000000 +0100
@@ -122,7 +122,7 @@
     int val;
     bool valid;
     
-    copycounter() : val(0), valid(false)
+    copycounter() : val(0), valid(true)
     { }
 
     copycounter(int inval) : val(inval), valid(true)

Attachment: changelog-move2
Description: application/text


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]