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]

WIP: C++11 allocator support for std::deque


This is an incomplete patch to add allocator support to std::deque.
Excuse the ugly code and inevitable bugs, it was coded at 5am because
I couldn't sleep.  I'm not going to finish it for stage1, so here it
is just for fun (and to show why we should change std::deque's
invariant).

The new 23_containers/deque/allocator/noexcept.cc test is XFAIL'd
because moving and swapping doesn't meet the noexcept guarantees we
provide for the other containers. std::deque has an invariant that
it's never empty, so it needs to allocate memory in its move
constructor. Eurgh.

The pre-existing 23_containers/deque/requirements/exception/basic.cc
exception safety test also fails now. I haven't figured out where the
problem is yet, but it's probably in

deque::_M_move_assign(deque&&, true_type), is truly horrible code ,.
The complexity there is that when
propagate_on_container_move_assignment is true we will leave __x with
a moved-from allocator, so its memory has to be allocated by an
allocator that compares equal to that same moved-from state, but to be
exception-safe we want to allocate first, before destroying the
existing data. Eurgh. I'll try to improve it another time.
diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index 9c33ad9..6dfff77 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -92,9 +92,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     deque<_Tp, _Alloc>::
     operator=(const deque& __x)
     {
-      const size_type __len = size();
       if (&__x != this)
 	{
+#if __cplusplus >= 201103L
+	  if (_Alloc_traits::_S_propagate_on_copy_assign())
+	    {
+	      if (!_Alloc_traits::_S_always_equal()
+	          && _M_get_Tp_allocator() != __x._M_get_Tp_allocator())
+	        {
+		  // replacement allocator cannot free existing storage
+		  deque __newobj(__x.size(), __x._M_get_Tp_allocator());
+		  this->clear();
+		  _M_destroy_nodes(this->_M_impl._M_start._M_node,
+				   this->_M_impl._M_finish._M_node + 1);
+		  _M_deallocate_map(this->_M_impl._M_map,
+				    this->_M_impl._M_map_size);
+		  this->_M_impl._M_map = nullptr;
+		  this->_M_impl._M_map_size = 0;
+		  std::__alloc_on_copy(_M_get_Tp_allocator(),
+				       __x._M_get_Tp_allocator());
+		  this->_M_impl._M_swap_data(__newobj._M_impl);
+		}
+	      else
+		std::__alloc_on_copy(_M_get_Tp_allocator(),
+				     __x._M_get_Tp_allocator());
+	    }
+#endif
+	  const size_type __len = size();
 	  if (__len >= __x.size())
 	    _M_erase_at_end(std::copy(__x.begin(), __x.end(),
 				      this->_M_impl._M_start));
@@ -117,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
 	  {
-	    this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1,
-				    std::forward<_Args>(__args)...);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_start._M_cur - 1,
+			             std::forward<_Args>(__args)...);
 	    --this->_M_impl._M_start._M_cur;
 	  }
 	else
@@ -134,8 +159,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	if (this->_M_impl._M_finish._M_cur
 	    != this->_M_impl._M_finish._M_last - 1)
 	  {
-	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
-				    std::forward<_Args>(__args)...);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_finish._M_cur,
+			             std::forward<_Args>(__args)...);
 	    ++this->_M_impl._M_finish._M_cur;
 	  }
 	else
@@ -453,10 +479,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	__try
 	  {
 #if __cplusplus >= 201103L
-	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
-				    std::forward<_Args>(__args)...);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_finish._M_cur,
+			             std::forward<_Args>(__args)...);
 #else
-	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_finish._M_cur, __t);
 #endif
 	    this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
 						+ 1);
@@ -490,10 +518,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 					       - 1);
 	    this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
 #if __cplusplus >= 201103L
-	    this->_M_impl.construct(this->_M_impl._M_start._M_cur,
-				    std::forward<_Args>(__args)...);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_start._M_cur,
+			             std::forward<_Args>(__args)...);
 #else
