Home | History | Annotate | Download | only in bits
      1 // Components for manipulating sequences of characters -*- C++ -*-
      2 
      3 // Copyright (C) 1997-2013 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file bits/basic_string.tcc
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{string}
     28  */
     29 
     30 //
     31 // ISO C++ 14882: 21  Strings library
     32 //
     33 
     34 // Written by Jason Merrill based upon the specification by Takanori Adachi
     35 // in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
     36 
     37 #ifndef _BASIC_STRING_TCC
     38 #define _BASIC_STRING_TCC 1
     39 
     40 #pragma GCC system_header
     41 
     42 #include <bits/cxxabi_forced.h>
     43 
     44 namespace std _GLIBCXX_VISIBILITY(default)
     45 {
     46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     47 
     48   template<typename _CharT, typename _Traits, typename _Alloc>
     49     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
     50     basic_string<_CharT, _Traits, _Alloc>::
     51     _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
     52 
     53   template<typename _CharT, typename _Traits, typename _Alloc>
     54     const _CharT
     55     basic_string<_CharT, _Traits, _Alloc>::
     56     _Rep::_S_terminal = _CharT();
     57 
     58   template<typename _CharT, typename _Traits, typename _Alloc>
     59     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
     60     basic_string<_CharT, _Traits, _Alloc>::npos;
     61 
     62   // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
     63   // at static init time (before static ctors are run).
     64   template<typename _CharT, typename _Traits, typename _Alloc>
     65     typename basic_string<_CharT, _Traits, _Alloc>::size_type
     66     basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
     67     (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
     68       sizeof(size_type)];
     69 
     70   // NB: This is the special case for Input Iterators, used in
     71   // istreambuf_iterators, etc.
     72   // Input Iterators have a cost structure very different from
     73   // pointers, calling for a different coding style.
     74   template<typename _CharT, typename _Traits, typename _Alloc>
     75     template<typename _InIterator>
     76       _CharT*
     77       basic_string<_CharT, _Traits, _Alloc>::
     78       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
     79 		   input_iterator_tag)
     80       {
     81 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
     82 	if (__beg == __end && __a == _Alloc())
     83 	  return _S_empty_rep()._M_refdata();
     84 #endif
     85 	// Avoid reallocation for common case.
     86 	_CharT __buf[128];
     87 	size_type __len = 0;
     88 	while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
     89 	  {
     90 	    __buf[__len++] = *__beg;
     91 	    ++__beg;
     92 	  }
     93 	_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
     94 	_M_copy(__r->_M_refdata(), __buf, __len);
     95 	__try
     96 	  {
     97 	    while (__beg != __end)
     98 	      {
     99 		if (__len == __r->_M_capacity)
    100 		  {
    101 		    // Allocate more space.
    102 		    _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
    103 		    _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
    104 		    __r->_M_destroy(__a);
    105 		    __r = __another;
    106 		  }
    107 		__r->_M_refdata()[__len++] = *__beg;
    108 		++__beg;
    109 	      }
    110 	  }
    111 	__catch(...)
    112 	  {
    113 	    __r->_M_destroy(__a);
    114 	    __throw_exception_again;
    115 	  }
    116 	__r->_M_set_length_and_sharable(__len);
    117 	return __r->_M_refdata();
    118       }
    119 
    120   template<typename _CharT, typename _Traits, typename _Alloc>
    121     template <typename _InIterator>
    122       _CharT*
    123       basic_string<_CharT, _Traits, _Alloc>::
    124       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
    125 		   forward_iterator_tag)
    126       {
    127 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
    128 	if (__beg == __end && __a == _Alloc())
    129 	  return _S_empty_rep()._M_refdata();
    130 #endif
    131 	// NB: Not required, but considered best practice.
    132 	if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
    133 	  __throw_logic_error(__N("basic_string::_S_construct null not valid"));
    134 
    135 	const size_type __dnew = static_cast<size_type>(std::distance(__beg,
    136 								      __end));
    137 	// Check for out_of_range and length_error exceptions.
    138 	_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
    139 	__try
    140 	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
    141 	__catch(...)
    142 	  {
    143 	    __r->_M_destroy(__a);
    144 	    __throw_exception_again;
    145 	  }
    146 	__r->_M_set_length_and_sharable(__dnew);
    147 	return __r->_M_refdata();
    148       }
    149 
    150   template<typename _CharT, typename _Traits, typename _Alloc>
    151     _CharT*
    152     basic_string<_CharT, _Traits, _Alloc>::
    153     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
    154     {
    155 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
    156       if (__n == 0 && __a == _Alloc())
    157 	return _S_empty_rep()._M_refdata();
    158 #endif
    159       // Check for out_of_range and length_error exceptions.
    160       _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
    161       if (__n)
    162 	_M_assign(__r->_M_refdata(), __n, __c);
    163 
    164       __r->_M_set_length_and_sharable(__n);
    165       return __r->_M_refdata();
    166     }
    167 
    168   template<typename _CharT, typename _Traits, typename _Alloc>
    169     basic_string<_CharT, _Traits, _Alloc>::
    170     basic_string(const basic_string& __str)
    171     : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
    172 					  __str.get_allocator()),
    173 		  __str.get_allocator())
    174     { }
    175 
    176   template<typename _CharT, typename _Traits, typename _Alloc>
    177     basic_string<_CharT, _Traits, _Alloc>::
    178     basic_string(const _Alloc& __a)
    179     : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
    180     { }
    181 
    182   template<typename _CharT, typename _Traits, typename _Alloc>
    183     basic_string<_CharT, _Traits, _Alloc>::
    184     basic_string(const basic_string& __str, size_type __pos, size_type __n)
    185     : _M_dataplus(_S_construct(__str._M_data()
    186 			       + __str._M_check(__pos,
    187 						"basic_string::basic_string"),
    188 			       __str._M_data() + __str._M_limit(__pos, __n)
    189 			       + __pos, _Alloc()), _Alloc())
    190     { }
    191 
    192   template<typename _CharT, typename _Traits, typename _Alloc>
    193     basic_string<_CharT, _Traits, _Alloc>::
    194     basic_string(const basic_string& __str, size_type __pos,
    195 		 size_type __n, const _Alloc& __a)
    196     : _M_dataplus(_S_construct(__str._M_data()
    197 			       + __str._M_check(__pos,
    198 						"basic_string::basic_string"),
    199 			       __str._M_data() + __str._M_limit(__pos, __n)
    200 			       + __pos, __a), __a)
    201     { }
    202 
    203   // TBD: DPG annotate
    204   template<typename _CharT, typename _Traits, typename _Alloc>
    205     basic_string<_CharT, _Traits, _Alloc>::
    206     basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
    207     : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
    208     { }
    209 
    210   // TBD: DPG annotate
    211   template<typename _CharT, typename _Traits, typename _Alloc>
    212     basic_string<_CharT, _Traits, _Alloc>::
    213     basic_string(const _CharT* __s, const _Alloc& __a)
    214     : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
    215 			       __s + npos, __a), __a)
    216     { }
    217 
    218   template<typename _CharT, typename _Traits, typename _Alloc>
    219     basic_string<_CharT, _Traits, _Alloc>::
    220     basic_string(size_type __n, _CharT __c, const _Alloc& __a)
    221     : _M_dataplus(_S_construct(__n, __c, __a), __a)
    222     { }
    223 
    224   // TBD: DPG annotate
    225   template<typename _CharT, typename _Traits, typename _Alloc>
    226     template<typename _InputIterator>
    227     basic_string<_CharT, _Traits, _Alloc>::
    228     basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
    229     : _M_dataplus(_S_construct(__beg, __end, __a), __a)
    230     { }
    231 
    232 #if __cplusplus >= 201103L
    233   template<typename _CharT, typename _Traits, typename _Alloc>
    234     basic_string<_CharT, _Traits, _Alloc>::
    235     basic_string(initializer_list<_CharT> __l, const _Alloc& __a)
    236     : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a)
    237     { }
    238 #endif
    239 
    240   template<typename _CharT, typename _Traits, typename _Alloc>
    241     basic_string<_CharT, _Traits, _Alloc>&
    242     basic_string<_CharT, _Traits, _Alloc>::
    243     assign(const basic_string& __str)
    244     {
    245       if (_M_rep() != __str._M_rep())
    246 	{
    247 	  // XXX MT
    248 	  const allocator_type __a = this->get_allocator();
    249 	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
    250 	  _M_rep()->_M_dispose(__a);
    251 	  _M_data(__tmp);
    252 	}
    253       return *this;
    254     }
    255 
    256   template<typename _CharT, typename _Traits, typename _Alloc>
    257     basic_string<_CharT, _Traits, _Alloc>&
    258     basic_string<_CharT, _Traits, _Alloc>::
    259     assign(const _CharT* __s, size_type __n)
    260     {
    261       __glibcxx_requires_string_len(__s, __n);
    262       _M_check_length(this->size(), __n, "basic_string::assign");
    263       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
    264 	return _M_replace_safe(size_type(0), this->size(), __s, __n);
    265       else
    266 	{
    267 	  // Work in-place.
    268 	  const size_type __pos = __s - _M_data();
    269 	  if (__pos >= __n)
    270 	    _M_copy(_M_data(), __s, __n);
    271 	  else if (__pos)
    272 	    _M_move(_M_data(), __s, __n);
    273 	  _M_rep()->_M_set_length_and_sharable(__n);
    274 	  return *this;
    275 	}
    276      }
    277 
    278   template<typename _CharT, typename _Traits, typename _Alloc>
    279     basic_string<_CharT, _Traits, _Alloc>&
    280     basic_string<_CharT, _Traits, _Alloc>::
    281     append(size_type __n, _CharT __c)
    282     {
    283       if (__n)
    284 	{
    285 	  _M_check_length(size_type(0), __n, "basic_string::append");	  
    286 	  const size_type __len = __n + this->size();
    287 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
    288 	    this->reserve(__len);
    289 	  _M_assign(_M_data() + this->size(), __n, __c);
    290 	  _M_rep()->_M_set_length_and_sharable(__len);
    291 	}
    292       return *this;
    293     }
    294 
    295   template<typename _CharT, typename _Traits, typename _Alloc>
    296     basic_string<_CharT, _Traits, _Alloc>&
    297     basic_string<_CharT, _Traits, _Alloc>::
    298     append(const _CharT* __s, size_type __n)
    299     {
    300       __glibcxx_requires_string_len(__s, __n);
    301       if (__n)
    302 	{
    303 	  _M_check_length(size_type(0), __n, "basic_string::append");
    304 	  const size_type __len = __n + this->size();
    305 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
    306 	    {
    307 	      if (_M_disjunct(__s))
    308 		this->reserve(__len);
    309 	      else
    310 		{
    311 		  const size_type __off = __s - _M_data();
    312 		  this->reserve(__len);
    313 		  __s = _M_data() + __off;
    314 		}
    315 	    }
    316 	  _M_copy(_M_data() + this->size(), __s, __n);
    317 	  _M_rep()->_M_set_length_and_sharable(__len);
    318 	}
    319       return *this;
    320     }
    321 
    322   template<typename _CharT, typename _Traits, typename _Alloc>
    323     basic_string<_CharT, _Traits, _Alloc>&
    324     basic_string<_CharT, _Traits, _Alloc>::
    325     append(const basic_string& __str)
    326     {
    327       const size_type __size = __str.size();
    328       if (__size)
    329 	{
    330 	  const size_type __len = __size + this->size();
    331 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
    332 	    this->reserve(__len);
    333 	  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
    334 	  _M_rep()->_M_set_length_and_sharable(__len);
    335 	}
    336       return *this;
    337     }    
    338 
    339   template<typename _CharT, typename _Traits, typename _Alloc>
    340     basic_string<_CharT, _Traits, _Alloc>&
    341     basic_string<_CharT, _Traits, _Alloc>::
    342     append(const basic_string& __str, size_type __pos, size_type __n)
    343     {
    344       __str._M_check(__pos, "basic_string::append");
    345       __n = __str._M_limit(__pos, __n);
    346       if (__n)
    347 	{
    348 	  const size_type __len = __n + this->size();
    349 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
    350 	    this->reserve(__len);
    351 	  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
    352 	  _M_rep()->_M_set_length_and_sharable(__len);	  
    353 	}
    354       return *this;
    355     }
    356 
    357    template<typename _CharT, typename _Traits, typename _Alloc>
    358      basic_string<_CharT, _Traits, _Alloc>&
    359      basic_string<_CharT, _Traits, _Alloc>::
    360      insert(size_type __pos, const _CharT* __s, size_type __n)
    361      {
    362        __glibcxx_requires_string_len(__s, __n);
    363        _M_check(__pos, "basic_string::insert");
    364        _M_check_length(size_type(0), __n, "basic_string::insert");
    365        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
    366          return _M_replace_safe(__pos, size_type(0), __s, __n);
    367        else
    368          {
    369            // Work in-place.
    370            const size_type __off = __s - _M_data();
    371            _M_mutate(__pos, 0, __n);
    372            __s = _M_data() + __off;
    373            _CharT* __p = _M_data() + __pos;
    374            if (__s  + __n <= __p)
    375              _M_copy(__p, __s, __n);
    376            else if (__s >= __p)
    377              _M_copy(__p, __s + __n, __n);
    378            else
    379              {
    380 	       const size_type __nleft = __p - __s;
    381                _M_copy(__p, __s, __nleft);
    382                _M_copy(__p + __nleft, __p + __n, __n - __nleft);
    383              }
    384            return *this;
    385          }
    386      }
    387 
    388    template<typename _CharT, typename _Traits, typename _Alloc>
    389      typename basic_string<_CharT, _Traits, _Alloc>::iterator
    390      basic_string<_CharT, _Traits, _Alloc>::
    391      erase(iterator __first, iterator __last)
    392      {
    393        _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
    394 				&& __last <= _M_iend());
    395 
    396        // NB: This isn't just an optimization (bail out early when
    397        // there is nothing to do, really), it's also a correctness
    398        // issue vs MT, see libstdc++/40518.
    399        const size_type __size = __last - __first;
    400        if (__size)
    401 	 {
    402 	   const size_type __pos = __first - _M_ibegin();
    403 	   _M_mutate(__pos, __size, size_type(0));
    404 	   _M_rep()->_M_set_leaked();
    405 	   return iterator(_M_data() + __pos);
    406 	 }
    407        else
    408 	 return __first;
    409      }
    410 
    411    template<typename _CharT, typename _Traits, typename _Alloc>
    412      basic_string<_CharT, _Traits, _Alloc>&
    413      basic_string<_CharT, _Traits, _Alloc>::
    414      replace(size_type __pos, size_type __n1, const _CharT* __s,
    415 	     size_type __n2)
    416      {
    417        __glibcxx_requires_string_len(__s, __n2);
    418        _M_check(__pos, "basic_string::replace");
    419        __n1 = _M_limit(__pos, __n1);
    420        _M_check_length(__n1, __n2, "basic_string::replace");
    421        bool __left;
    422        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
    423          return _M_replace_safe(__pos, __n1, __s, __n2);
    424        else if ((__left = __s + __n2 <= _M_data() + __pos)
    425 		|| _M_data() + __pos + __n1 <= __s)
    426 	 {
    427 	   // Work in-place: non-overlapping case.
    428 	   size_type __off = __s - _M_data();
    429 	   __left ? __off : (__off += __n2 - __n1);
    430 	   _M_mutate(__pos, __n1, __n2);
    431 	   _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
    432 	   return *this;
    433 	 }
    434        else
    435 	 {
    436 	   // Todo: overlapping case.
    437 	   const basic_string __tmp(__s, __n2);
    438 	   return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
    439 	 }
    440      }
    441 
    442   template<typename _CharT, typename _Traits, typename _Alloc>
    443     void
    444     basic_string<_CharT, _Traits, _Alloc>::_Rep::
    445     _M_destroy(const _Alloc& __a) throw ()
    446     {
    447       const size_type __size = sizeof(_Rep_base) +
    448 	                       (this->_M_capacity + 1) * sizeof(_CharT);
    449       _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
    450     }
    451 
    452   template<typename _CharT, typename _Traits, typename _Alloc>
    453     void
    454     basic_string<_CharT, _Traits, _Alloc>::
    455     _M_leak_hard()
    456     {
    457 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
    458       if (_M_rep() == &_S_empty_rep())
    459 	return;
    460 #endif
    461       if (_M_rep()->_M_is_shared())
    462 	_M_mutate(0, 0, 0);
    463       _M_rep()->_M_set_leaked();
    464     }
    465 
    466   template<typename _CharT, typename _Traits, typename _Alloc>
    467     void
    468     basic_string<_CharT, _Traits, _Alloc>::
    469     _M_mutate(size_type __pos, size_type __len1, size_type __len2)
    470     {
    471       const size_type __old_size = this->size();
    472       const size_type __new_size = __old_size + __len2 - __len1;
    473       const size_type __how_much = __old_size - __pos - __len1;
    474 
    475       if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
    476 	{
    477 	  // Must reallocate.
    478 	  const allocator_type __a = get_allocator();
    479 	  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
    480 
    481 	  if (__pos)
    482 	    _M_copy(__r->_M_refdata(), _M_data(), __pos);
    483 	  if (__how_much)
    484 	    _M_copy(__r->_M_refdata() + __pos + __len2,
    485 		    _M_data() + __pos + __len1, __how_much);
    486 
    487 	  _M_rep()->_M_dispose(__a);
    488 	  _M_data(__r->_M_refdata());
    489 	}
    490       else if (__how_much && __len1 != __len2)
    491 	{
    492 	  // Work in-place.
    493 	  _M_move(_M_data() + __pos + __len2,
    494 		  _M_data() + __pos + __len1, __how_much);
    495 	}
    496       _M_rep()->_M_set_length_and_sharable(__new_size);
    497     }
    498 
    499   template<typename _CharT, typename _Traits, typename _Alloc>
    500     void
    501     basic_string<_CharT, _Traits, _Alloc>::
    502     reserve(size_type __res)
    503     {
    504       if (__res != this->capacity() || _M_rep()->_M_is_shared())
    505         {
    506 	  // Make sure we don't shrink below the current size
    507 	  if (__res < this->size())
    508 	    __res = this->size();
    509 	  const allocator_type __a = get_allocator();
    510 	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
    511 	  _M_rep()->_M_dispose(__a);
    512 	  _M_data(__tmp);
    513         }
    514     }
    515 
    516   template<typename _CharT, typename _Traits, typename _Alloc>
    517     void
    518     basic_string<_CharT, _Traits, _Alloc>::
    519     swap(basic_string& __s)
    520     {
    521       if (_M_rep()->_M_is_leaked())
    522 	_M_rep()->_M_set_sharable();
    523       if (__s._M_rep()->_M_is_leaked())
    524 	__s._M_rep()->_M_set_sharable();
    525       if (this->get_allocator() == __s.get_allocator())
    526 	{
    527 	  _CharT* __tmp = _M_data();
    528 	  _M_data(__s._M_data());
    529 	  __s._M_data(__tmp);
    530 	}
    531       // The code below can usually be optimized away.
    532       else
    533 	{
    534 	  const basic_string __tmp1(_M_ibegin(), _M_iend(),
    535 				    __s.get_allocator());
    536 	  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
    537 				    this->get_allocator());
    538 	  *this = __tmp2;
    539 	  __s = __tmp1;
    540 	}
    541     }
    542 
    543   template<typename _CharT, typename _Traits, typename _Alloc>
    544     typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
    545     basic_string<_CharT, _Traits, _Alloc>::_Rep::
    546     _S_create(size_type __capacity, size_type __old_capacity,
    547 	      const _Alloc& __alloc)
    548     {
    549       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    550       // 83.  String::npos vs. string::max_size()
    551       if (__capacity > _S_max_size)
    552 	__throw_length_error(__N("basic_string::_S_create"));
    553 
    554       // The standard places no restriction on allocating more memory
    555       // than is strictly needed within this layer at the moment or as
    556       // requested by an explicit application call to reserve().
    557 
    558       // Many malloc implementations perform quite poorly when an
    559       // application attempts to allocate memory in a stepwise fashion
    560       // growing each allocation size by only 1 char.  Additionally,
    561       // it makes little sense to allocate less linear memory than the
    562       // natural blocking size of the malloc implementation.
    563       // Unfortunately, we would need a somewhat low-level calculation
    564       // with tuned parameters to get this perfect for any particular
    565       // malloc implementation.  Fortunately, generalizations about
    566       // common features seen among implementations seems to suffice.
    567 
    568       // __pagesize need not match the actual VM page size for good
    569       // results in practice, thus we pick a common value on the low
    570       // side.  __malloc_header_size is an estimate of the amount of
    571       // overhead per memory allocation (in practice seen N * sizeof
    572       // (void*) where N is 0, 2 or 4).  According to folklore,
    573       // picking this value on the high side is better than
    574       // low-balling it (especially when this algorithm is used with
    575       // malloc implementations that allocate memory blocks rounded up
    576       // to a size which is a power of 2).
    577       const size_type __pagesize = 4096;
    578       const size_type __malloc_header_size = 4 * sizeof(void*);
    579 
    580       // The below implements an exponential growth policy, necessary to
    581       // meet amortized linear time requirements of the library: see
    582       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
    583       // It's active for allocations requiring an amount of memory above
    584       // system pagesize. This is consistent with the requirements of the
    585       // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
    586       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
    587 	__capacity = 2 * __old_capacity;
    588 
    589       // NB: Need an array of char_type[__capacity], plus a terminating
    590       // null char_type() element, plus enough for the _Rep data structure.
    591       // Whew. Seemingly so needy, yet so elemental.
    592       size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
    593 
    594       const size_type __adj_size = __size + __malloc_header_size;
    595       if (__adj_size > __pagesize && __capacity > __old_capacity)
    596 	{
    597 	  const size_type __extra = __pagesize - __adj_size % __pagesize;
    598 	  __capacity += __extra / sizeof(_CharT);
    599 	  // Never allocate a string bigger than _S_max_size.
    600 	  if (__capacity > _S_max_size)
    601 	    __capacity = _S_max_size;
    602 	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
    603 	}
    604 
    605       // NB: Might throw, but no worries about a leak, mate: _Rep()
    606       // does not throw.
    607       void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
    608       _Rep *__p = new (__place) _Rep;
    609       __p->_M_capacity = __capacity;
    610       // ABI compatibility - 3.4.x set in _S_create both
    611       // _M_refcount and _M_length.  All callers of _S_create
    612       // in basic_string.tcc then set just _M_length.
    613       // In 4.0.x and later both _M_refcount and _M_length
    614       // are initialized in the callers, unfortunately we can
    615       // have 3.4.x compiled code with _S_create callers inlined
    616       // calling 4.0.x+ _S_create.
    617       __p->_M_set_sharable();
    618       return __p;
    619     }
    620 
    621   template<typename _CharT, typename _Traits, typename _Alloc>
    622     _CharT*
    623     basic_string<_CharT, _Traits, _Alloc>::_Rep::
    624     _M_clone(const _Alloc& __alloc, size_type __res)
    625     {
    626       // Requested capacity of the clone.
    627       const size_type __requested_cap = this->_M_length + __res;
    628       _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
    629 				  __alloc);
    630       if (this->_M_length)
    631 	_M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
    632 
    633       __r->_M_set_length_and_sharable(this->_M_length);
    634       return __r->_M_refdata();
    635     }
    636 
    637   template<typename _CharT, typename _Traits, typename _Alloc>
    638     void
    639     basic_string<_CharT, _Traits, _Alloc>::
    640     resize(size_type __n, _CharT __c)
    641     {
    642       const size_type __size = this->size();
    643       _M_check_length(__size, __n, "basic_string::resize");
    644       if (__size < __n)
    645 	this->append(__n - __size, __c);
    646       else if (__n < __size)
    647 	this->erase(__n);
    648       // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
    649     }
    650 
    651   template<typename _CharT, typename _Traits, typename _Alloc>
    652     template<typename _InputIterator>
    653       basic_string<_CharT, _Traits, _Alloc>&
    654       basic_string<_CharT, _Traits, _Alloc>::
    655       _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
    656 			  _InputIterator __k2, __false_type)
    657       {
    658 	const basic_string __s(__k1, __k2);
    659 	const size_type __n1 = __i2 - __i1;
    660 	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
    661 	return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
    662 			       __s.size());
    663       }
    664 
    665   template<typename _CharT, typename _Traits, typename _Alloc>
    666     basic_string<_CharT, _Traits, _Alloc>&
    667     basic_string<_CharT, _Traits, _Alloc>::
    668     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
    669 		   _CharT __c)
    670     {
    671       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
    672       _M_mutate(__pos1, __n1, __n2);
    673       if (__n2)
    674 	_M_assign(_M_data() + __pos1, __n2, __c);
    675       return *this;
    676     }
    677 
    678   template<typename _CharT, typename _Traits, typename _Alloc>
    679     basic_string<_CharT, _Traits, _Alloc>&
    680     basic_string<_CharT, _Traits, _Alloc>::
    681     _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
    682 		    size_type __n2)
    683     {
    684       _M_mutate(__pos1, __n1, __n2);
    685       if (__n2)
    686 	_M_copy(_M_data() + __pos1, __s, __n2);
    687       return *this;
    688     }
    689    
    690   template<typename _CharT, typename _Traits, typename _Alloc>
    691     basic_string<_CharT, _Traits, _Alloc>
    692     operator+(const _CharT* __lhs,
    693 	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    694     {
    695       __glibcxx_requires_string(__lhs);
    696       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
    697       typedef typename __string_type::size_type	  __size_type;
    698       const __size_type __len = _Traits::length(__lhs);
    699       __string_type __str;
    700       __str.reserve(__len + __rhs.size());
    701       __str.append(__lhs, __len);
    702       __str.append(__rhs);
    703       return __str;
    704     }
    705 
    706   template<typename _CharT, typename _Traits, typename _Alloc>
    707     basic_string<_CharT, _Traits, _Alloc>
    708     operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    709     {
    710       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
    711       typedef typename __string_type::size_type	  __size_type;
    712       __string_type __str;
    713       const __size_type __len = __rhs.size();
    714       __str.reserve(__len + 1);
    715       __str.append(__size_type(1), __lhs);
    716       __str.append(__rhs);
    717       return __str;
    718     }
    719 
    720   template<typename _CharT, typename _Traits, typename _Alloc>
    721     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    722     basic_string<_CharT, _Traits, _Alloc>::
    723     copy(_CharT* __s, size_type __n, size_type __pos) const
    724     {
    725       _M_check(__pos, "basic_string::copy");
    726       __n = _M_limit(__pos, __n);
    727       __glibcxx_requires_string_len(__s, __n);
    728       if (__n)
    729 	_M_copy(__s, _M_data() + __pos, __n);
    730       // 21.3.5.7 par 3: do not append null.  (good.)
    731       return __n;
    732     }
    733 
    734   template<typename _CharT, typename _Traits, typename _Alloc>
    735     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    736     basic_string<_CharT, _Traits, _Alloc>::
    737     find(const _CharT* __s, size_type __pos, size_type __n) const
    738     {
    739       __glibcxx_requires_string_len(__s, __n);
    740       const size_type __size = this->size();
    741       const _CharT* __data = _M_data();
    742 
    743       if (__n == 0)
    744 	return __pos <= __size ? __pos : npos;
    745 
    746       if (__n <= __size)
    747 	{
    748 	  for (; __pos <= __size - __n; ++__pos)
    749 	    if (traits_type::eq(__data[__pos], __s[0])
    750 		&& traits_type::compare(__data + __pos + 1,
    751 					__s + 1, __n - 1) == 0)
    752 	      return __pos;
    753 	}
    754       return npos;
    755     }
    756 
    757   template<typename _CharT, typename _Traits, typename _Alloc>
    758     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    759     basic_string<_CharT, _Traits, _Alloc>::
    760     find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
    761     {
    762       size_type __ret = npos;
    763       const size_type __size = this->size();
    764       if (__pos < __size)
    765 	{
    766 	  const _CharT* __data = _M_data();
    767 	  const size_type __n = __size - __pos;
    768 	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
    769 	  if (__p)
    770 	    __ret = __p - __data;
    771 	}
    772       return __ret;
    773     }
    774 
    775   template<typename _CharT, typename _Traits, typename _Alloc>
    776     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    777     basic_string<_CharT, _Traits, _Alloc>::
    778     rfind(const _CharT* __s, size_type __pos, size_type __n) const
    779     {
    780       __glibcxx_requires_string_len(__s, __n);
    781       const size_type __size = this->size();
    782       if (__n <= __size)
    783 	{
    784 	  __pos = std::min(size_type(__size - __n), __pos);
    785 	  const _CharT* __data = _M_data();
    786 	  do
    787 	    {
    788 	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
    789 		return __pos;
    790 	    }
    791 	  while (__pos-- > 0);
    792 	}
    793       return npos;
    794     }
    795 
    796   template<typename _CharT, typename _Traits, typename _Alloc>
    797     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    798     basic_string<_CharT, _Traits, _Alloc>::
    799     rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
    800     {
    801       size_type __size = this->size();
    802       if (__size)
    803 	{
    804 	  if (--__size > __pos)
    805 	    __size = __pos;
    806 	  for (++__size; __size-- > 0; )
    807 	    if (traits_type::eq(_M_data()[__size], __c))
    808 	      return __size;
    809 	}
    810       return npos;
    811     }
    812 
    813   template<typename _CharT, typename _Traits, typename _Alloc>
    814     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    815     basic_string<_CharT, _Traits, _Alloc>::
    816     find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
    817     {
    818       __glibcxx_requires_string_len(__s, __n);
    819       for (; __n && __pos < this->size(); ++__pos)
    820 	{
    821 	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
    822 	  if (__p)
    823 	    return __pos;
    824 	}
    825       return npos;
    826     }
    827 
    828   template<typename _CharT, typename _Traits, typename _Alloc>
    829     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    830     basic_string<_CharT, _Traits, _Alloc>::
    831     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
    832     {
    833       __glibcxx_requires_string_len(__s, __n);
    834       size_type __size = this->size();
    835       if (__size && __n)
    836 	{
    837 	  if (--__size > __pos)
    838 	    __size = __pos;
    839 	  do
    840 	    {
    841 	      if (traits_type::find(__s, __n, _M_data()[__size]))
    842 		return __size;
    843 	    }
    844 	  while (__size-- != 0);
    845 	}
    846       return npos;
    847     }
    848 
    849   template<typename _CharT, typename _Traits, typename _Alloc>
    850     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    851     basic_string<_CharT, _Traits, _Alloc>::
    852     find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
    853     {
    854       __glibcxx_requires_string_len(__s, __n);
    855       for (; __pos < this->size(); ++__pos)
    856 	if (!traits_type::find(__s, __n, _M_data()[__pos]))
    857 	  return __pos;
    858       return npos;
    859     }
    860 
    861   template<typename _CharT, typename _Traits, typename _Alloc>
    862     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    863     basic_string<_CharT, _Traits, _Alloc>::
    864     find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
    865     {
    866       for (; __pos < this->size(); ++__pos)
    867 	if (!traits_type::eq(_M_data()[__pos], __c))
    868 	  return __pos;
    869       return npos;
    870     }
    871 
    872   template<typename _CharT, typename _Traits, typename _Alloc>
    873     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    874     basic_string<_CharT, _Traits, _Alloc>::
    875     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
    876     {
    877       __glibcxx_requires_string_len(__s, __n);
    878       size_type __size = this->size();
    879       if (__size)
    880 	{
    881 	  if (--__size > __pos)
    882 	    __size = __pos;
    883 	  do
    884 	    {
    885 	      if (!traits_type::find(__s, __n, _M_data()[__size]))
    886 		return __size;
    887 	    }
    888 	  while (__size--);
    889 	}
    890       return npos;
    891     }
    892 
    893   template<typename _CharT, typename _Traits, typename _Alloc>
    894     typename basic_string<_CharT, _Traits, _Alloc>::size_type
    895     basic_string<_CharT, _Traits, _Alloc>::
    896     find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
    897     {
    898       size_type __size = this->size();
    899       if (__size)
    900 	{
    901 	  if (--__size > __pos)
    902 	    __size = __pos;
    903 	  do
    904 	    {
    905 	      if (!traits_type::eq(_M_data()[__size], __c))
    906 		return __size;
    907 	    }
    908 	  while (__size--);
    909 	}
    910       return npos;
    911     }
    912 
    913   template<typename _CharT, typename _Traits, typename _Alloc>
    914     int
    915     basic_string<_CharT, _Traits, _Alloc>::
    916     compare(size_type __pos, size_type __n, const basic_string& __str) const
    917     {
    918       _M_check(__pos, "basic_string::compare");
    919       __n = _M_limit(__pos, __n);
    920       const size_type __osize = __str.size();
    921       const size_type __len = std::min(__n, __osize);
    922       int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
    923       if (!__r)
    924 	__r = _S_compare(__n, __osize);
    925       return __r;
    926     }
    927 
    928   template<typename _CharT, typename _Traits, typename _Alloc>
    929     int
    930     basic_string<_CharT, _Traits, _Alloc>::
    931     compare(size_type __pos1, size_type __n1, const basic_string& __str,
    932 	    size_type __pos2, size_type __n2) const
    933     {
    934       _M_check(__pos1, "basic_string::compare");
    935       __str._M_check(__pos2, "basic_string::compare");
    936       __n1 = _M_limit(__pos1, __n1);
    937       __n2 = __str._M_limit(__pos2, __n2);
    938       const size_type __len = std::min(__n1, __n2);
    939       int __r = traits_type::compare(_M_data() + __pos1,
    940 				     __str.data() + __pos2, __len);
    941       if (!__r)
    942 	__r = _S_compare(__n1, __n2);
    943       return __r;
    944     }
    945 
    946   template<typename _CharT, typename _Traits, typename _Alloc>
    947     int
    948     basic_string<_CharT, _Traits, _Alloc>::
    949     compare(const _CharT* __s) const
    950     {
    951       __glibcxx_requires_string(__s);
    952       const size_type __size = this->size();
    953       const size_type __osize = traits_type::length(__s);
    954       const size_type __len = std::min(__size, __osize);
    955       int __r = traits_type::compare(_M_data(), __s, __len);
    956       if (!__r)
    957 	__r = _S_compare(__size, __osize);
    958       return __r;
    959     }
    960 
    961   template<typename _CharT, typename _Traits, typename _Alloc>
    962     int
    963     basic_string <_CharT, _Traits, _Alloc>::
    964     compare(size_type __pos, size_type __n1, const _CharT* __s) const
    965     {
    966       __glibcxx_requires_string(__s);
    967       _M_check(__pos, "basic_string::compare");
    968       __n1 = _M_limit(__pos, __n1);
    969       const size_type __osize = traits_type::length(__s);
    970       const size_type __len = std::min(__n1, __osize);
    971       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
    972       if (!__r)
    973 	__r = _S_compare(__n1, __osize);
    974       return __r;
    975     }
    976 
    977   template<typename _CharT, typename _Traits, typename _Alloc>
    978     int
    979     basic_string <_CharT, _Traits, _Alloc>::
    980     compare(size_type __pos, size_type __n1, const _CharT* __s,
    981 	    size_type __n2) const
    982     {
    983       __glibcxx_requires_string_len(__s, __n2);
    984       _M_check(__pos, "basic_string::compare");
    985       __n1 = _M_limit(__pos, __n1);
    986       const size_type __len = std::min(__n1, __n2);
    987       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
    988       if (!__r)
    989 	__r = _S_compare(__n1, __n2);
    990       return __r;
    991     }
    992 
    993   // 21.3.7.9 basic_string::getline and operators
    994   template<typename _CharT, typename _Traits, typename _Alloc>
    995     basic_istream<_CharT, _Traits>&
    996     operator>>(basic_istream<_CharT, _Traits>& __in,
    997 	       basic_string<_CharT, _Traits, _Alloc>& __str)
    998     {
    999       typedef basic_istream<_CharT, _Traits>		__istream_type;
   1000       typedef basic_string<_CharT, _Traits, _Alloc>	__string_type;
   1001       typedef typename __istream_type::ios_base         __ios_base;
   1002       typedef typename __istream_type::int_type		__int_type;
   1003       typedef typename __string_type::size_type		__size_type;
   1004       typedef ctype<_CharT>				__ctype_type;
   1005       typedef typename __ctype_type::ctype_base         __ctype_base;
   1006 
   1007       __size_type __extracted = 0;
   1008       typename __ios_base::iostate __err = __ios_base::goodbit;
   1009       typename __istream_type::sentry __cerb(__in, false);
   1010       if (__cerb)
   1011 	{
   1012 	  __try
   1013 	    {
   1014 	      // Avoid reallocation for common case.
   1015 	      __str.erase();
   1016 	      _CharT __buf[128];
   1017 	      __size_type __len = 0;	      
   1018 	      const streamsize __w = __in.width();
   1019 	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
   1020 		                              : __str.max_size();
   1021 	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
   1022 	      const __int_type __eof = _Traits::eof();
   1023 	      __int_type __c = __in.rdbuf()->sgetc();
   1024 
   1025 	      while (__extracted < __n
   1026 		     && !_Traits::eq_int_type(__c, __eof)
   1027 		     && !__ct.is(__ctype_base::space,
   1028 				 _Traits::to_char_type(__c)))
   1029 		{
   1030 		  if (__len == sizeof(__buf) / sizeof(_CharT))
   1031 		    {
   1032 		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
   1033 		      __len = 0;
   1034 		    }
   1035 		  __buf[__len++] = _Traits::to_char_type(__c);
   1036 		  ++__extracted;
   1037 		  __c = __in.rdbuf()->snextc();
   1038 		}
   1039 	      __str.append(__buf, __len);
   1040 
   1041 	      if (_Traits::eq_int_type(__c, __eof))
   1042 		__err |= __ios_base::eofbit;
   1043 	      __in.width(0);
   1044 	    }
   1045 	  __catch(__cxxabiv1::__forced_unwind&)
   1046 	    {
   1047 	      __in._M_setstate(__ios_base::badbit);
   1048 	      __throw_exception_again;
   1049 	    }
   1050 	  __catch(...)
   1051 	    {
   1052 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1053 	      // 91. Description of operator>> and getline() for string<>
   1054 	      // might cause endless loop
   1055 	      __in._M_setstate(__ios_base::badbit);
   1056 	    }
   1057 	}
   1058       // 211.  operator>>(istream&, string&) doesn't set failbit
   1059       if (!__extracted)
   1060 	__err |= __ios_base::failbit;
   1061       if (__err)
   1062 	__in.setstate(__err);
   1063       return __in;
   1064     }
   1065 
   1066   template<typename _CharT, typename _Traits, typename _Alloc>
   1067     basic_istream<_CharT, _Traits>&
   1068     getline(basic_istream<_CharT, _Traits>& __in,
   1069 	    basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
   1070     {
   1071       typedef basic_istream<_CharT, _Traits>		__istream_type;
   1072       typedef basic_string<_CharT, _Traits, _Alloc>	__string_type;
   1073       typedef typename __istream_type::ios_base         __ios_base;
   1074       typedef typename __istream_type::int_type		__int_type;
   1075       typedef typename __string_type::size_type		__size_type;
   1076 
   1077       __size_type __extracted = 0;
   1078       const __size_type __n = __str.max_size();
   1079       typename __ios_base::iostate __err = __ios_base::goodbit;
   1080       typename __istream_type::sentry __cerb(__in, true);
   1081       if (__cerb)
   1082 	{
   1083 	  __try
   1084 	    {
   1085 	      __str.erase();
   1086 	      const __int_type __idelim = _Traits::to_int_type(__delim);
   1087 	      const __int_type __eof = _Traits::eof();
   1088 	      __int_type __c = __in.rdbuf()->sgetc();
   1089 
   1090 	      while (__extracted < __n
   1091 		     && !_Traits::eq_int_type(__c, __eof)
   1092 		     && !_Traits::eq_int_type(__c, __idelim))
   1093 		{
   1094 		  __str += _Traits::to_char_type(__c);
   1095 		  ++__extracted;
   1096 		  __c = __in.rdbuf()->snextc();
   1097 		}
   1098 
   1099 	      if (_Traits::eq_int_type(__c, __eof))
   1100 		__err |= __ios_base::eofbit;
   1101 	      else if (_Traits::eq_int_type(__c, __idelim))
   1102 		{
   1103 		  ++__extracted;		  
   1104 		  __in.rdbuf()->sbumpc();
   1105 		}
   1106 	      else
   1107 		__err |= __ios_base::failbit;
   1108 	    }
   1109 	  __catch(__cxxabiv1::__forced_unwind&)
   1110 	    {
   1111 	      __in._M_setstate(__ios_base::badbit);
   1112 	      __throw_exception_again;
   1113 	    }
   1114 	  __catch(...)
   1115 	    {
   1116 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1117 	      // 91. Description of operator>> and getline() for string<>
   1118 	      // might cause endless loop
   1119 	      __in._M_setstate(__ios_base::badbit);
   1120 	    }
   1121 	}
   1122       if (!__extracted)
   1123 	__err |= __ios_base::failbit;
   1124       if (__err)
   1125 	__in.setstate(__err);
   1126       return __in;
   1127     }
   1128 
   1129   // Inhibit implicit instantiations for required instantiations,
   1130   // which are defined via explicit instantiations elsewhere.
   1131 #if _GLIBCXX_EXTERN_TEMPLATE > 0
   1132   extern template class basic_string<char>;
   1133   extern template
   1134     basic_istream<char>&
   1135     operator>>(basic_istream<char>&, string&);
   1136   extern template
   1137     basic_ostream<char>&
   1138     operator<<(basic_ostream<char>&, const string&);
   1139   extern template
   1140     basic_istream<char>&
   1141     getline(basic_istream<char>&, string&, char);
   1142   extern template
   1143     basic_istream<char>&
   1144     getline(basic_istream<char>&, string&);
   1145 
   1146 #ifdef _GLIBCXX_USE_WCHAR_T
   1147   extern template class basic_string<wchar_t>;
   1148   extern template
   1149     basic_istream<wchar_t>&
   1150     operator>>(basic_istream<wchar_t>&, wstring&);
   1151   extern template
   1152     basic_ostream<wchar_t>&
   1153     operator<<(basic_ostream<wchar_t>&, const wstring&);
   1154   extern template
   1155     basic_istream<wchar_t>&
   1156     getline(basic_istream<wchar_t>&, wstring&, wchar_t);
   1157   extern template
   1158     basic_istream<wchar_t>&
   1159     getline(basic_istream<wchar_t>&, wstring&);
   1160 #endif
   1161 #endif
   1162 
   1163 _GLIBCXX_END_NAMESPACE_VERSION
   1164 } // namespace std
   1165 
   1166 #endif
   1167