]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rc_string_base.h (__rc_string_base<>::_Rep): Avoid the anonymous struct extension...
authorPaolo Carlini <pcarlini@suse.de>
Fri, 18 Nov 2005 11:50:22 +0000 (11:50 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Fri, 18 Nov 2005 11:50:22 +0000 (11:50 +0000)
2005-11-18  Paolo Carlini  <pcarlini@suse.de>

* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Avoid the
anonymous struct extension, adjust everywhere.

* include/ext/rc_string_base.h (__rc_string_base<>::_S_empty_rep()):
Just use a static member.
(__rc_string_base<>::__rc_string_base(), _S_construct): Adjust.

* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Use anonymous
union together with _CharT to fix alignment issues, rebind to _Rep and
rename _Raw_alloc to _Rep_alloc_type.
(__rc_string_base<>::_Rep::_S_create, _M_destroy): Adjust consistently.

* include/ext/vstring_util.h (__is_null_p): Move inside struct
__vstring_utility as static _S_is_null_pointer.
* include/ext/sso_string.h
(__sso_string_base<>::_M_construct(std::forward_iterator_tag): Adjust.
* include/ext/rc_string_base.h
(__rc_string_base<>::_S_construct(std::forward_iterator_tag): Likewise.

Implement Option 3 of DR 431 for ext/vstring - both available bases.
* include/bits/cpp_type_traits.h (struct __is_empty): Add.
* include/ext/vstring.h (__versa_string<>::swap): Delegate to
this->_M_swap.
* include/ext/vstring.tcc (__versa_string<>::swap): Remove.
* include/ext/vstring_util.h (struct __vstring_utility<>): Add struct
_Alloc_hider<>, augmented of allocator swapping facility, specialized
to nop for empty allocators.
* include/ext/rc_string_base.h (__rc_string_base<>::_M_swap): Use it.
(__rc_string_base<>::_M_is_leaked, _M_set_sharable): Change to private.
* include/ext/sso_string_base.h (__sso_string_base<>::_M_swap):
Likewise.
(__sso_string_base<>::_M_is_leaked, _M_set_sharable): Remove, unused.

* include/ext/rc_string_base.h (__rc_string_base<>::_M_data(_CharT*):
Return void.
* include/ext/sso_string_base.h (__sso_string_base<>::_M_data(_CharT*):
Likewise.

From-SVN: r107176

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/cpp_type_traits.h
libstdc++-v3/include/ext/rc_string_base.h
libstdc++-v3/include/ext/sso_string_base.h
libstdc++-v3/include/ext/vstring.h
libstdc++-v3/include/ext/vstring.tcc
libstdc++-v3/include/ext/vstring_util.h

index f6ddc196f8683f29107e9e2d0e51a2dfeee3eea0..9b6a0b0a3e022c70af254f126b2fb4bee5df03a5 100644 (file)
@@ -1,3 +1,43 @@
+2005-11-18  Paolo Carlini  <pcarlini@suse.de>
+
+       * include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Avoid the
+       anonymous struct extension, adjust everywhere.
+
+       * include/ext/rc_string_base.h (__rc_string_base<>::_S_empty_rep()):
+       Just use a static member.
+       (__rc_string_base<>::__rc_string_base(), _S_construct): Adjust.
+
+       * include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Use anonymous
+       union together with _CharT to fix alignment issues, rebind to _Rep and
+       rename _Raw_alloc to _Rep_alloc_type.
+       (__rc_string_base<>::_Rep::_S_create, _M_destroy): Adjust consistently.
+
+       * include/ext/vstring_util.h (__is_null_p): Move inside struct
+       __vstring_utility as static _S_is_null_pointer.
+       * include/ext/sso_string.h
+       (__sso_string_base<>::_M_construct(std::forward_iterator_tag): Adjust.
+       * include/ext/rc_string_base.h
+       (__rc_string_base<>::_S_construct(std::forward_iterator_tag): Likewise.
+
+       Implement Option 3 of DR 431 for ext/vstring - both available bases.
+       * include/bits/cpp_type_traits.h (struct __is_empty): Add.
+       * include/ext/vstring.h (__versa_string<>::swap): Delegate to
+       this->_M_swap.
+       * include/ext/vstring.tcc (__versa_string<>::swap): Remove.
+       * include/ext/vstring_util.h (struct __vstring_utility<>): Add struct
+       _Alloc_hider<>, augmented of allocator swapping facility, specialized
+       to nop for empty allocators.
+       * include/ext/rc_string_base.h (__rc_string_base<>::_M_swap): Use it.
+       (__rc_string_base<>::_M_is_leaked, _M_set_sharable): Change to private.
+       * include/ext/sso_string_base.h (__sso_string_base<>::_M_swap):
+       Likewise.
+       (__sso_string_base<>::_M_is_leaked, _M_set_sharable): Remove, unused.   
+
+       * include/ext/rc_string_base.h (__rc_string_base<>::_M_data(_CharT*):
+       Return void.
+       * include/ext/sso_string_base.h (__sso_string_base<>::_M_data(_CharT*):
+       Likewise.
+
 2005-11-17  Geoffrey Keating  <geoffk@apple.com>
 
        * config/os/bsd/darwin/ppc-extra.ver: New.
index f02caab031149eacc0652ae61d2effed678e5a74..5ac9c98e704dda399d45570f1a99b548f517793f 100644 (file)
@@ -364,6 +364,26 @@ namespace std
        };
     };
 
+  //
+  // A stripped-down version of std::tr1::is_empty
+  //
+  template<typename _Tp>
+    struct __is_empty
+    { 
+    private:
+      template<typename>
+        struct __first { };
+      template<typename _Up>
+        struct __second
+        : public _Up { };
+           
+    public:
+      enum
+       {
+         __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>)
+       };
+    };
+
 } // namespace std
 
 #endif //_CPP_TYPE_TRAITS_H
index e462680eddf7902e2b607d45fbb8e464e2d370d1..58994222eae5d7ee3ea6d6487822400a4afa5411 100644 (file)
@@ -92,8 +92,8 @@ namespace __gnu_cxx
       typedef typename _Traits::char_type                  value_type;
       typedef _Alloc                                       allocator_type;
 
-      typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
-        _CharT_alloc_type                                   _CharT_alloc_type;
+      typedef __vstring_utility<_CharT, _Traits, _Alloc>    _Util_Base;
+      typedef typename _Util_Base::_CharT_alloc_type        _CharT_alloc_type;
       typedef typename _CharT_alloc_type::size_type        size_type;
 
     private:
@@ -107,16 +107,25 @@ namespace __gnu_cxx
       //      -1: leaked, one reference, no ref-copies allowed, non-const.
       //       0: one reference, non-const.
       //     n>0: n + 1 references, operations require a lock, const.
-      //   4. All fields==0 is an empty string, given the extra storage
+      //   4. All fields == 0 is an empty string, given the extra storage
       //      beyond-the-end for a null terminator; thus, the shared
       //      empty string representation needs no constructor.
       struct _Rep
       {
-       size_type               _M_length;
-       size_type               _M_capacity;
-       _Atomic_word            _M_refcount;
+       union
+       {
+         struct
+         {
+           size_type       _M_length;
+           size_type       _M_capacity;
+           _Atomic_word    _M_refcount;
+         }                 _M_info;
+         
+         // Only for alignment purposes.
+         _CharT            _M_align;
+       };
 
-       typedef typename _Alloc::template rebind<size_type>::other _Raw_alloc;
+       typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
 
        _CharT*
        _M_refdata() throw()
@@ -125,15 +134,15 @@ namespace __gnu_cxx
        _CharT*
        _M_refcopy() throw()
        {
-         __atomic_add(&_M_refcount, 1);
+         __atomic_add(&_M_info._M_refcount, 1);
          return _M_refdata();
        }  // XXX MT
        
        void
        _M_set_length(size_type __n)
        { 
-         _M_refcount = 0;  // One reference.
-         _M_length = __n;
+         _M_info._M_refcount = 0;  // One reference.
+         _M_info._M_length = __n;
          // grrr. (per 21.3.4)
          // You cannot leave those LWG people alone for a second.
          traits_type::assign(_M_refdata()[__n], _CharT());
@@ -150,11 +159,14 @@ namespace __gnu_cxx
        _M_clone(const _Alloc&, size_type __res = 0);
       };
 
-      struct _Rep_empty : _Rep
+      struct _Rep_empty
+      : public _Rep
       {
-       _CharT                  _M_terminal;
+       _CharT              _M_terminal;
       };
 
+      static _Rep_empty     _S_empty_rep;
+
       // The maximum number of individual char_type elements of an
       // individual string is determined by _S_max_size. This is the
       // value that will be returned by max_size().  (Whereas npos
@@ -169,28 +181,12 @@ namespace __gnu_cxx
       enum { _S_max_size = (((static_cast<size_type>(-1) - sizeof(_Rep))
                             / sizeof(_CharT)) - 1) / 4 };
 
-      // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
-      struct _Alloc_hider : _Alloc
-      {
-       _Alloc_hider(_CharT* __dat, const _Alloc& __a)
-       : _Alloc(__a), _M_p(__dat) { }
-
-       _CharT* _M_p; // The actual data.
-      };
-
       // Data Member (private):
-      mutable _Alloc_hider     _M_dataplus;
-
-      static _Rep_empty&
-      _S_empty_rep()
-      {
-       static _Rep_empty _Empty_rep;
-       return _Empty_rep;
-      }
+      mutable typename _Util_Base::template _Alloc_hider<_Alloc>  _M_dataplus;
 
-      _CharT*
+      void
       _M_data(_CharT* __p)
-      { return (_M_dataplus._M_p = __p); }
+      { _M_dataplus._M_p = __p; }
 
       _Rep*
       _M_rep() const
@@ -206,15 +202,23 @@ namespace __gnu_cxx
       void
       _M_dispose(const _Alloc& __a)
       {
-       if (__exchange_and_add(&_M_rep()->_M_refcount, -1) <= 0)
+       if (__exchange_and_add(&_M_rep()->_M_info._M_refcount, -1) <= 0)
          _M_rep()->_M_destroy(__a);
       }  // XXX MT
 
+      bool
+      _M_is_leaked() const
+      { return _M_rep()->_M_info._M_refcount < 0; }
+
+      void
+      _M_set_sharable()
+      { _M_rep()->_M_info._M_refcount = 0; }
+
       void
       _M_leak_hard();
 
       // _S_construct_aux is used to implement the 21.3.1 para 15 which
-      // requires special behaviour if _InIter is an integral type
+      // requires special behaviour if _InIterator is an integral type
       template<class _InIterator>
         static _CharT*
         _S_construct_aux(_InIterator __beg, _InIterator __end,
@@ -266,31 +270,19 @@ namespace __gnu_cxx
 
       size_type
       _M_length() const
-      { return _M_rep()->_M_length; }
+      { return _M_rep()->_M_info._M_length; }
 
       size_type
       _M_capacity() const
-      { return _M_rep()->_M_capacity; }
+      { return _M_rep()->_M_info._M_capacity; }
 
       bool
       _M_is_shared() const
-      { return _M_rep()->_M_refcount > 0; }
-
-      bool
-      _M_is_leaked() const
-      { return _M_rep()->_M_refcount < 0; }
-
-      void
-      _M_set_sharable()
-      { _M_rep()->_M_refcount = 0; }
+      { return _M_rep()->_M_info._M_refcount > 0; }
 
       void
       _M_set_leaked()
-      { _M_rep()->_M_refcount = -1; }
-
-      void
-      _M_set_length(size_type __n)
-      { _M_rep()->_M_set_length(__n); }
+      { _M_rep()->_M_info._M_refcount = -1; }
 
       void
       _M_leak()    // for use in begin() & non-const op[]
@@ -299,8 +291,12 @@ namespace __gnu_cxx
          _M_leak_hard();
       }
 
+      void
+      _M_set_length(size_type __n)
+      { _M_rep()->_M_set_length(__n); }
+
       __rc_string_base()
-      : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { }
+      : _M_dataplus(_Alloc(), _S_empty_rep._M_refcopy()) { }
 
       __rc_string_base(const _Alloc& __a);
 
@@ -310,7 +306,7 @@ namespace __gnu_cxx
 
       template<typename _InputIterator>
         __rc_string_base(_InputIterator __beg, _InputIterator __end,
-                   const _Alloc& __a);
+                        const _Alloc& __a);
 
       ~__rc_string_base()
       { _M_dispose(_M_get_allocator()); }      
@@ -320,12 +316,7 @@ namespace __gnu_cxx
       { return _M_dataplus; }
 
       void
-      _M_swap(__rc_string_base& __rcs)
-      {
-       _CharT* __tmp = _M_data();
-       _M_data(__rcs._M_data());
-       __rcs._M_data(__tmp);
-      }
+      _M_swap(__rc_string_base& __rcs);
 
       void
       _M_assign(const __rc_string_base& __rcs);
@@ -337,6 +328,10 @@ namespace __gnu_cxx
       _M_mutate(size_type __pos, size_type __len1, size_type __len2);
     };
 
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
+    __rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
+
   template<typename _CharT, typename _Traits, typename _Alloc>
     typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
     __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
@@ -388,8 +383,8 @@ namespace __gnu_cxx
       // plus sizeof(size_type) - 1 to upper round to a size multiple
       // of sizeof(size_type).
       // Whew. Seemingly so needy, yet so elemental.
-      size_type __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
-                         + sizeof(size_type) - 1);
+      size_type __size = ((__capacity + 1) * sizeof(_CharT)
+                         + 2 * sizeof(_Rep) - 1);
 
       const size_type __adj_size = __size + __malloc_header_size;
       if (__adj_size > __pagesize && __capacity > __old_capacity)
@@ -399,16 +394,14 @@ namespace __gnu_cxx
          // Never allocate a string bigger than _S_max_size.
          if (__capacity > size_type(_S_max_size))
            __capacity = size_type(_S_max_size);
-         __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
-                   + sizeof(size_type) - 1);
+         __size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
        }
 
       // NB: Might throw, but no worries about a leak, mate: _Rep()
       // does not throw.
-      void* __place = _Raw_alloc(__alloc).allocate(__size
-                                                  / sizeof(size_type));
-      _Rep *__p = new (__place) _Rep;
-      __p->_M_capacity = __capacity;
+      _Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
+      _Rep* __p = new (__place) _Rep;
+      __p->_M_info._M_capacity = __capacity;
       return __p;
     }
 
