basic_string.tcc revision 259694
1139823Simp// Components for manipulating sequences of characters -*- C++ -*-
2133920Sandre
3133920Sandre// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4133920Sandre// 2006, 2007
5133920Sandre// Free Software Foundation, Inc.
6133920Sandre//
7133920Sandre// This file is part of the GNU ISO C++ Library.  This library is free
8133920Sandre// software; you can redistribute it and/or modify it under the
9133920Sandre// terms of the GNU General Public License as published by the
10133920Sandre// Free Software Foundation; either version 2, or (at your option)
11133920Sandre// any later version.
12133920Sandre
13133920Sandre// This library is distributed in the hope that it will be useful,
14133920Sandre// but WITHOUT ANY WARRANTY; without even the implied warranty of
15133920Sandre// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16133920Sandre// GNU General Public License for more details.
17133920Sandre
18133920Sandre// You should have received a copy of the GNU General Public License along
19133920Sandre// with this library; see the file COPYING.  If not, write to the Free
20133920Sandre// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21133920Sandre// USA.
22133920Sandre
23133920Sandre// As a special exception, you may use this file as part of a free software
24133920Sandre// library without restriction.  Specifically, if other files instantiate
25133920Sandre// templates or use macros or inline functions from this file, or you compile
26133920Sandre// this file and link it with other files to produce an executable, this
27172467Ssilby// file does not by itself cause the resulting executable to be covered by
28172467Ssilby// the GNU General Public License.  This exception does not however
29172467Ssilby// invalidate any other reasons why the executable file might be covered by
30225518Sjhb// the GNU General Public License.
31133920Sandre
32225793Sbz/** @file basic_string.tcc
33133920Sandre *  This is an internal header file, included by other library headers.
34133920Sandre *  You should not attempt to use it directly.
35133920Sandre */
36133920Sandre
37133920Sandre//
38133920Sandre// ISO C++ 14882: 21  Strings library
39133920Sandre//
40133920Sandre
41133920Sandre// Written by Jason Merrill based upon the specification by Takanori Adachi
42133920Sandre// in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
43185895Szec
44185895Szec#ifndef _BASIC_STRING_TCC
45133920Sandre#define _BASIC_STRING_TCC 1
46133920Sandre
47133920Sandre#pragma GCC system_header
48133920Sandre
49133920Sandre_GLIBCXX_BEGIN_NAMESPACE(std)
50240099Smelifaro
51133920Sandre  template<typename _Type>
52196423Sjulian    inline bool
53133920Sandre    __is_null_pointer(_Type* __ptr)
54133920Sandre    { return __ptr == 0; }
55133920Sandre
56133920Sandre  template<typename _Type>
57133920Sandre    inline bool
58133920Sandre    __is_null_pointer(_Type)
59223593Sglebius    { return false; }
60223593Sglebius
61223593Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
62223593Sglebius    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
63200580Sluigi    basic_string<_CharT, _Traits, _Alloc>::
64201124Sluigi    _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
65133920Sandre
66133920Sandre  template<typename _CharT, typename _Traits, typename _Alloc>
67133920Sandre    const _CharT
68215701Sdim    basic_string<_CharT, _Traits, _Alloc>::
69200601Sluigi    _Rep::_S_terminal = _CharT();
70200601Sluigi
71158470Smlaier  template<typename _CharT, typename _Traits, typename _Alloc>
72215701Sdim    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
73200601Sluigi    basic_string<_CharT, _Traits, _Alloc>::npos;
74158470Smlaier
75133920Sandre  // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
76240099Smelifaro  // at static init time (before static ctors are run).
77240099Smelifaro  template<typename _CharT, typename _Traits, typename _Alloc>
78240099Smelifaro    typename basic_string<_CharT, _Traits, _Alloc>::size_type
79158470Smlaier    basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
80158470Smlaier    (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
81136714Sandre      sizeof(size_type)];
82201527Sluigi
83240099Smelifaro  // NB: This is the special case for Input Iterators, used in
84240099Smelifaro  // istreambuf_iterators, etc.
85240099Smelifaro  // Input Iterators have a cost structure very different from
86240099Smelifaro  // pointers, calling for a different coding style.
87133920Sandre  template<typename _CharT, typename _Traits, typename _Alloc>
88200601Sluigi    template<typename _InIterator>
89204591Sluigi      _CharT*
90204591Sluigi      basic_string<_CharT, _Traits, _Alloc>::
91204591Sluigi      _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
92200601Sluigi		   input_iterator_tag)
93200601Sluigi      {
94200601Sluigi#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
95200601Sluigi	if (__beg == __end && __a == _Alloc())
96200601Sluigi	  return _S_empty_rep()._M_refdata();
97200601Sluigi#endif
98200601Sluigi	// Avoid reallocation for common case.
99200601Sluigi	_CharT __buf[128];
100200601Sluigi	size_type __len = 0;
101200601Sluigi	while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
102204591Sluigi	  {
103240099Smelifaro	    __buf[__len++] = *__beg;
104240099Smelifaro	    ++__beg;
105240099Smelifaro	  }
106240099Smelifaro	_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
107240099Smelifaro	_M_copy(__r->_M_refdata(), __buf, __len);
108204591Sluigi	try
109204591Sluigi	  {
110200601Sluigi	    while (__beg != __end)
111200601Sluigi	      {
112201122Sluigi		if (__len == __r->_M_capacity)
113201122Sluigi		  {
114201122Sluigi		    // Allocate more space.
115201122Sluigi		    _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
116201122Sluigi		    _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
117240099Smelifaro		    __r->_M_destroy(__a);
118240099Smelifaro		    __r = __another;
119135920Smlaier		  }
120133920Sandre		__r->_M_refdata()[__len++] = *__beg;
121133920Sandre		++__beg;
122201527Sluigi	      }
123201122Sluigi	  }
124201122Sluigi	catch(...)
125133920Sandre	  {
126201527Sluigi	    __r->_M_destroy(__a);
127201740Sluigi	    __throw_exception_again;
128201740Sluigi	  }
129201527Sluigi	__r->_M_set_length_and_sharable(__len);
130201122Sluigi	return __r->_M_refdata();
131201122Sluigi      }
132133920Sandre
133133920Sandre  template<typename _CharT, typename _Traits, typename _Alloc>
134173399Soleg    template <typename _InIterator>
135201527Sluigi      _CharT*
136201527Sluigi      basic_string<_CharT, _Traits, _Alloc>::
137201527Sluigi      _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
138201527Sluigi		   forward_iterator_tag)
139201527Sluigi      {
140201527Sluigi#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
141201527Sluigi	if (__beg == __end && __a == _Alloc())
142201527Sluigi	  return _S_empty_rep()._M_refdata();
143201527Sluigi#endif
144223358Sae	// NB: Not required, but considered best practice.
145223358Sae	if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0))
146223358Sae	  __throw_logic_error(__N("basic_string::_S_construct NULL not valid"));
147201527Sluigi
148133920Sandre	const size_type __dnew = static_cast<size_type>(std::distance(__beg,
149133920Sandre								      __end));
150133920Sandre	// Check for out_of_range and length_error exceptions.
151201122Sluigi	_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
152135920Smlaier	try
153133920Sandre	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
154201527Sluigi	catch(...)
155201527Sluigi	  {
156191570Soleg	    __r->_M_destroy(__a);
157140224Sglebius	    __throw_exception_again;
158140224Sglebius	  }
159133920Sandre	__r->_M_set_length_and_sharable(__dnew);
160201122Sluigi	return __r->_M_refdata();
161201122Sluigi      }
162140224Sglebius
163140224Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
164201122Sluigi    _CharT*
165225044Sbz    basic_string<_CharT, _Traits, _Alloc>::
166206845Sluigi    _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
167225793Sbz    {
168201122Sluigi#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
169201122Sluigi      if (__n == 0 && __a == _Alloc())
170201527Sluigi	return _S_empty_rep()._M_refdata();
171201527Sluigi#endif
172225044Sbz      // Check for out_of_range and length_error exceptions.
173201527Sluigi      _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
174225044Sbz      if (__n)
175225044Sbz	_M_assign(__r->_M_refdata(), __n, __c);
176225044Sbz
177225044Sbz      __r->_M_set_length_and_sharable(__n);
178225044Sbz      return __r->_M_refdata();
179225044Sbz    }
180225044Sbz
181225044Sbz  template<typename _CharT, typename _Traits, typename _Alloc>
182225044Sbz    basic_string<_CharT, _Traits, _Alloc>::
183225044Sbz    basic_string(const basic_string& __str)
184225044Sbz    : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
185225044Sbz					  __str.get_allocator()),
186201122Sluigi		  __str.get_allocator())
187201122Sluigi    { }
188201122Sluigi
189201122Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
190201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
191201122Sluigi    basic_string(const _Alloc& __a)
192201122Sluigi    : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
193201122Sluigi    { }
194201122Sluigi
195225044Sbz  template<typename _CharT, typename _Traits, typename _Alloc>
196225044Sbz    basic_string<_CharT, _Traits, _Alloc>::
197201122Sluigi    basic_string(const basic_string& __str, size_type __pos, size_type __n)
198201122Sluigi    : _M_dataplus(_S_construct(__str._M_data()
199201122Sluigi			       + __str._M_check(__pos,
200201122Sluigi						"basic_string::basic_string"),
201201122Sluigi			       __str._M_data() + __str._M_limit(__pos, __n)
202225044Sbz			       + __pos, _Alloc()), _Alloc())
203225044Sbz    { }
204225044Sbz
205225044Sbz  template<typename _CharT, typename _Traits, typename _Alloc>
206225044Sbz    basic_string<_CharT, _Traits, _Alloc>::
207225044Sbz    basic_string(const basic_string& __str, size_type __pos,
208225044Sbz		 size_type __n, const _Alloc& __a)
209225044Sbz    : _M_dataplus(_S_construct(__str._M_data()
210225044Sbz			       + __str._M_check(__pos,
211225044Sbz						"basic_string::basic_string"),
212225044Sbz			       __str._M_data() + __str._M_limit(__pos, __n)
213225044Sbz			       + __pos, __a), __a)
214225044Sbz    { }
215225044Sbz
216133920Sandre  // TBD: DPG annotate
217201527Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
218225793Sbz    basic_string<_CharT, _Traits, _Alloc>::
219201122Sluigi    basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
220133920Sandre    : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
221140224Sglebius    { }
222201122Sluigi
223201122Sluigi  // TBD: DPG annotate
224140224Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
225140224Sglebius    basic_string<_CharT, _Traits, _Alloc>::
226201122Sluigi    basic_string(const _CharT* __s, const _Alloc& __a)
227193502Sluigi    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
228201122Sluigi			       __s + npos, __a), __a)
229145246Sbrooks    { }
230201122Sluigi
231145246Sbrooks  template<typename _CharT, typename _Traits, typename _Alloc>
232201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
233201122Sluigi    basic_string(size_type __n, _CharT __c, const _Alloc& __a)
234201122Sluigi    : _M_dataplus(_S_construct(__n, __c, __a), __a)
235201122Sluigi    { }
236201122Sluigi
237201122Sluigi  // TBD: DPG annotate
238201122Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
239201122Sluigi    template<typename _InputIterator>
240201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
241201122Sluigi    basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
242173399Soleg    : _M_dataplus(_S_construct(__beg, __end, __a), __a)
243173399Soleg    { }
244140224Sglebius
245140224Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
246140224Sglebius    basic_string<_CharT, _Traits, _Alloc>&
247140224Sglebius    basic_string<_CharT, _Traits, _Alloc>::
248201122Sluigi    assign(const basic_string& __str)
249201122Sluigi    {
250201122Sluigi      if (_M_rep() != __str._M_rep())
251201122Sluigi	{
252201527Sluigi	  // XXX MT
253201527Sluigi	  const allocator_type __a = this->get_allocator();
254201527Sluigi	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
255201527Sluigi	  _M_rep()->_M_dispose(__a);
256201527Sluigi	  _M_data(__tmp);
257201122Sluigi	}
258140224Sglebius      return *this;
259141351Sglebius    }
260141351Sglebius
261201732Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
262201122Sluigi    basic_string<_CharT, _Traits, _Alloc>&
263201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
264201122Sluigi    assign(const _CharT* __s, size_type __n)
265201122Sluigi    {
266201122Sluigi      __glibcxx_requires_string_len(__s, __n);
267201122Sluigi      _M_check_length(this->size(), __n, "basic_string::assign");
268201122Sluigi      if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
269201122Sluigi	return _M_replace_safe(size_type(0), this->size(), __s, __n);
270141351Sglebius      else
271165648Spiso	{
272213254Sluigi	  // Work in-place.
273213254Sluigi	  const size_type __pos = __s - _M_data();
274213254Sluigi	  if (__pos >= __n)
275213254Sluigi	    _M_copy(_M_data(), __s, __n);
276213254Sluigi	  else if (__pos)
277201122Sluigi	    _M_move(_M_data(), __s, __n);
278165648Spiso	  _M_rep()->_M_set_length_and_sharable(__n);
279190633Spiso	  return *this;
280140224Sglebius	}
281140224Sglebius     }
282140224Sglebius
283140224Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
284201122Sluigi    basic_string<_CharT, _Traits, _Alloc>&
285201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
286201527Sluigi    append(size_type __n, _CharT __c)
287201122Sluigi    {
288201122Sluigi      if (__n)
289201740Sluigi	{
290201527Sluigi	  _M_check_length(size_type(0), __n, "basic_string::append");	  
291201122Sluigi	  const size_type __len = __n + this->size();
292133920Sandre	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
293133920Sandre	    this->reserve(__len);
294240099Smelifaro	  _M_assign(_M_data() + this->size(), __n, __c);
295240099Smelifaro	  _M_rep()->_M_set_length_and_sharable(__len);
296240099Smelifaro	}
297240099Smelifaro      return *this;
298240099Smelifaro    }
299240099Smelifaro
300240099Smelifaro  template<typename _CharT, typename _Traits, typename _Alloc>
301240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>&
302240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>::
303240099Smelifaro    append(const _CharT* __s, size_type __n)
304240099Smelifaro    {
305240099Smelifaro      __glibcxx_requires_string_len(__s, __n);
306240099Smelifaro      if (__n)
307240099Smelifaro	{
308240099Smelifaro	  _M_check_length(size_type(0), __n, "basic_string::append");
309240099Smelifaro	  const size_type __len = __n + this->size();
310240099Smelifaro	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
311240099Smelifaro	    {
312240099Smelifaro	      if (_M_disjunct(__s))
313240099Smelifaro		this->reserve(__len);
314240099Smelifaro	      else
315240099Smelifaro		{
316240099Smelifaro		  const size_type __off = __s - _M_data();
317240099Smelifaro		  this->reserve(__len);
318240099Smelifaro		  __s = _M_data() + __off;
319240099Smelifaro		}
320240099Smelifaro	    }
321240099Smelifaro	  _M_copy(_M_data() + this->size(), __s, __n);
322240099Smelifaro	  _M_rep()->_M_set_length_and_sharable(__len);
323240099Smelifaro	}
324240099Smelifaro      return *this;
325240099Smelifaro    }
326240099Smelifaro
327240099Smelifaro  template<typename _CharT, typename _Traits, typename _Alloc>
328240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>&
329240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>::
330240099Smelifaro    append(const basic_string& __str)
331240099Smelifaro    {
332240099Smelifaro      const size_type __size = __str.size();
333240099Smelifaro      if (__size)
334240099Smelifaro	{
335240099Smelifaro	  const size_type __len = __size + this->size();
336240099Smelifaro	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
337240099Smelifaro	    this->reserve(__len);
338240099Smelifaro	  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
339240099Smelifaro	  _M_rep()->_M_set_length_and_sharable(__len);
340240099Smelifaro	}
341240099Smelifaro      return *this;
342240099Smelifaro    }    
343240099Smelifaro
344240099Smelifaro  template<typename _CharT, typename _Traits, typename _Alloc>
345240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>&
346240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>::
347240099Smelifaro    append(const basic_string& __str, size_type __pos, size_type __n)
348240099Smelifaro    {
349240099Smelifaro      __str._M_check(__pos, "basic_string::append");
350240099Smelifaro      __n = __str._M_limit(__pos, __n);
351240099Smelifaro      if (__n)
352240099Smelifaro	{
353240099Smelifaro	  const size_type __len = __n + this->size();
354240099Smelifaro	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
355240099Smelifaro	    this->reserve(__len);
356240099Smelifaro	  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
357240099Smelifaro	  _M_rep()->_M_set_length_and_sharable(__len);	  
358240099Smelifaro	}
359240099Smelifaro      return *this;
360240099Smelifaro    }
361240099Smelifaro
362240099Smelifaro   template<typename _CharT, typename _Traits, typename _Alloc>
363240099Smelifaro     basic_string<_CharT, _Traits, _Alloc>&
364240099Smelifaro     basic_string<_CharT, _Traits, _Alloc>::
365240099Smelifaro     insert(size_type __pos, const _CharT* __s, size_type __n)
366240099Smelifaro     {
367240099Smelifaro       __glibcxx_requires_string_len(__s, __n);
368240099Smelifaro       _M_check(__pos, "basic_string::insert");
369240099Smelifaro       _M_check_length(size_type(0), __n, "basic_string::insert");
370240099Smelifaro       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
371240099Smelifaro         return _M_replace_safe(__pos, size_type(0), __s, __n);
372240099Smelifaro       else
373240099Smelifaro         {
374240099Smelifaro           // Work in-place.
375240099Smelifaro           const size_type __off = __s - _M_data();
376240099Smelifaro           _M_mutate(__pos, 0, __n);
377240099Smelifaro           __s = _M_data() + __off;
378240099Smelifaro           _CharT* __p = _M_data() + __pos;
379240099Smelifaro           if (__s  + __n <= __p)
380240099Smelifaro             _M_copy(__p, __s, __n);
381240099Smelifaro           else if (__s >= __p)
382240099Smelifaro             _M_copy(__p, __s + __n, __n);
383240099Smelifaro           else
384240099Smelifaro             {
385240099Smelifaro	       const size_type __nleft = __p - __s;
386240099Smelifaro               _M_copy(__p, __s, __nleft);
387240099Smelifaro               _M_copy(__p + __nleft, __p + __n, __n - __nleft);
388240099Smelifaro             }
389240099Smelifaro           return *this;
390240099Smelifaro         }
391240099Smelifaro     }
392240099Smelifaro
393240099Smelifaro   template<typename _CharT, typename _Traits, typename _Alloc>
394240099Smelifaro     basic_string<_CharT, _Traits, _Alloc>&
395240099Smelifaro     basic_string<_CharT, _Traits, _Alloc>::
396240099Smelifaro     replace(size_type __pos, size_type __n1, const _CharT* __s,
397240099Smelifaro	     size_type __n2)
398240099Smelifaro     {
399201527Sluigi       __glibcxx_requires_string_len(__s, __n2);
400201527Sluigi       _M_check(__pos, "basic_string::replace");
401201527Sluigi       __n1 = _M_limit(__pos, __n1);
402201527Sluigi       _M_check_length(__n1, __n2, "basic_string::replace");
403133920Sandre       bool __left;
404133920Sandre       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
405135154Sandre         return _M_replace_safe(__pos, __n1, __s, __n2);
406133920Sandre       else if ((__left = __s + __n2 <= _M_data() + __pos)
407133920Sandre		|| _M_data() + __pos + __n1 <= __s)
408133920Sandre	 {
409201122Sluigi	   // Work in-place: non-overlapping case.
410223593Sglebius	   size_type __off = __s - _M_data();
411201527Sluigi	   __left ? __off : (__off += __n2 - __n1);
412133920Sandre	   _M_mutate(__pos, __n1, __n2);
413133920Sandre	   _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
414201122Sluigi	   return *this;
415201122Sluigi	 }
416201122Sluigi       else
417201122Sluigi	 {
418201122Sluigi	   // Todo: overlapping case.
419201122Sluigi	   const basic_string __tmp(__s, __n2);
420201122Sluigi	   return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
421201122Sluigi	 }
422201122Sluigi     }
423201527Sluigi
424201122Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
425133920Sandre    void
426133920Sandre    basic_string<_CharT, _Traits, _Alloc>::_Rep::
427201122Sluigi    _M_destroy(const _Alloc& __a) throw ()
428201122Sluigi    {
429201122Sluigi      const size_type __size = sizeof(_Rep_base) +
430201122Sluigi	                       (this->_M_capacity + 1) * sizeof(_CharT);
431201122Sluigi      _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
432201122Sluigi    }
433133920Sandre
434223593Sglebius  template<typename _CharT, typename _Traits, typename _Alloc>
435223593Sglebius    void
436223593Sglebius    basic_string<_CharT, _Traits, _Alloc>::
437201122Sluigi    _M_leak_hard()
438201122Sluigi    {
439133920Sandre#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
440201527Sluigi      if (_M_rep() == &_S_empty_rep())
441201122Sluigi	return;
442201122Sluigi#endif
443201527Sluigi      if (_M_rep()->_M_is_shared())
444201122Sluigi	_M_mutate(0, 0, 0);
445133920Sandre      _M_rep()->_M_set_leaked();
446133920Sandre    }
447133920Sandre
448133920Sandre  template<typename _CharT, typename _Traits, typename _Alloc>
449201122Sluigi    void
450201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::
451201122Sluigi    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
452201122Sluigi    {
453201122Sluigi      const size_type __old_size = this->size();
454201122Sluigi      const size_type __new_size = __old_size + __len2 - __len1;
455201122Sluigi      const size_type __how_much = __old_size - __pos - __len1;
456201122Sluigi
457201122Sluigi      if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
458223593Sglebius	{
459223593Sglebius	  // Must reallocate.
460223593Sglebius	  const allocator_type __a = get_allocator();
461223593Sglebius	  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
462223593Sglebius
463223593Sglebius	  if (__pos)
464223593Sglebius	    _M_copy(__r->_M_refdata(), _M_data(), __pos);
465223593Sglebius	  if (__how_much)
466223593Sglebius	    _M_copy(__r->_M_refdata() + __pos + __len2,
467223593Sglebius		    _M_data() + __pos + __len1, __how_much);
468223593Sglebius
469223593Sglebius	  _M_rep()->_M_dispose(__a);
470223593Sglebius	  _M_data(__r->_M_refdata());
471223593Sglebius	}
472223593Sglebius      else if (__how_much && __len1 != __len2)
473223593Sglebius	{
474223593Sglebius	  // Work in-place.
475223593Sglebius	  _M_move(_M_data() + __pos + __len2,
476133920Sandre		  _M_data() + __pos + __len1, __how_much);
477223593Sglebius	}
478201527Sluigi      _M_rep()->_M_set_length_and_sharable(__new_size);
479201527Sluigi    }
480201527Sluigi
481201527Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
482201527Sluigi    void
483201527Sluigi    basic_string<_CharT, _Traits, _Alloc>::
484201527Sluigi    reserve(size_type __res)
485201527Sluigi    {
486201527Sluigi      if (__res != this->capacity() || _M_rep()->_M_is_shared())
487133920Sandre        {
488133920Sandre	  // Make sure we don't shrink below the current size
489201122Sluigi	  if (__res < this->size())
490201527Sluigi	    __res = this->size();
491133920Sandre	  const allocator_type __a = get_allocator();
492133920Sandre	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
493201122Sluigi	  _M_rep()->_M_dispose(__a);
494201122Sluigi	  _M_data(__tmp);
495201122Sluigi        }
496200601Sluigi    }
497201122Sluigi
498133920Sandre  template<typename _CharT, typename _Traits, typename _Alloc>
499201122Sluigi    void
500240099Smelifaro    basic_string<_CharT, _Traits, _Alloc>::
501133920Sandre    swap(basic_string& __s)
502201122Sluigi    {
503201122Sluigi      if (_M_rep()->_M_is_leaked())
504133920Sandre	_M_rep()->_M_set_sharable();
505133920Sandre      if (__s._M_rep()->_M_is_leaked())
506240099Smelifaro	__s._M_rep()->_M_set_sharable();
507240099Smelifaro      if (this->get_allocator() == __s.get_allocator())
508201527Sluigi	{
509240099Smelifaro	  _CharT* __tmp = _M_data();
510133920Sandre	  _M_data(__s._M_data());
511133920Sandre	  __s._M_data(__tmp);
512133920Sandre	}
513133920Sandre      // The code below can usually be optimized away.
514196423Sjulian      else
515201122Sluigi	{
516133920Sandre	  const basic_string __tmp1(_M_ibegin(), _M_iend(),
517200601Sluigi				    __s.get_allocator());
518200601Sluigi	  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
519201122Sluigi				    this->get_allocator());
520201122Sluigi	  *this = __tmp2;
521206845Sluigi	  __s = __tmp1;
522200601Sluigi	}
523200601Sluigi    }
524200601Sluigi
525200601Sluigi  template<typename _CharT, typename _Traits, typename _Alloc>
526201122Sluigi    typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
527201122Sluigi    basic_string<_CharT, _Traits, _Alloc>::_Rep::
528206845Sluigi    _S_create(size_type __capacity, size_type __old_capacity,
529200601Sluigi	      const _Alloc& __alloc)
530200601Sluigi    {
531200601Sluigi      // _GLIBCXX_RESOLVE_LIB_DEFECTS
532200601Sluigi      // 83.  String::npos vs. string::max_size()
533240099Smelifaro      if (__capacity > _S_max_size)
534240099Smelifaro	__throw_length_error(__N("basic_string::_S_create"));
535240099Smelifaro
536240099Smelifaro      // The standard places no restriction on allocating more memory
537240099Smelifaro      // than is strictly needed within this layer at the moment or as
538240099Smelifaro      // requested by an explicit application call to reserve().
539200601Sluigi
540200601Sluigi      // Many malloc implementations perform quite poorly when an
541200601Sluigi      // application attempts to allocate memory in a stepwise fashion
542200601Sluigi      // growing each allocation size by only 1 char.  Additionally,
543158470Smlaier      // it makes little sense to allocate less linear memory than the
544158470Smlaier      // natural blocking size of the malloc implementation.
545240099Smelifaro      // Unfortunately, we would need a somewhat low-level calculation
546240099Smelifaro      // with tuned parameters to get this perfect for any particular
547158470Smlaier      // malloc implementation.  Fortunately, generalizations about
548201122Sluigi      // common features seen among implementations seems to suffice.
549158470Smlaier
550197952Sjulian      // __pagesize need not match the actual VM page size for good
551240099Smelifaro      // results in practice, thus we pick a common value on the low
552201122Sluigi      // side.  __malloc_header_size is an estimate of the amount of
553197952Sjulian      // overhead per memory allocation (in practice seen N * sizeof
554197952Sjulian      // (void*) where N is 0, 2 or 4).  According to folklore,
555197952Sjulian      // picking this value on the high side is better than
556240099Smelifaro      // low-balling it (especially when this algorithm is used with
557201122Sluigi      // malloc implementations that allocate memory blocks rounded up
558197952Sjulian      // to a size which is a power of 2).
559196423Sjulian      const size_type __pagesize = 4096;
560240099Smelifaro      const size_type __malloc_header_size = 4 * sizeof(void*);
561240099Smelifaro
562240099Smelifaro      // The below implements an exponential growth policy, necessary to
563240099Smelifaro      // meet amortized linear time requirements of the library: see
564197952Sjulian      // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
565197952Sjulian      // It's active for allocations requiring an amount of memory above
566197952Sjulian      // system pagesize. This is consistent with the requirements of the
567240099Smelifaro      // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
568197952Sjulian      if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
569240099Smelifaro	__capacity = 2 * __old_capacity;
570240099Smelifaro
571197952Sjulian      // NB: Need an array of char_type[__capacity], plus a terminating
572158470Smlaier      // null char_type() element, plus enough for the _Rep data structure.
573158470Smlaier      // Whew. Seemingly so needy, yet so elemental.
574158470Smlaier      size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
575240099Smelifaro
576240099Smelifaro      const size_type __adj_size = __size + __malloc_header_size;
577158470Smlaier      if (__adj_size > __pagesize && __capacity > __old_capacity)
578240099Smelifaro	{
579158470Smlaier	  const size_type __extra = __pagesize - __adj_size % __pagesize;
580158470Smlaier	  __capacity += __extra / sizeof(_CharT);
581240099Smelifaro	  // Never allocate a string bigger than _S_max_size.
582201122Sluigi	  if (__capacity > _S_max_size)
583201122Sluigi	    __capacity = _S_max_size;
584240099Smelifaro	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
585158470Smlaier	}
586158470Smlaier
587158470Smlaier      // NB: Might throw, but no worries about a leak, mate: _Rep()
588200601Sluigi      // does not throw.
589      void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
590      _Rep *__p = new (__place) _Rep;
591      __p->_M_capacity = __capacity;
592      // ABI compatibility - 3.4.x set in _S_create both
593      // _M_refcount and _M_length.  All callers of _S_create
594      // in basic_string.tcc then set just _M_length.
595      // In 4.0.x and later both _M_refcount and _M_length
596      // are initialized in the callers, unfortunately we can
597      // have 3.4.x compiled code with _S_create callers inlined
598      // calling 4.0.x+ _S_create.
599      __p->_M_set_sharable();
600      return __p;
601    }
602
603  template<typename _CharT, typename _Traits, typename _Alloc>
604    _CharT*
605    basic_string<_CharT, _Traits, _Alloc>::_Rep::
606    _M_clone(const _Alloc& __alloc, size_type __res)
607    {
608      // Requested capacity of the clone.
609      const size_type __requested_cap = this->_M_length + __res;
610      _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
611				  __alloc);
612      if (this->_M_length)
613	_M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
614
615      __r->_M_set_length_and_sharable(this->_M_length);
616      return __r->_M_refdata();
617    }
618
619  template<typename _CharT, typename _Traits, typename _Alloc>
620    void
621    basic_string<_CharT, _Traits, _Alloc>::
622    resize(size_type __n, _CharT __c)
623    {
624      const size_type __size = this->size();
625      _M_check_length(__size, __n, "basic_string::resize");
626      if (__size < __n)
627	this->append(__n - __size, __c);
628      else if (__n < __size)
629	this->erase(__n);
630      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
631    }
632
633  template<typename _CharT, typename _Traits, typename _Alloc>
634    template<typename _InputIterator>
635      basic_string<_CharT, _Traits, _Alloc>&
636      basic_string<_CharT, _Traits, _Alloc>::
637      _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
638			  _InputIterator __k2, __false_type)
639      {
640	const basic_string __s(__k1, __k2);
641	const size_type __n1 = __i2 - __i1;
642	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
643	return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
644			       __s.size());
645      }
646
647  template<typename _CharT, typename _Traits, typename _Alloc>
648    basic_string<_CharT, _Traits, _Alloc>&
649    basic_string<_CharT, _Traits, _Alloc>::
650    _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
651		   _CharT __c)
652    {
653      _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
654      _M_mutate(__pos1, __n1, __n2);
655      if (__n2)
656	_M_assign(_M_data() + __pos1, __n2, __c);
657      return *this;
658    }
659
660  template<typename _CharT, typename _Traits, typename _Alloc>
661    basic_string<_CharT, _Traits, _Alloc>&
662    basic_string<_CharT, _Traits, _Alloc>::
663    _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
664		    size_type __n2)
665    {
666      _M_mutate(__pos1, __n1, __n2);
667      if (__n2)
668	_M_copy(_M_data() + __pos1, __s, __n2);
669      return *this;
670    }
671   
672  template<typename _CharT, typename _Traits, typename _Alloc>
673    basic_string<_CharT, _Traits, _Alloc>
674    operator+(const _CharT* __lhs,
675	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
676    {
677      __glibcxx_requires_string(__lhs);
678      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
679      typedef typename __string_type::size_type	  __size_type;
680      const __size_type __len = _Traits::length(__lhs);
681      __string_type __str;
682      __str.reserve(__len + __rhs.size());
683      __str.append(__lhs, __len);
684      __str.append(__rhs);
685      return __str;
686    }
687
688  template<typename _CharT, typename _Traits, typename _Alloc>
689    basic_string<_CharT, _Traits, _Alloc>
690    operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
691    {
692      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
693      typedef typename __string_type::size_type	  __size_type;
694      __string_type __str;
695      const __size_type __len = __rhs.size();
696      __str.reserve(__len + 1);
697      __str.append(__size_type(1), __lhs);
698      __str.append(__rhs);
699      return __str;
700    }
701
702  template<typename _CharT, typename _Traits, typename _Alloc>
703    typename basic_string<_CharT, _Traits, _Alloc>::size_type
704    basic_string<_CharT, _Traits, _Alloc>::
705    copy(_CharT* __s, size_type __n, size_type __pos) const
706    {
707      _M_check(__pos, "basic_string::copy");
708      __n = _M_limit(__pos, __n);
709      __glibcxx_requires_string_len(__s, __n);
710      if (__n)
711	_M_copy(__s, _M_data() + __pos, __n);
712      // 21.3.5.7 par 3: do not append null.  (good.)
713      return __n;
714    }
715
716  template<typename _CharT, typename _Traits, typename _Alloc>
717    typename basic_string<_CharT, _Traits, _Alloc>::size_type
718    basic_string<_CharT, _Traits, _Alloc>::
719    find(const _CharT* __s, size_type __pos, size_type __n) const
720    {
721      __glibcxx_requires_string_len(__s, __n);
722      const size_type __size = this->size();
723      const _CharT* __data = _M_data();
724
725      if (__n == 0)
726	return __pos <= __size ? __pos : npos;
727
728      if (__n <= __size)
729	{
730	  for (; __pos <= __size - __n; ++__pos)
731	    if (traits_type::eq(__data[__pos], __s[0])
732		&& traits_type::compare(__data + __pos + 1,
733					__s + 1, __n - 1) == 0)
734	      return __pos;
735	}
736      return npos;
737    }
738
739  template<typename _CharT, typename _Traits, typename _Alloc>
740    typename basic_string<_CharT, _Traits, _Alloc>::size_type
741    basic_string<_CharT, _Traits, _Alloc>::
742    find(_CharT __c, size_type __pos) const
743    {
744      size_type __ret = npos;
745      const size_type __size = this->size();
746      if (__pos < __size)
747	{
748	  const _CharT* __data = _M_data();
749	  const size_type __n = __size - __pos;
750	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
751	  if (__p)
752	    __ret = __p - __data;
753	}
754      return __ret;
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    rfind(const _CharT* __s, size_type __pos, size_type __n) const
761    {
762      __glibcxx_requires_string_len(__s, __n);
763      const size_type __size = this->size();
764      if (__n <= __size)
765	{
766	  __pos = std::min(size_type(__size - __n), __pos);
767	  const _CharT* __data = _M_data();
768	  do
769	    {
770	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
771		return __pos;
772	    }
773	  while (__pos-- > 0);
774	}
775      return npos;
776    }
777
778  template<typename _CharT, typename _Traits, typename _Alloc>
779    typename basic_string<_CharT, _Traits, _Alloc>::size_type
780    basic_string<_CharT, _Traits, _Alloc>::
781    rfind(_CharT __c, size_type __pos) const
782    {
783      size_type __size = this->size();
784      if (__size)
785	{
786	  if (--__size > __pos)
787	    __size = __pos;
788	  for (++__size; __size-- > 0; )
789	    if (traits_type::eq(_M_data()[__size], __c))
790	      return __size;
791	}
792      return npos;
793    }
794
795  template<typename _CharT, typename _Traits, typename _Alloc>
796    typename basic_string<_CharT, _Traits, _Alloc>::size_type
797    basic_string<_CharT, _Traits, _Alloc>::
798    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
799    {
800      __glibcxx_requires_string_len(__s, __n);
801      for (; __n && __pos < this->size(); ++__pos)
802	{
803	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
804	  if (__p)
805	    return __pos;
806	}
807      return npos;
808    }
809
810  template<typename _CharT, typename _Traits, typename _Alloc>
811    typename basic_string<_CharT, _Traits, _Alloc>::size_type
812    basic_string<_CharT, _Traits, _Alloc>::
813    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
814    {
815      __glibcxx_requires_string_len(__s, __n);
816      size_type __size = this->size();
817      if (__size && __n)
818	{
819	  if (--__size > __pos)
820	    __size = __pos;
821	  do
822	    {
823	      if (traits_type::find(__s, __n, _M_data()[__size]))
824		return __size;
825	    }
826	  while (__size-- != 0);
827	}
828      return npos;
829    }
830
831  template<typename _CharT, typename _Traits, typename _Alloc>
832    typename basic_string<_CharT, _Traits, _Alloc>::size_type
833    basic_string<_CharT, _Traits, _Alloc>::
834    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
835    {
836      __glibcxx_requires_string_len(__s, __n);
837      for (; __pos < this->size(); ++__pos)
838	if (!traits_type::find(__s, __n, _M_data()[__pos]))
839	  return __pos;
840      return npos;
841    }
842
843  template<typename _CharT, typename _Traits, typename _Alloc>
844    typename basic_string<_CharT, _Traits, _Alloc>::size_type
845    basic_string<_CharT, _Traits, _Alloc>::
846    find_first_not_of(_CharT __c, size_type __pos) const
847    {
848      for (; __pos < this->size(); ++__pos)
849	if (!traits_type::eq(_M_data()[__pos], __c))
850	  return __pos;
851      return npos;
852    }
853
854  template<typename _CharT, typename _Traits, typename _Alloc>
855    typename basic_string<_CharT, _Traits, _Alloc>::size_type
856    basic_string<_CharT, _Traits, _Alloc>::
857    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
858    {
859      __glibcxx_requires_string_len(__s, __n);
860      size_type __size = this->size();
861      if (__size)
862	{
863	  if (--__size > __pos)
864	    __size = __pos;
865	  do
866	    {
867	      if (!traits_type::find(__s, __n, _M_data()[__size]))
868		return __size;
869	    }
870	  while (__size--);
871	}
872      return npos;
873    }
874
875  template<typename _CharT, typename _Traits, typename _Alloc>
876    typename basic_string<_CharT, _Traits, _Alloc>::size_type
877    basic_string<_CharT, _Traits, _Alloc>::
878    find_last_not_of(_CharT __c, size_type __pos) const
879    {
880      size_type __size = this->size();
881      if (__size)
882	{
883	  if (--__size > __pos)
884	    __size = __pos;
885	  do
886	    {
887	      if (!traits_type::eq(_M_data()[__size], __c))
888		return __size;
889	    }
890	  while (__size--);
891	}
892      return npos;
893    }
894
895  template<typename _CharT, typename _Traits, typename _Alloc>
896    int
897    basic_string<_CharT, _Traits, _Alloc>::
898    compare(size_type __pos, size_type __n, const basic_string& __str) const
899    {
900      _M_check(__pos, "basic_string::compare");
901      __n = _M_limit(__pos, __n);
902      const size_type __osize = __str.size();
903      const size_type __len = std::min(__n, __osize);
904      int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
905      if (!__r)
906	__r = _S_compare(__n, __osize);
907      return __r;
908    }
909
910  template<typename _CharT, typename _Traits, typename _Alloc>
911    int
912    basic_string<_CharT, _Traits, _Alloc>::
913    compare(size_type __pos1, size_type __n1, const basic_string& __str,
914	    size_type __pos2, size_type __n2) const
915    {
916      _M_check(__pos1, "basic_string::compare");
917      __str._M_check(__pos2, "basic_string::compare");
918      __n1 = _M_limit(__pos1, __n1);
919      __n2 = __str._M_limit(__pos2, __n2);
920      const size_type __len = std::min(__n1, __n2);
921      int __r = traits_type::compare(_M_data() + __pos1,
922				     __str.data() + __pos2, __len);
923      if (!__r)
924	__r = _S_compare(__n1, __n2);
925      return __r;
926    }
927
928  template<typename _CharT, typename _Traits, typename _Alloc>
929    int
930    basic_string<_CharT, _Traits, _Alloc>::
931    compare(const _CharT* __s) const
932    {
933      __glibcxx_requires_string(__s);
934      const size_type __size = this->size();
935      const size_type __osize = traits_type::length(__s);
936      const size_type __len = std::min(__size, __osize);
937      int __r = traits_type::compare(_M_data(), __s, __len);
938      if (!__r)
939	__r = _S_compare(__size, __osize);
940      return __r;
941    }
942
943  template<typename _CharT, typename _Traits, typename _Alloc>
944    int
945    basic_string <_CharT, _Traits, _Alloc>::
946    compare(size_type __pos, size_type __n1, const _CharT* __s) const
947    {
948      __glibcxx_requires_string(__s);
949      _M_check(__pos, "basic_string::compare");
950      __n1 = _M_limit(__pos, __n1);
951      const size_type __osize = traits_type::length(__s);
952      const size_type __len = std::min(__n1, __osize);
953      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
954      if (!__r)
955	__r = _S_compare(__n1, __osize);
956      return __r;
957    }
958
959  template<typename _CharT, typename _Traits, typename _Alloc>
960    int
961    basic_string <_CharT, _Traits, _Alloc>::
962    compare(size_type __pos, size_type __n1, const _CharT* __s,
963	    size_type __n2) const
964    {
965      __glibcxx_requires_string_len(__s, __n2);
966      _M_check(__pos, "basic_string::compare");
967      __n1 = _M_limit(__pos, __n1);
968      const size_type __len = std::min(__n1, __n2);
969      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
970      if (!__r)
971	__r = _S_compare(__n1, __n2);
972      return __r;
973    }
974
975  // Inhibit implicit instantiations for required instantiations,
976  // which are defined via explicit instantiations elsewhere.
977  // NB: This syntax is a GNU extension.
978#if _GLIBCXX_EXTERN_TEMPLATE
979  extern template class basic_string<char>;
980  extern template
981    basic_istream<char>&
982    operator>>(basic_istream<char>&, string&);
983  extern template
984    basic_ostream<char>&
985    operator<<(basic_ostream<char>&, const string&);
986  extern template
987    basic_istream<char>&
988    getline(basic_istream<char>&, string&, char);
989  extern template
990    basic_istream<char>&
991    getline(basic_istream<char>&, string&);
992
993#ifdef _GLIBCXX_USE_WCHAR_T
994  extern template class basic_string<wchar_t>;
995  extern template
996    basic_istream<wchar_t>&
997    operator>>(basic_istream<wchar_t>&, wstring&);
998  extern template
999    basic_ostream<wchar_t>&
1000    operator<<(basic_ostream<wchar_t>&, const wstring&);
1001  extern template
1002    basic_istream<wchar_t>&
1003    getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1004  extern template
1005    basic_istream<wchar_t>&
1006    getline(basic_istream<wchar_t>&, wstring&);
1007#endif
1008#endif
1009
1010_GLIBCXX_END_NAMESPACE
1011
1012#endif
1013