-	    this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_start._M_cur, __t);
 #endif
 	  }
 	__catch(...)
@@ -512,7 +542,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _M_deallocate_node(this->_M_impl._M_finish._M_first);
       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_last - 1;
-      this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
+      _Alloc_traits::destroy(_M_get_Tp_allocator(),
+			     this->_M_impl._M_finish._M_cur);
     }
 
   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
@@ -524,7 +555,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     void deque<_Tp, _Alloc>::
     _M_pop_front_aux()
     {
-      this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
+      _Alloc_traits::destroy(_M_get_Tp_allocator(),
+			     this->_M_impl._M_finish._M_cur);
       _M_deallocate_node(this->_M_impl._M_start._M_first);
       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_first;
@@ -878,6 +910,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     deque<_Tp, _Alloc>::
     _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
     {
+#if 0
+      if (__builtin_expect(_M_impl._M_map == _Map_pointer(), 0)) // TODO improve
+	  this->_M_initialize_map(0);
+#endif
+
       const size_type __old_num_nodes
 	= this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1;
       const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index ca9e417..e0c9055 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -85,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #define _GLIBCXX_DEQUE_BUF_SIZE 512
 #endif
 
-  inline size_t
+  _GLIBCXX_CONSTEXPR inline size_t
   __deque_buf_size(size_t __size)
   { return (__size < _GLIBCXX_DEQUE_BUF_SIZE
 	    ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); }
@@ -105,8 +105,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Ref, typename _Ptr>
     struct _Deque_iterator
     {
+#if __cplusplus < 201103L
       typedef _Deque_iterator<_Tp, _Tp&, _Tp*>             iterator;
       typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
+      typedef _Tp*                                         _Elt_pointer;
+      typedef _Tp**                                        _Map_pointer;
+#else
+    private:
+      template<typename _Up>
+	using __ptr_to = typename pointer_traits<_Ptr>::template rebind<_Up>;
+      template<typename _CvTp>
+	using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_to<_CvTp>>;
+    public:
+      typedef __iter<_Tp>		iterator;
+      typedef __iter<const _Tp>		const_iterator;
+      typedef __ptr_to<_Tp>		_Elt_pointer;
+      typedef __ptr_to<_Elt_pointer>	_Map_pointer;
+#endif
 
       static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
       { return __deque_buf_size(sizeof(_Tp)); }
@@ -117,15 +132,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       typedef _Ref                            reference;
       typedef size_t                          size_type;
       typedef ptrdiff_t                       difference_type;
-      typedef _Tp**                           _Map_pointer;
       typedef _Deque_iterator                 _Self;
 
-      _Tp* _M_cur;
-      _Tp* _M_first;
-      _Tp* _M_last;
+      _Elt_pointer _M_cur;
+      _Elt_pointer _M_first;
+      _Elt_pointer _M_last;
       _Map_pointer _M_node;
 
-      _Deque_iterator(_Tp* __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT
+      _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT
       : _M_cur(__x), _M_first(*__y),
         _M_last(*__y + _S_buffer_size()), _M_node(__y) { }
 
@@ -443,15 +457,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     class _Deque_base
     {
+    protected:
+      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
+	rebind<_Tp>::other _Tp_alloc_type;
+      typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type>	 _Alloc_traits;
+
+#if __cplusplus < 201103L
+      typedef _Tp*					_Ptr;
+      typedef const _Tp*				_Ptr_const;
+#else
+      typedef typename _Alloc_traits::pointer		_Ptr;
+      typedef typename _Alloc_traits::const_pointer	_Ptr_const;
+#endif
+
+      typedef typename _Alloc_traits::template rebind<_Ptr>::other
+	_Map_alloc_type;
+      typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits;
+
     public:
       typedef _Alloc                  allocator_type;
+      typedef typename _Alloc_traits::size_type size_type;
 
       allocator_type
       get_allocator() const _GLIBCXX_NOEXCEPT
       { return allocator_type(_M_get_Tp_allocator()); }
 
-      typedef _Deque_iterator<_Tp, _Tp&, _Tp*>             iterator;
-      typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
+      typedef _Deque_iterator<_Tp, _Tp&, _Ptr>          iterator;
+      typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const>   const_iterator;
 
       _Deque_base()
       : _M_impl()
@@ -473,13 +505,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _Deque_base(_Deque_base&& __x)
       : _M_impl(std::move(__x._M_get_Tp_allocator()))
       {
-	_M_initialize_map(0);
 	if (__x._M_impl._M_map)
 	  {
-	    std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
-	    std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
-	    std::swap(this->_M_impl._M_map, __x._M_impl._M_map);
-	    std::swap(this->_M_impl._M_map_size, __x._M_impl._M_map_size);
+	    this->_M_impl._M_swap_data(__x._M_impl);
+	    // re-initialize __x using its moved-from allocator
+	    __x._M_initialize_map(0);  // TODO remove somehow?
+	  }
+      }
+
+      _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n)
+      : _M_impl(__a)
+      {
+	if (__x.get_allocator() == __a)
+	  {
+	    _M_initialize_map(0);  // TODO remove somehow?
+	    if (__x._M_impl._M_map)
+	      this->_M_impl._M_swap_data(__x._M_impl);
+	  }
+	else
+	  {
+	    _M_initialize_map(__n);
 	  }
       }
 #endif
@@ -487,37 +532,43 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       ~_Deque_base() _GLIBCXX_NOEXCEPT;
 
     protected:
+      typedef typename iterator::_Map_pointer _Map_pointer;
+
       //This struct encapsulates the implementation of the std::deque
       //standard container and at the same time makes use of the EBO
       //for empty allocators.
-      typedef typename _Alloc::template rebind<_Tp*>::other _Map_alloc_type;
-
-      typedef typename _Alloc::template rebind<_Tp>::other  _Tp_alloc_type;
-
       struct _Deque_impl
       : public _Tp_alloc_type
       {
-	_Tp** _M_map;
+	_Map_pointer _M_map;
 	size_t _M_map_size;
 	iterator _M_start;
 	iterator _M_finish;
 
 	_Deque_impl()
-	: _Tp_alloc_type(), _M_map(0), _M_map_size(0),
+	: _Tp_alloc_type(), _M_map(), _M_map_size(0),
 	  _M_start(), _M_finish()
 	{ }
 
 	_Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
-	: _Tp_alloc_type(__a), _M_map(0), _M_map_size(0),
+	: _Tp_alloc_type(__a), _M_map(), _M_map_size(0),
 	  _M_start(), _M_finish()
 	{ }
 
 #if __cplusplus >= 201103L
 	_Deque_impl(_Tp_alloc_type&& __a) _GLIBCXX_NOEXCEPT
-	: _Tp_alloc_type(std::move(__a)), _M_map(0), _M_map_size(0),
+	: _Tp_alloc_type(std::move(__a)), _M_map(), _M_map_size(0),
 	  _M_start(), _M_finish()
 	{ }
 #endif
+
+	void _M_swap_data(_Deque_impl& __x)
+	{
+	  std::swap(this->_M_start, __x._M_start);
+	  std::swap(this->_M_finish, __x._M_finish);
+	  std::swap(this->_M_map, __x._M_map);
+	  std::swap(this->_M_map_size, __x._M_map_size);
+	}
       };
 
       _Tp_alloc_type&
@@ -532,30 +583,38 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _M_get_map_allocator() const _GLIBCXX_NOEXCEPT
       { return _Map_alloc_type(_M_get_Tp_allocator()); }
 
-      _Tp*
+      _Ptr
       _M_allocate_node()
       { 
-	return _M_impl._Tp_alloc_type::allocate(__deque_buf_size(sizeof(_Tp)));
+	typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits;
+	return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp)));
       }
 
       void
-      _M_deallocate_node(_Tp* __p) _GLIBCXX_NOEXCEPT
+      _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT
       {
-	_M_impl._Tp_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp)));
+	typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits;
+	_Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp)));
       }
 