@@ -417,10 +410,9 @@ namespace __gnu_cxx
     __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
     _M_destroy(const _Alloc& __a) throw ()
     {
-      const size_type __size = ((_M_capacity + 1) * sizeof(_CharT)
-                               + sizeof(_Rep) + sizeof(size_type) - 1);
-      _Raw_alloc(__a).deallocate(reinterpret_cast<size_type*>(this),
-                                __size / sizeof(size_type));
+      const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
+                               + 2 * sizeof(_Rep) - 1);
+      _Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -429,41 +421,40 @@ namespace __gnu_cxx
     _M_clone(const _Alloc& __alloc, size_type __res)
     {
       // Requested capacity of the clone.
-      const size_type __requested_cap = _M_length + __res;
-      _Rep* __r = _Rep::_S_create(__requested_cap, _M_capacity, __alloc);
+      const size_type __requested_cap = _M_info._M_length + __res;
+      _Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
+                                 __alloc);
 
-      if (_M_length)
-       _S_copy(__r->_M_refdata(), _M_refdata(), _M_length);
+      if (_M_info._M_length)
+       _S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
 
-      __r->_M_set_length(_M_length);
+      __r->_M_set_length(_M_info._M_length);
       return __r->_M_refdata();
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     __rc_string_base<_CharT, _Traits, _Alloc>::
     __rc_string_base(const _Alloc& __a)
-    : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) { }
+    : _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     __rc_string_base<_CharT, _Traits, _Alloc>::
     __rc_string_base(const __rc_string_base& __rcs)
-    : _M_dataplus(__rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
-                               __rcs._M_get_allocator()),
-                 __rcs._M_get_allocator()) { }
+    : _M_dataplus(__rcs._M_get_allocator(),
+                 __rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
+                               __rcs._M_get_allocator())) { }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     __rc_string_base<_CharT, _Traits, _Alloc>::
     __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
-    : _M_dataplus(_S_construct(__n, __c, __a), __a)
-    { }
+    : _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     template<typename _InputIterator>
     __rc_string_base<_CharT, _Traits, _Alloc>::
     __rc_string_base(_InputIterator __beg, _InputIterator __end,
                     const _Alloc& __a)
-    : _M_dataplus(_S_construct(__beg, __end, __a), __a)
-    { }
+    : _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
@@ -487,7 +478,7 @@ namespace __gnu_cxx
                   std::input_iterator_tag)
       {
        if (__beg == __end && __a == _Alloc())
-         return _S_empty_rep()._M_refcopy();
+         return _S_empty_rep._M_refcopy();
 
        // Avoid reallocation for common case.
        _CharT __buf[128];
@@ -532,10 +523,10 @@ namespace __gnu_cxx
                   std::forward_iterator_tag)
       {
        if (__beg == __end && __a == _Alloc())
-         return _S_empty_rep()._M_refcopy();
+         return _S_empty_rep._M_refcopy();
 
        // NB: Not required, but considered best practice.
-       if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
+       if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
          std::__throw_logic_error(__N("__rc_string_base::"
                                       "_S_construct NULL not valid"));
 
@@ -560,7 +551,7 @@ namespace __gnu_cxx
     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
     {
       if (__n == 0 && __a == _Alloc())
-       return _S_empty_rep()._M_refcopy();
+       return _S_empty_rep._M_refcopy();
 
       // Check for out_of_range and length_error exceptions.
       _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
@@ -571,6 +562,24 @@ namespace __gnu_cxx
       return __r->_M_refdata();
     }
 
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    void
+    __rc_string_base<_CharT, _Traits, _Alloc>::
+    _M_swap(__rc_string_base& __rcs)
+    {
+      if (_M_is_leaked())
+       _M_set_sharable();
+      if (__rcs._M_is_leaked())
+       __rcs._M_set_sharable();
+      
+      _CharT* __tmp = _M_data();
+      _M_data(__rcs._M_data());
+      __rcs._M_data(__tmp);
+      
+      // NB: Implement Option 3 of DR 431 (see N1599).
+      _M_dataplus._M_alloc_swap(__rcs._M_dataplus);
+    } 
+
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     __rc_string_base<_CharT, _Traits, _Alloc>::
index c37bd88ca5a7eae07b9efd444181be5c4ce9723b..bd29413eb8325f9d0334775f0a8ce3d46ea6f235 100644 (file)
@@ -47,8 +47,8 @@ namespace __gnu_cxx
       typedef typename _Traits::char_type                  value_type;
       typedef _Alloc                                       allocator_type;
 
-      typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
-        _CharT_alloc_type                                   _CharT_alloc_type;
+      typedef __vstring_utility<_CharT, _Traits, _Alloc>    _Util_Base;
+      typedef typename _Util_Base::_CharT_alloc_type        _CharT_alloc_type;
       typedef typename _CharT_alloc_type::size_type        size_type;
       
     private:
@@ -66,18 +66,9 @@ namespace __gnu_cxx
       enum { _S_max_size = (((static_cast<size_type>(-1)
                              / sizeof(_CharT)) - 1) / 4) };
 
-      // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
-      struct _Alloc_hider : _Alloc
-      {
-       _Alloc_hider(const _Alloc& __a, _CharT* __ptr)
-       : _Alloc(__a), _M_p(__ptr) { }
-
-       _CharT* _M_p; // The actual data.
-      };
-
       // Data Members (private):
-      _Alloc_hider             _M_dataplus;
-      size_type                 _M_string_length;
+      typename _Util_Base::template _Alloc_hider<_Alloc>    _M_dataplus;
+      size_type                                             _M_string_length;
 
       enum { _S_local_capacity = 15 };
       
@@ -87,9 +78,9 @@ namespace __gnu_cxx
        size_type               _M_allocated_capacity;
       };
 