-      _Tp**
+      _Map_pointer
       _M_allocate_map(size_t __n)
-      { return _M_get_map_allocator().allocate(__n); }
+      {
+	_Map_alloc_type __map_alloc = _M_get_map_allocator();
+	return _Map_alloc_traits::allocate(__map_alloc, __n);
+      }
 
-      void
-      _M_deallocate_map(_Tp** __p, size_t __n) _GLIBCXX_NOEXCEPT
-      { _M_get_map_allocator().deallocate(__p, __n); }
+      _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT
+      {
+	_Map_alloc_type __map_alloc = _M_get_map_allocator();
+	_Map_alloc_traits::deallocate(__map_alloc, __p, __n);
+      }
 
     protected:
       void _M_initialize_map(size_t);
-      void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
-      void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT;
+      void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish);
+      void _M_destroy_nodes(_Map_pointer __nstart,
+			    _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT;
       enum { _S_initial_map_size = 8 };
 
       _Deque_impl _M_impl;
@@ -576,7 +635,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   /**
    *  @brief Layout storage.
    *  @param  __num_elements  The count of T's for which to allocate space
-   *                        at first.
+   *                          at first.
    *  @return   Nothing.
    *
    *  The initial underlying memory layout is a bit complicated...
@@ -598,9 +657,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       // the beginning of _M_map, but for small maps it may be as far in as
       // _M_map+3.
 
-      _Tp** __nstart = (this->_M_impl._M_map
-			+ (this->_M_impl._M_map_size - __num_nodes) / 2);
-      _Tp** __nfinish = __nstart + __num_nodes;
+      _Map_pointer __nstart = (this->_M_impl._M_map
+			       + (this->_M_impl._M_map_size - __num_nodes) / 2);
+      _Map_pointer __nfinish = __nstart + __num_nodes;
 
       __try
 	{ _M_create_nodes(__nstart, __nfinish); }
@@ -623,9 +682,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     void
     _Deque_base<_Tp, _Alloc>::
-    _M_create_nodes(_Tp** __nstart, _Tp** __nfinish)
+    _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish)
     {
-      _Tp** __cur;
+      _Map_pointer __cur;
       __try
 	{
 	  for (__cur = __nstart; __cur < __nfinish; ++__cur)
@@ -641,9 +700,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     void
     _Deque_base<_Tp, _Alloc>::
-    _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT
+    _M_destroy_nodes(_Map_pointer __nstart,
+		     _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT
     {
-      for (_Tp** __n = __nstart; __n < __nfinish; ++__n)
+      for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n)
 	_M_deallocate_node(*__n);
     }
 
@@ -672,6 +732,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    *  - size_t      _M_map_size
    *  - iterator    _M_start, _M_finish
    *
+   *  // TODO unless moved-from, ...
    *  map_size is at least 8.  %map is an array of map_size
    *  pointers-to-@a nodes.  (The name %map has nothing to do with the
    *  std::map class, and @b nodes should not be confused with
@@ -739,15 +800,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
       __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
 
-      typedef _Deque_base<_Tp, _Alloc>           _Base;
-      typedef typename _Base::_Tp_alloc_type	 _Tp_alloc_type;
+      typedef _Deque_base<_Tp, _Alloc>			_Base;
+      typedef typename _Base::_Tp_alloc_type		_Tp_alloc_type;
+      typedef typename _Base::_Alloc_traits		_Alloc_traits;
+      typedef typename _Base::_Map_pointer		_Map_pointer;
 
     public:
       typedef _Tp                                        value_type;
-      typedef typename _Tp_alloc_type::pointer           pointer;
-      typedef typename _Tp_alloc_type::const_pointer     const_pointer;
-      typedef typename _Tp_alloc_type::reference         reference;
-      typedef typename _Tp_alloc_type::const_reference   const_reference;
+      typedef typename _Alloc_traits::pointer            pointer;
+      typedef typename _Alloc_traits::const_pointer      const_pointer;
+      typedef typename _Alloc_traits::reference          reference;
+      typedef typename _Alloc_traits::const_reference    const_reference;
       typedef typename _Base::iterator                   iterator;
       typedef typename _Base::const_iterator             const_iterator;
       typedef std::reverse_iterator<const_iterator>      const_reverse_iterator;
@@ -757,8 +820,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       typedef _Alloc                             allocator_type;
 
     protected:
-      typedef pointer*                           _Map_pointer;
-
       static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
       { return __deque_buf_size(sizeof(_Tp)); }
 
@@ -798,8 +859,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  constructed elements.
        */
       explicit
-      deque(size_type __n)
-      : _Base(__n)
+      deque(size_type __n, const allocator_type& __a = allocator_type())
+      : _Base(__a, __n)
       { _M_default_initialize(); }
 
       /**
@@ -838,7 +899,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  by @a __x.
        */
       deque(const deque& __x)
-      : _Base(__x._M_get_Tp_allocator(), __x.size())
+      : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()),
+	      __x.size())
       { std::__uninitialized_copy_a(__x.begin(), __x.end(), 
 				    this->_M_impl._M_start,
 				    _M_get_Tp_allocator()); }
@@ -851,9 +913,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  The newly-created %deque contains the exact contents of @a __x.
        *  The contents of @a __x are a valid, but unspecified %deque.
        */
-      deque(deque&& __x)
+      deque(deque&& __x) // TODO noexcept
       : _Base(std::move(__x)) { }
 
+      /// Copy constructor with alternative allocator
+      deque(const deque& __x, const allocator_type& __a)
+      : _Base(__a, __x.size())
+      { std::__uninitialized_copy_a(__x.begin(), __x.end(),
+				    this->_M_impl._M_start,
+				    _M_get_Tp_allocator()); }
+
+      /// Move constructor with alternative allocator
+      deque(deque&& __x, const allocator_type& __a) // TODO noexcept(_S_)
+      : _Base(std::move(__x), __a, __x.size())
+      {
+	if (__x.get_allocator() != __a)
+	  {
+	    std::__uninitialized_move_a(__x.begin(), __x.end(),
+					this->_M_impl._M_start,
+					_M_get_Tp_allocator());
+	    __x.clear();
+	  }
+      }
+
       /**
        *  @brief  Builds a %deque from an initializer list.
        *  @param  __l  An initializer_list.
@@ -935,15 +1017,61 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @a __x is a valid, but unspecified %deque.
        */
       deque&