-      _CharT*
+      void
       _M_data(_CharT* __p)
-      { return (_M_dataplus._M_p = __p); }
+      { _M_dataplus._M_p = __p; }
 
       void
       _M_length(size_type __length)
@@ -118,7 +109,7 @@ namespace __gnu_cxx
       _M_destroy(size_type) throw();
 
       // _M_construct_aux is used to implement the 21.3.1 para 15 which
-      // requires special behaviour if _InIter is an integral type
+      // requires special behaviour if _InIterator is an integral type
       template<class _InIterator>
         void
         _M_construct_aux(_InIterator __beg, _InIterator __end, __false_type)
@@ -181,28 +172,19 @@ namespace __gnu_cxx
       _M_is_shared() const
       { return false; }
 
-      bool
-      _M_is_leaked() const
-      { return false; }
-
       void
-      _M_set_sharable() { }
+      _M_set_leaked() { }
 
       void
-      _M_set_leaked() { }
+      _M_leak() { }
 
       void
       _M_set_length(size_type __n)
       {
        _M_length(__n);
-       // grrr. (per 21.3.4)
-       // You cannot leave those LWG people alone for a second.
        traits_type::assign(_M_data()[__n], _CharT());
       }
 
-      void
-      _M_leak() { }
-
       __sso_string_base()
       : _M_dataplus(_Alloc(), _M_local_data)
       { _M_set_length(0); }