-      operator=(deque&& __x) noexcept
+      operator=(deque&& __x) // TODO cond noexcept
       {
-	// NB: DR 1204.
-	// NB: DR 675.
-	this->clear();
-	this->swap(__x);
+	constexpr bool __move_storage =
+          _Alloc_traits::_S_propagate_on_move_assign()
+          || _Alloc_traits::_S_always_equal();
+        _M_move_assign(std::move(__x),
+                       integral_constant<bool, __move_storage>());
 	return *this;
       }
 
+      // TODO make private and put later in file
+      // Constant-time move assignment when source object's memory can be
+      // moved, either because the source's allocator will move too
+      // or because the allocators are equal.
+      void
+      _M_move_assign(deque&& __x, true_type)
+      {
+	_Tp_alloc_type __alloc =
+	  _Alloc_traits::_S_propagate_on_move_assign()
+	  ? _Tp_alloc_type(std::move(__x._M_get_Tp_allocator()))
+	  : __x._M_get_Tp_allocator();
+	// initialize empty deque using maybe-moved-from allocator
+	deque __empty(__x._M_get_Tp_allocator()); // XXX can throw
+	// free existing storage
+	this->clear();
+	_M_destroy_nodes(this->_M_impl._M_start._M_node,
+			 this->_M_impl._M_finish._M_node + 1);
+	_M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
+	this->_M_impl._M_map = nullptr;
+	this->_M_impl._M_map_size = 0;
+	// take ownership of __x's storage
+	this->_M_impl._M_swap_data(__x._M_impl);
+	// and maybe its allocator
+	std::__alloc_on_move(_M_get_Tp_allocator(), __alloc);
+	// swap __x storage with "empty" deque created using same alloc
+	__empty._M_impl._M_swap_data(__x._M_impl);
+      }
+
+      // Do move assignment when it might not be possible to move source
+      // object's memory, resulting in a linear-time operation.
+      void
+      _M_move_assign(deque&& __x, false_type)
+      {
+	if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
+	  _M_move_assign(std::move(__x), std::true_type());
+	else
+	  {
+	    // The rvalue's allocator cannot be moved and is not equal,
+	    // so we need to individually move each element.
+	    this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
+			 std::__make_move_if_noexcept_iterator(__x.end()));
+	    __x.clear();
+	  }
+      }
+
       /**
        *  @brief  Assigns an initializer list to a %deque.
        *  @param  __l  An initializer_list.
@@ -1144,7 +1272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /**  Returns the size() of the largest possible %deque.  */
       size_type
       max_size() const _GLIBCXX_NOEXCEPT
-      { return _M_get_Tp_allocator().max_size(); }
+      { return _Alloc_traits::max_size(_M_get_Tp_allocator()); }
 
 #if __cplusplus >= 201103L
       /**
@@ -1362,7 +1490,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
 	  {
-	    this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1, __x);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_start._M_cur - 1,
+	                             __x);
 	    --this->_M_impl._M_start._M_cur;
 	  }
 	else
@@ -1394,7 +1524,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	if (this->_M_impl._M_finish._M_cur
 	    != this->_M_impl._M_finish._M_last - 1)
 	  {
-	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __x);
+	    _Alloc_traits::construct(this->_M_impl,
+	                             this->_M_impl._M_finish._M_cur, __x);
 	    ++this->_M_impl._M_finish._M_cur;
 	  }
 	else
@@ -1425,7 +1556,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	if (this->_M_impl._M_start._M_cur
 	    != this->_M_impl._M_start._M_last - 1)
 	  {
-	    this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
+	    _Alloc_traits::destroy(this->_M_impl,
+	                           this->_M_impl._M_start._M_cur);
 	    ++this->_M_impl._M_start._M_cur;
 	  }
 	else
@@ -1447,7 +1579,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    != this->_M_impl._M_finish._M_first)
 	  {
 	    --this->_M_impl._M_finish._M_cur;
-	    this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
+	    _Alloc_traits::destroy(this->_M_impl,
+	                           this->_M_impl._M_finish._M_cur);
 	  }
 	else
 	  _M_pop_back_aux();
@@ -1653,7 +1786,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  std::swap(d1,d2) will feed to this function.
        */
       void