@@ -248,6 +230,9 @@ namespace __gnu_cxx
     __sso_string_base<_CharT, _Traits, _Alloc>::
     _M_swap(__sso_string_base& __rcs)
     {
+      // NB: Implement Option 3 of DR 431 (see N1599).
+      _M_dataplus._M_alloc_swap(__rcs._M_dataplus);
+
       if (_M_is_local())
        if (__rcs._M_is_local())
          {
@@ -325,9 +310,6 @@ namespace __gnu_cxx
       // The below implements an exponential growth policy, necessary to
       // meet amortized linear time requirements of the library: see
       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
-      // It's active for allocations requiring an amount of memory above
-      // system pagesize. This is consistent with the requirements of the
-      // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
        __capacity = 2 * __old_capacity;
 
@@ -373,7 +355,6 @@ namespace __gnu_cxx
       _M_construct(_InIterator __beg, _InIterator __end,
                   std::input_iterator_tag)
       {
-       // Avoid reallocation for common case.
        size_type __len = 0;
        size_type __capacity = size_type(_S_local_capacity);
 
@@ -418,7 +399,7 @@ namespace __gnu_cxx
                   std::forward_iterator_tag)
       {
        // NB: Not required, but considered best practice.
-       if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
+       if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
          std::__throw_logic_error(__N("__sso_string_base::"
                                       "_M_construct NULL not valid"));
 
index a7741949f64c6fa45f6e46f102373633ac80b15a..1aaa87665e7984cb9b28b3fda66a46e4c0691629 100644 (file)
@@ -1214,7 +1214,8 @@ namespace __gnu_cxx
        *  time.
       */
       void
-      swap(__versa_string& __s);
+      swap(__versa_string& __s)
+      { this->_M_swap(__s); }
 
       // String operations:
       /**
index b8d35e3aceb6fbd96db6d1b7ce7807fc71cf56b2..76fa96bcbd3427800db45ffaeae65125390e2145 100644 (file)
@@ -218,30 +218,6 @@ namespace __gnu_cxx
         }
      }
 
-  template<typename _CharT, typename _Traits, typename _Alloc,
-          template <typename, typename, typename> class _Base>
-    void
-    __versa_string<_CharT, _Traits, _Alloc, _Base>::
-    swap(__versa_string& __s)
-    {
-      if (this->_M_is_leaked())
-       this->_M_set_sharable();
-      if (__s._M_is_leaked())
-       __s._M_set_sharable();
-      if (this->get_allocator() == __s.get_allocator())
-       this->_M_swap(__s);
-      // The code below can usually be optimized away.
-      else
-       {
-         const __versa_string __tmp1(_M_ibegin(), _M_iend(),
-                                     __s.get_allocator());
-         const __versa_string __tmp2(__s._M_ibegin(), __s._M_iend(),
-                                     this->get_allocator());
-         *this = __tmp2;
-         __s = __tmp1;
-       }
-    }
-
   template<typename _CharT, typename _Traits, typename _Alloc,
           template <typename, typename, typename> class _Base>
     void
index 38c7c10976a8dbd23aa5b0f9b4163bdc1a48f676..2a53fbdd4bd28cedd3860dfb8a117aeb727fa004 100644 (file)
@@ -1,4 +1,4 @@
-// Versatile string utilities -*- C++ -*-
+// Versatile string utility -*- C++ -*-
 
 // Copyright (C) 2005 Free Software Foundation, Inc.
 //
 
 namespace __gnu_cxx
 {
-  template<typename _Type>
-    inline bool
-    __is_null_p(_Type* __ptr)
-    { return __ptr == 0; }
-
-  template<typename _Type>
-    inline bool
-    __is_null_p(_Type)
-    { return false; }
-
   template<typename _CharT, typename _Traits, typename _Alloc>
     struct __vstring_utility
     {
@@ -92,6 +82,53 @@ namespace __gnu_cxx
                                       __rc_string_base> >
         __const_rc_iterator;
 
+      // NB:  When the allocator is empty, deriving from it saves space 
+      // (http://www.cantrip.org/emptyopt.html).  We do that anyway for
+      // consistency.
+      template<typename _Alloc1, bool = std::__is_empty<_Alloc1>::__value>
+        struct _Alloc_hider
+       : public _Alloc1
+       {
+         _Alloc_hider(const _Alloc1& __a, _CharT* __ptr)
+         : _Alloc1(__a), _M_p(__ptr) { }
+
+         void
+         _M_alloc_swap(_Alloc_hider& __ah)
+         {
+           // Implement Option 3 of DR 431 (see N1599).
+           // Precondition: swappable allocators.
+           _Alloc1& __this = static_cast<_Alloc1&>(*this);
+           _Alloc1& __that = static_cast<_Alloc1&>(__ah);
+           if (__this != __that)
+             swap(__this, __that);
+         }
+
+         _CharT*  _M_p; // The actual data.
+       };
+
+      template<typename _Alloc1>
+        struct _Alloc_hider<_Alloc1, true>
+       : public _Alloc1
+       {
+         _Alloc_hider(const _Alloc1& __a, _CharT* __ptr)
+         : _Alloc1(__a), _M_p(__ptr) { }
+
+         void _M_alloc_swap(_Alloc_hider&) { }
+
+         _CharT*  _M_p; // The actual data.
+       };
+
+      // For use in _M_construct (_S_construct) forward_iterator_tag.
+      template<typename _Type>
+        static bool
+        _S_is_null_pointer(_Type* __ptr)
+        { return __ptr == 0; }
+
+      template<typename _Type>
+        static bool
+        _S_is_null_pointer(_Type)
+        { return false; }
+
       // When __n = 1 way faster than the general multichar
       // traits_type::copy/move/assign.
       static void