-      swap(deque& __x) _GLIBCXX_NOEXCEPT
+      swap(deque& __x) _GLIBCXX_NOEXCEPT  // TODO cond noexcept?
       {
 	std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
 	std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 5c8c161..c945a44 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1435,9 +1435,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	const vector __tmp(std::move(*this));
 	this->_M_impl._M_swap_data(__x._M_impl);
-	if (_Alloc_traits::_S_propagate_on_move_assign())
-	  std::__alloc_on_move(_M_get_Tp_allocator(),
-			       __x._M_get_Tp_allocator());
+	std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator());
       }
 
       // Do move assignment when it might not be possible to move source
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/copy.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/copy.cc
new file mode 100644
index 0000000..9e4fb34
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/copy.cc
@@ -0,0 +1,67 @@
+// Copyright (C) 2013 Free Software Foundation
+//
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, false> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(0 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(v1, alloc_type(2));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/copy_assign.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/copy_assign.cc
new file mode 100644
index 0000000..c2cc55d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/copy_assign.cc
@@ -0,0 +1,57 @@
+// Copyright (C) 2013 Free Software Foundation
+//
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, false> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/ext_ptr.cc
new file mode 100644
index 0000000..69b11d2
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/ext_ptr.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2013 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::CustomPointerAlloc;
+
+template class std::deque<T, CustomPointerAlloc<T>>;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef CustomPointerAlloc<T> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v(1);
+  VERIFY( ++v.begin() == v.end() );
+}
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/minimal.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/minimal.cc
new file mode 100644
index 0000000..cd5ea66
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/minimal.cc
@@ -0,0 +1,45 @@
+// Copyright (C) 2011-2013 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::SimpleAllocator;
+
+template class std::deque<T, SimpleAllocator<T>>;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef SimpleAllocator<T> alloc_type;
+  typedef std::allocator_traits<alloc_type> traits_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v(1, alloc_type{});
+  VERIFY( v.max_size() == traits_type::max_size(v.get_allocator()) );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/move.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/move.cc
new file mode 100644
index 0000000..244a7e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/move.cc
@@ -0,0 +1,55 @@
+// Copyright (C) 2013 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<T> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(std::move(v1));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<T> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(std::move(v1), alloc_type(2));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/move_assign.cc
new file mode 100644
index 0000000..ee7c65f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/move_assign.cc
@@ -0,0 +1,57 @@
+// Copyright (C) 2013 Free Software Foundation
+//
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, false> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  v2 = std::move(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  v2 = std::move(v1);
+  VERIFY(0 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/noexcept.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/noexcept.cc
new file mode 100644
index 0000000..7bd65e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/noexcept.cc
@@ -0,0 +1,67 @@
+// Copyright (C) 2013 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/>.
+
+// XFAIL while std::deque allocates memory in move constructor
+// { dg-do compile { xfail *-*-* } }
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+namespace __gnu_test
+{
+  template<typename U>
+    inline void
+    swap(propagating_allocator<U, true>& l, propagating_allocator<U, true>& r)
+    noexcept(false)
+    { }
+}
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  typedef std::allocator<T> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1;
+  test_type v2;
+  // this is a GNU extension for std::allocator
+  static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); // { dg-error "throw" }
+  static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
+}
+
+void test02()
+{
+  typedef propagating_allocator<T, false> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  test_type v2(alloc_type(2));
+  static_assert( !noexcept( v1 = std::move(v2) ), "Move assign can throw" );
+  static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
+}
+
+void test03()
+{
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  test_type v2(alloc_type(2));
+  static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); // { dg-error "throw" }
+  static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" ); // { dg-error "throw" }
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/swap.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/swap.cc
new file mode 100644
index 0000000..c504581
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/swap.cc
@@ -0,0 +1,77 @@
+// Copyright (C) 2013 Free Software Foundation
+//
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+// It is undefined behaviour to swap() containers wth unequal allocators
+// if the allocator doesn't propagate, so ensure the allocators compare
+// equal, while still being able to test propagation via get_personality().
+bool
+operator==(const propagating_allocator<T, false>&,
+           const propagating_allocator<T, false>&)
+{
+  return true;
+}
+
+bool
+operator!=(const propagating_allocator<T, false>&,
+           const propagating_allocator<T, false>&)
+{
+  return false;
+}
+
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, false> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  std::swap(v1, v2);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+  // swap back so assertions in uneq_allocator::deallocate don't fail
+  std::swap(v1, v2);
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<T, true> alloc_type;
+  typedef std::deque<T, alloc_type> test_type;
+  test_type v1(1, alloc_type(1));
+  test_type v2(1, alloc_type(2));
+  std::swap(v1, v2);
+  VERIFY(2 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}

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