string revision 1.1
1// Debugging string implementation -*- C++ -*-
2
3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26/** @file debug/string
27 *  This file is a GNU debug extension to the Standard C++ Library.
28 */
29
30#ifndef _GLIBCXX_DEBUG_STRING
31#define _GLIBCXX_DEBUG_STRING 1
32
33#include <string>
34#include <debug/safe_sequence.h>
35#include <debug/safe_iterator.h>
36
37namespace __gnu_debug
38{
39  /// Class std::basic_string with safety/checking/debug instrumentation.
40  template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
41            typename _Allocator = std::allocator<_CharT> >
42    class basic_string
43    : public std::basic_string<_CharT, _Traits, _Allocator>,
44      public __gnu_debug::_Safe_sequence<basic_string<_CharT, _Traits,
45						      _Allocator> >
46    {
47      typedef std::basic_string<_CharT, _Traits, _Allocator> _Base;
48      typedef __gnu_debug::_Safe_sequence<basic_string>     _Safe_base;
49
50  public:
51    // types:
52    typedef _Traits				       traits_type;
53    typedef typename _Traits::char_type		       value_type;
54    typedef _Allocator				       allocator_type;
55    typedef typename _Base::size_type                  size_type;
56    typedef typename _Base::difference_type            difference_type;
57    typedef typename _Base::reference                  reference;
58    typedef typename _Base::const_reference            const_reference;
59    typedef typename _Base::pointer                    pointer;
60    typedef typename _Base::const_pointer              const_pointer;
61
62    typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, basic_string>
63                                                       iterator;
64    typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
65                                         basic_string> const_iterator;
66
67    typedef std::reverse_iterator<iterator>            reverse_iterator;
68    typedef std::reverse_iterator<const_iterator>      const_reverse_iterator;
69
70    using _Base::npos;
71
72    // 21.3.1 construct/copy/destroy:
73    explicit basic_string(const _Allocator& __a = _Allocator())
74    : _Base(__a)
75    { }
76
77    // Provides conversion from a release-mode string to a debug-mode string
78    basic_string(const _Base& __base) : _Base(__base), _Safe_base() { }
79
80    // _GLIBCXX_RESOLVE_LIB_DEFECTS
81    // 42. string ctors specify wrong default allocator
82    basic_string(const basic_string& __str)
83    : _Base(__str, 0, _Base::npos, __str.get_allocator()), _Safe_base()
84    { }
85
86    // _GLIBCXX_RESOLVE_LIB_DEFECTS
87    // 42. string ctors specify wrong default allocator
88    basic_string(const basic_string& __str, size_type __pos,
89		   size_type __n = _Base::npos,
90		   const _Allocator& __a = _Allocator())
91    : _Base(__str, __pos, __n, __a)
92    { }
93
94    basic_string(const _CharT* __s, size_type __n,
95		   const _Allocator& __a = _Allocator())
96    : _Base(__gnu_debug::__check_string(__s, __n), __n, __a)
97    { }
98
99    basic_string(const _CharT* __s, const _Allocator& __a = _Allocator())
100    : _Base(__gnu_debug::__check_string(__s), __a)
101    { this->assign(__s); }
102
103    basic_string(size_type __n, _CharT __c,
104		   const _Allocator& __a = _Allocator())
105    : _Base(__n, __c, __a)
106    { }
107
108    template<typename _InputIterator>
109      basic_string(_InputIterator __begin, _InputIterator __end,
110		     const _Allocator& __a = _Allocator())
111      : _Base(__gnu_debug::__check_valid_range(__begin, __end), __end, __a)
112      { }
113
114#ifdef __GXX_EXPERIMENTAL_CXX0X__
115    basic_string(basic_string&& __str)
116    : _Base(std::forward<_Base>(__str))
117    { }
118
119    basic_string(std::initializer_list<_CharT> __l,
120		 const _Allocator& __a = _Allocator())
121    : _Base(__l, __a)
122    { }
123#endif // __GXX_EXPERIMENTAL_CXX0X__
124
125    ~basic_string() { }
126
127    basic_string&
128    operator=(const basic_string& __str)
129    {
130      *static_cast<_Base*>(this) = __str;
131      this->_M_invalidate_all();
132      return *this;
133    }
134
135    basic_string&
136    operator=(const _CharT* __s)
137    {
138      __glibcxx_check_string(__s);
139      *static_cast<_Base*>(this) = __s;
140      this->_M_invalidate_all();
141      return *this;
142    }
143
144    basic_string&
145    operator=(_CharT __c)
146    {
147      *static_cast<_Base*>(this) = __c;
148      this->_M_invalidate_all();
149      return *this;
150    }
151
152#ifdef __GXX_EXPERIMENTAL_CXX0X__
153    basic_string&
154    operator=(basic_string&& __str)
155    {
156      *static_cast<_Base*>(this) = std::forward<_Base>(__str);
157      this->_M_invalidate_all();
158      return *this;
159    }
160
161    basic_string&
162    operator=(std::initializer_list<_CharT> __l)
163    {
164      *static_cast<_Base*>(this) = __l;
165      this->_M_invalidate_all();
166      return *this;
167    }
168#endif // __GXX_EXPERIMENTAL_CXX0X__
169
170    // 21.3.2 iterators:
171    iterator
172    begin()
173    { return iterator(_Base::begin(), this); }
174
175    const_iterator
176    begin() const
177    { return const_iterator(_Base::begin(), this); }
178
179    iterator
180    end()
181    { return iterator(_Base::end(), this); }
182
183    const_iterator
184    end() const
185    { return const_iterator(_Base::end(), this); }
186
187    reverse_iterator
188    rbegin()
189    { return reverse_iterator(end()); }
190
191    const_reverse_iterator
192    rbegin() const
193    { return const_reverse_iterator(end()); }
194
195    reverse_iterator
196    rend()
197    { return reverse_iterator(begin()); }
198
199    const_reverse_iterator
200    rend() const
201    { return const_reverse_iterator(begin()); }
202
203    // 21.3.3 capacity:
204    using _Base::size;
205    using _Base::length;
206    using _Base::max_size;
207
208    void
209    resize(size_type __n, _CharT __c)
210    {
211      _Base::resize(__n, __c);
212      this->_M_invalidate_all();
213    }
214
215    void
216    resize(size_type __n)
217    { this->resize(__n, _CharT()); }
218
219#ifdef __GXX_EXPERIMENTAL_CXX0X__
220    using _Base::shrink_to_fit;
221#endif
222
223    using _Base::capacity;
224    using _Base::reserve;
225
226    void
227    clear()
228    {
229      _Base::clear();
230      this->_M_invalidate_all();
231    }
232
233    using _Base::empty;
234
235    // 21.3.4 element access:
236    const_reference
237    operator[](size_type __pos) const
238    {
239      _GLIBCXX_DEBUG_VERIFY(__pos <= this->size(),
240			    _M_message(__gnu_debug::__msg_subscript_oob)
241			    ._M_sequence(*this, "this")
242			    ._M_integer(__pos, "__pos")
243			    ._M_integer(this->size(), "size"));
244      return _M_base()[__pos];
245    }
246
247    reference
248    operator[](size_type __pos)
249    {
250#ifdef _GLIBCXX_DEBUG_PEDANTIC
251      __glibcxx_check_subscript(__pos);
252#else
253      // as an extension v3 allows s[s.size()] when s is non-const.
254      _GLIBCXX_DEBUG_VERIFY(__pos <= this->size(),
255			    _M_message(__gnu_debug::__msg_subscript_oob)
256			    ._M_sequence(*this, "this")
257			    ._M_integer(__pos, "__pos")
258			    ._M_integer(this->size(), "size"));
259#endif
260      return _M_base()[__pos];
261    }
262
263    using _Base::at;
264
265    // 21.3.5 modifiers:
266    basic_string&
267    operator+=(const basic_string& __str)
268    {
269      _M_base() += __str;
270      this->_M_invalidate_all();
271      return *this;
272    }
273
274    basic_string&
275    operator+=(const _CharT* __s)
276    {
277      __glibcxx_check_string(__s);
278      _M_base() += __s;
279      this->_M_invalidate_all();
280      return *this;
281    }
282
283    basic_string&
284    operator+=(_CharT __c)
285    {
286      _M_base() += __c;
287      this->_M_invalidate_all();
288      return *this;
289    }
290
291#ifdef __GXX_EXPERIMENTAL_CXX0X__
292    basic_string&
293    operator+=(std::initializer_list<_CharT> __l)
294    {
295      _M_base() += __l;
296      this->_M_invalidate_all();
297      return *this;
298    }
299#endif // __GXX_EXPERIMENTAL_CXX0X__
300
301    basic_string&
302    append(const basic_string& __str)
303    {
304      _Base::append(__str);
305      this->_M_invalidate_all();
306      return *this;
307    }
308
309    basic_string&
310    append(const basic_string& __str, size_type __pos, size_type __n)
311    {
312      _Base::append(__str, __pos, __n);
313      this->_M_invalidate_all();
314      return *this;
315    }
316
317    basic_string&
318    append(const _CharT* __s, size_type __n)
319    {
320      __glibcxx_check_string_len(__s, __n);
321      _Base::append(__s, __n);
322      this->_M_invalidate_all();
323      return *this;
324    }
325
326    basic_string&
327    append(const _CharT* __s)
328    {
329      __glibcxx_check_string(__s);
330      _Base::append(__s);
331      this->_M_invalidate_all();
332      return *this;
333    }
334
335    basic_string&
336    append(size_type __n, _CharT __c)
337    {
338      _Base::append(__n, __c);
339      this->_M_invalidate_all();
340      return *this;
341    }
342
343    template<typename _InputIterator>
344      basic_string&
345      append(_InputIterator __first, _InputIterator __last)
346      {
347	__glibcxx_check_valid_range(__first, __last);
348	_Base::append(__first, __last);
349	this->_M_invalidate_all();
350	return *this;
351      }
352
353    // _GLIBCXX_RESOLVE_LIB_DEFECTS
354    // 7. string clause minor problems
355    void
356    push_back(_CharT __c)
357    {
358      _Base::push_back(__c);
359      this->_M_invalidate_all();
360    }
361
362    basic_string&
363    assign(const basic_string& __x)
364    {
365      _Base::assign(__x);
366      this->_M_invalidate_all();
367      return *this;
368    }
369
370#ifdef __GXX_EXPERIMENTAL_CXX0X__
371    basic_string&
372    assign(basic_string&& __x)
373    {
374      _Base::assign(std::forward<_Base>(__x));
375      this->_M_invalidate_all();
376      return *this;
377    }
378#endif // __GXX_EXPERIMENTAL_CXX0X__
379
380    basic_string&
381    assign(const basic_string& __str, size_type __pos, size_type __n)
382    {
383      _Base::assign(__str, __pos, __n);
384      this->_M_invalidate_all();
385      return *this;
386    }
387
388    basic_string&
389    assign(const _CharT* __s, size_type __n)
390    {
391      __glibcxx_check_string_len(__s, __n);
392      _Base::assign(__s, __n);
393      this->_M_invalidate_all();
394      return *this;
395    }
396
397    basic_string&
398    assign(const _CharT* __s)
399    {
400      __glibcxx_check_string(__s);
401      _Base::assign(__s);
402      this->_M_invalidate_all();
403      return *this;
404    }
405
406    basic_string&
407    assign(size_type __n, _CharT __c)
408    {
409      _Base::assign(__n, __c);
410      this->_M_invalidate_all();
411      return *this;
412    }
413
414    template<typename _InputIterator>
415      basic_string&
416      assign(_InputIterator __first, _InputIterator __last)
417      {
418	__glibcxx_check_valid_range(__first, __last);
419	_Base::assign(__first, __last);
420	this->_M_invalidate_all();
421	return *this;
422      }
423
424#ifdef __GXX_EXPERIMENTAL_CXX0X__
425    basic_string&
426    assign(std::initializer_list<_CharT> __l)
427    {
428      _Base::assign(__l);
429      this->_M_invalidate_all();
430      return *this;
431    }
432#endif // __GXX_EXPERIMENTAL_CXX0X__
433
434    basic_string&
435    insert(size_type __pos1, const basic_string& __str)
436    {
437      _Base::insert(__pos1, __str);
438      this->_M_invalidate_all();
439      return *this;
440    }
441
442    basic_string&
443    insert(size_type __pos1, const basic_string& __str,
444	   size_type __pos2, size_type __n)
445    {
446      _Base::insert(__pos1, __str, __pos2, __n);
447      this->_M_invalidate_all();
448      return *this;
449    }
450
451    basic_string&
452    insert(size_type __pos, const _CharT* __s, size_type __n)
453    {
454      __glibcxx_check_string(__s);
455      _Base::insert(__pos, __s, __n);
456      this->_M_invalidate_all();
457      return *this;
458    }
459
460    basic_string&
461    insert(size_type __pos, const _CharT* __s)
462    {
463      __glibcxx_check_string(__s);
464      _Base::insert(__pos, __s);
465      this->_M_invalidate_all();
466      return *this;
467    }
468
469    basic_string&
470    insert(size_type __pos, size_type __n, _CharT __c)
471    {
472      _Base::insert(__pos, __n, __c);
473      this->_M_invalidate_all();
474      return *this;
475    }
476
477    iterator
478    insert(iterator __p, _CharT __c)
479    {
480      __glibcxx_check_insert(__p);
481      typename _Base::iterator __res = _Base::insert(__p.base(), __c);
482      this->_M_invalidate_all();
483      return iterator(__res, this);
484    }
485
486    void
487    insert(iterator __p, size_type __n, _CharT __c)
488    {
489      __glibcxx_check_insert(__p);
490      _Base::insert(__p.base(), __n, __c);
491      this->_M_invalidate_all();
492    }
493
494    template<typename _InputIterator>
495      void
496      insert(iterator __p, _InputIterator __first, _InputIterator __last)
497      {
498	__glibcxx_check_insert_range(__p, __first, __last);
499	_Base::insert(__p.base(), __first, __last);
500	this->_M_invalidate_all();
501      }
502
503#ifdef __GXX_EXPERIMENTAL_CXX0X__
504    void
505    insert(iterator __p, std::initializer_list<_CharT> __l)
506    {
507      _Base::insert(__p, __l);
508      this->_M_invalidate_all();
509    }
510#endif // __GXX_EXPERIMENTAL_CXX0X__
511
512    basic_string&
513    erase(size_type __pos = 0, size_type __n = _Base::npos)
514    {
515      _Base::erase(__pos, __n);
516      this->_M_invalidate_all();
517      return *this;
518    }
519
520    iterator
521    erase(iterator __position)
522    {
523      __glibcxx_check_erase(__position);
524      typename _Base::iterator __res = _Base::erase(__position.base());
525      this->_M_invalidate_all();
526      return iterator(__res, this);
527    }
528
529    iterator
530    erase(iterator __first, iterator __last)
531    {
532      // _GLIBCXX_RESOLVE_LIB_DEFECTS
533      // 151. can't currently clear() empty container
534      __glibcxx_check_erase_range(__first, __last);
535      typename _Base::iterator __res = _Base::erase(__first.base(),
536						       __last.base());
537      this->_M_invalidate_all();
538      return iterator(__res, this);
539    }
540
541    basic_string&
542    replace(size_type __pos1, size_type __n1, const basic_string& __str)
543    {
544      _Base::replace(__pos1, __n1, __str);
545      this->_M_invalidate_all();
546      return *this;
547    }
548
549    basic_string&
550    replace(size_type __pos1, size_type __n1, const basic_string& __str,
551	    size_type __pos2, size_type __n2)
552    {
553      _Base::replace(__pos1, __n1, __str, __pos2, __n2);
554      this->_M_invalidate_all();
555      return *this;
556    }
557
558    basic_string&
559    replace(size_type __pos, size_type __n1, const _CharT* __s,
560	    size_type __n2)
561    {
562      __glibcxx_check_string_len(__s, __n2);
563      _Base::replace(__pos, __n1, __s, __n2);
564      this->_M_invalidate_all();
565      return *this;
566    }
567
568    basic_string&
569    replace(size_type __pos, size_type __n1, const _CharT* __s)
570    {
571      __glibcxx_check_string(__s);
572      _Base::replace(__pos, __n1, __s);
573      this->_M_invalidate_all();
574      return *this;
575    }
576
577    basic_string&
578    replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
579    {
580      _Base::replace(__pos, __n1, __n2, __c);
581      this->_M_invalidate_all();
582      return *this;
583    }
584
585    basic_string&
586    replace(iterator __i1, iterator __i2, const basic_string& __str)
587    {
588      __glibcxx_check_erase_range(__i1, __i2);
589      _Base::replace(__i1.base(), __i2.base(), __str);
590      this->_M_invalidate_all();
591      return *this;
592    }
593
594    basic_string&
595    replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n)
596    {
597      __glibcxx_check_erase_range(__i1, __i2);
598      __glibcxx_check_string_len(__s, __n);
599      _Base::replace(__i1.base(), __i2.base(), __s, __n);
600      this->_M_invalidate_all();
601      return *this;
602    }
603
604    basic_string&
605    replace(iterator __i1, iterator __i2, const _CharT* __s)
606    {
607      __glibcxx_check_erase_range(__i1, __i2);
608      __glibcxx_check_string(__s);
609      _Base::replace(__i1.base(), __i2.base(), __s);
610      this->_M_invalidate_all();
611      return *this;
612    }
613
614    basic_string&
615    replace(iterator __i1, iterator __i2, size_type __n, _CharT __c)
616    {
617      __glibcxx_check_erase_range(__i1, __i2);
618      _Base::replace(__i1.base(), __i2.base(), __n, __c);
619      this->_M_invalidate_all();
620      return *this;
621    }
622
623    template<typename _InputIterator>
624      basic_string&
625      replace(iterator __i1, iterator __i2,
626	      _InputIterator __j1, _InputIterator __j2)
627      {
628	__glibcxx_check_erase_range(__i1, __i2);
629	__glibcxx_check_valid_range(__j1, __j2);
630	_Base::replace(__i1.base(), __i2.base(), __j1, __j2);
631	this->_M_invalidate_all();
632	return *this;
633      }
634
635#ifdef __GXX_EXPERIMENTAL_CXX0X__
636      basic_string& replace(iterator __i1, iterator __i2,
637			    std::initializer_list<_CharT> __l)
638      {
639	__glibcxx_check_erase_range(__i1, __i2);
640	_Base::replace(__i1.base(), __i2.base(), __l);
641	this->_M_invalidate_all();
642	return *this;
643      }
644#endif // __GXX_EXPERIMENTAL_CXX0X__
645
646    size_type
647    copy(_CharT* __s, size_type __n, size_type __pos = 0) const
648    {
649      __glibcxx_check_string_len(__s, __n);
650      return _Base::copy(__s, __n, __pos);
651    }
652
653    void
654    swap(basic_string<_CharT,_Traits,_Allocator>& __x)
655    {
656      _Base::swap(__x);
657      this->_M_swap(__x);
658      this->_M_invalidate_all();
659      __x._M_invalidate_all();
660    }
661
662    // 21.3.6 string operations:
663    const _CharT*
664    c_str() const
665    {
666      const _CharT* __res = _Base::c_str();
667      this->_M_invalidate_all();
668      return __res;
669    }
670
671    const _CharT*
672    data() const
673    {
674      const _CharT* __res = _Base::data();
675      this->_M_invalidate_all();
676      return __res;
677    }
678
679    using _Base::get_allocator;
680
681    size_type
682    find(const basic_string& __str, size_type __pos = 0) const
683    { return _Base::find(__str, __pos); }
684
685    size_type
686    find(const _CharT* __s, size_type __pos, size_type __n) const
687    {
688      __glibcxx_check_string(__s);
689      return _Base::find(__s, __pos, __n);
690    }
691
692    size_type
693    find(const _CharT* __s, size_type __pos = 0) const
694    {
695      __glibcxx_check_string(__s);
696      return _Base::find(__s, __pos);
697    }
698
699    size_type
700    find(_CharT __c, size_type __pos = 0) const
701    { return _Base::find(__c, __pos); }
702
703    size_type
704    rfind(const basic_string& __str, size_type __pos = _Base::npos) const
705    { return _Base::rfind(__str, __pos); }
706
707    size_type
708    rfind(const _CharT* __s, size_type __pos, size_type __n) const
709    {
710      __glibcxx_check_string_len(__s, __n);
711      return _Base::rfind(__s, __pos, __n);
712    }
713
714    size_type
715    rfind(const _CharT* __s, size_type __pos = _Base::npos) const
716    {
717      __glibcxx_check_string(__s);
718      return _Base::rfind(__s, __pos);
719    }
720
721    size_type
722    rfind(_CharT __c, size_type __pos = _Base::npos) const
723    { return _Base::rfind(__c, __pos); }
724
725    size_type
726    find_first_of(const basic_string& __str, size_type __pos = 0) const
727    { return _Base::find_first_of(__str, __pos); }
728
729    size_type
730    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
731    {
732      __glibcxx_check_string(__s);
733      return _Base::find_first_of(__s, __pos, __n);
734    }
735
736    size_type
737    find_first_of(const _CharT* __s, size_type __pos = 0) const
738    {
739      __glibcxx_check_string(__s);
740      return _Base::find_first_of(__s, __pos);
741    }
742
743    size_type
744    find_first_of(_CharT __c, size_type __pos = 0) const
745    { return _Base::find_first_of(__c, __pos); }
746
747    size_type
748    find_last_of(const basic_string& __str, 
749		 size_type __pos = _Base::npos) const
750    { return _Base::find_last_of(__str, __pos); }
751
752    size_type
753    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
754    {
755      __glibcxx_check_string(__s);
756      return _Base::find_last_of(__s, __pos, __n);
757    }
758
759    size_type
760    find_last_of(const _CharT* __s, size_type __pos = _Base::npos) const
761    {
762      __glibcxx_check_string(__s);
763      return _Base::find_last_of(__s, __pos);
764    }
765
766    size_type
767    find_last_of(_CharT __c, size_type __pos = _Base::npos) const
768    { return _Base::find_last_of(__c, __pos); }
769
770    size_type
771    find_first_not_of(const basic_string& __str, size_type __pos = 0) const
772    { return _Base::find_first_not_of(__str, __pos); }
773
774    size_type
775    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
776    {
777      __glibcxx_check_string_len(__s, __n);
778      return _Base::find_first_not_of(__s, __pos, __n);
779    }
780
781    size_type
782    find_first_not_of(const _CharT* __s, size_type __pos = 0) const
783    {
784      __glibcxx_check_string(__s);
785      return _Base::find_first_not_of(__s, __pos);
786    }
787
788    size_type
789    find_first_not_of(_CharT __c, size_type __pos = 0) const
790    { return _Base::find_first_not_of(__c, __pos); }
791
792    size_type
793    find_last_not_of(const basic_string& __str,
794				  size_type __pos = _Base::npos) const
795    { return _Base::find_last_not_of(__str, __pos); }
796
797    size_type
798    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
799    {
800      __glibcxx_check_string(__s);
801      return _Base::find_last_not_of(__s, __pos, __n);
802    }
803
804    size_type
805    find_last_not_of(const _CharT* __s, size_type __pos = _Base::npos) const
806    {
807      __glibcxx_check_string(__s);
808      return _Base::find_last_not_of(__s, __pos);
809    }
810
811    size_type
812    find_last_not_of(_CharT __c, size_type __pos = _Base::npos) const
813    { return _Base::find_last_not_of(__c, __pos); }
814
815    basic_string
816    substr(size_type __pos = 0, size_type __n = _Base::npos) const
817    { return basic_string(_Base::substr(__pos, __n)); }
818
819    int
820    compare(const basic_string& __str) const
821    { return _Base::compare(__str); }
822
823    int
824    compare(size_type __pos1, size_type __n1,
825		  const basic_string& __str) const
826    { return _Base::compare(__pos1, __n1, __str); }
827
828    int
829    compare(size_type __pos1, size_type __n1, const basic_string& __str,
830	      size_type __pos2, size_type __n2) const
831    { return _Base::compare(__pos1, __n1, __str, __pos2, __n2); }
832
833    int
834    compare(const _CharT* __s) const
835    {
836      __glibcxx_check_string(__s);
837      return _Base::compare(__s);
838    }
839
840    //  _GLIBCXX_RESOLVE_LIB_DEFECTS
841    //  5. string::compare specification questionable
842    int
843    compare(size_type __pos1, size_type __n1, const _CharT* __s) const
844    {
845      __glibcxx_check_string(__s);
846      return _Base::compare(__pos1, __n1, __s);
847    }
848
849    //  _GLIBCXX_RESOLVE_LIB_DEFECTS
850    //  5. string::compare specification questionable
851    int
852    compare(size_type __pos1, size_type __n1,const _CharT* __s,
853	      size_type __n2) const
854    {
855      __glibcxx_check_string_len(__s, __n2);
856      return _Base::compare(__pos1, __n1, __s, __n2);
857    }
858
859    _Base&
860    _M_base() { return *this; }
861
862    const _Base&
863    _M_base() const { return *this; }
864
865    using _Safe_base::_M_invalidate_all;
866  };
867
868  template<typename _CharT, typename _Traits, typename _Allocator>
869    inline basic_string<_CharT,_Traits,_Allocator>
870    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
871	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
872    { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; }
873
874  template<typename _CharT, typename _Traits, typename _Allocator>
875    inline basic_string<_CharT,_Traits,_Allocator>
876    operator+(const _CharT* __lhs,
877	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
878    {
879      __glibcxx_check_string(__lhs);
880      return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs;
881    }
882
883  template<typename _CharT, typename _Traits, typename _Allocator>
884    inline basic_string<_CharT,_Traits,_Allocator>
885    operator+(_CharT __lhs,
886	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
887    { return basic_string<_CharT,_Traits,_Allocator>(1, __lhs) += __rhs; }
888
889  template<typename _CharT, typename _Traits, typename _Allocator>
890    inline basic_string<_CharT,_Traits,_Allocator>
891    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
892	      const _CharT* __rhs)
893    {
894      __glibcxx_check_string(__rhs);
895      return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs;
896    }
897
898  template<typename _CharT, typename _Traits, typename _Allocator>
899    inline basic_string<_CharT,_Traits,_Allocator>
900    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
901	      _CharT __rhs)
902    { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; }
903
904  template<typename _CharT, typename _Traits, typename _Allocator>
905    inline bool
906    operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
907	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
908    { return __lhs._M_base() == __rhs._M_base(); }
909
910  template<typename _CharT, typename _Traits, typename _Allocator>
911    inline bool
912    operator==(const _CharT* __lhs,
913	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
914    {
915      __glibcxx_check_string(__lhs);
916      return __lhs == __rhs._M_base();
917    }
918
919  template<typename _CharT, typename _Traits, typename _Allocator>
920    inline bool
921    operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
922	       const _CharT* __rhs)
923    {
924      __glibcxx_check_string(__rhs);
925      return __lhs._M_base() == __rhs;
926    }
927
928  template<typename _CharT, typename _Traits, typename _Allocator>
929    inline bool
930    operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
931	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
932    { return __lhs._M_base() != __rhs._M_base(); }
933
934  template<typename _CharT, typename _Traits, typename _Allocator>
935    inline bool
936    operator!=(const _CharT* __lhs,
937	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
938    {
939      __glibcxx_check_string(__lhs);
940      return __lhs != __rhs._M_base();
941    }
942
943  template<typename _CharT, typename _Traits, typename _Allocator>
944    inline bool
945    operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
946	       const _CharT* __rhs)
947    {
948      __glibcxx_check_string(__rhs);
949      return __lhs._M_base() != __rhs;
950    }
951
952  template<typename _CharT, typename _Traits, typename _Allocator>
953    inline bool
954    operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
955	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
956    { return __lhs._M_base() < __rhs._M_base(); }
957
958  template<typename _CharT, typename _Traits, typename _Allocator>
959    inline bool
960    operator<(const _CharT* __lhs,
961	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
962    {
963      __glibcxx_check_string(__lhs);
964      return __lhs < __rhs._M_base();
965    }
966
967  template<typename _CharT, typename _Traits, typename _Allocator>
968    inline bool
969    operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
970	      const _CharT* __rhs)
971    {
972      __glibcxx_check_string(__rhs);
973      return __lhs._M_base() < __rhs;
974    }
975
976  template<typename _CharT, typename _Traits, typename _Allocator>
977    inline bool
978    operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
979	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
980    { return __lhs._M_base() <= __rhs._M_base(); }
981
982  template<typename _CharT, typename _Traits, typename _Allocator>
983    inline bool
984    operator<=(const _CharT* __lhs,
985	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
986    {
987      __glibcxx_check_string(__lhs);
988      return __lhs <= __rhs._M_base();
989    }
990
991  template<typename _CharT, typename _Traits, typename _Allocator>
992    inline bool
993    operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
994	       const _CharT* __rhs)
995    {
996      __glibcxx_check_string(__rhs);
997      return __lhs._M_base() <= __rhs;
998    }
999
1000  template<typename _CharT, typename _Traits, typename _Allocator>
1001    inline bool
1002    operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1003	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1004    { return __lhs._M_base() >= __rhs._M_base(); }
1005
1006  template<typename _CharT, typename _Traits, typename _Allocator>
1007    inline bool
1008    operator>=(const _CharT* __lhs,
1009	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1010    {
1011      __glibcxx_check_string(__lhs);
1012      return __lhs >= __rhs._M_base();
1013    }
1014
1015  template<typename _CharT, typename _Traits, typename _Allocator>
1016    inline bool
1017    operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1018	       const _CharT* __rhs)
1019    {
1020      __glibcxx_check_string(__rhs);
1021      return __lhs._M_base() >= __rhs;
1022    }
1023
1024  template<typename _CharT, typename _Traits, typename _Allocator>
1025    inline bool
1026    operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1027	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1028    { return __lhs._M_base() > __rhs._M_base(); }
1029
1030  template<typename _CharT, typename _Traits, typename _Allocator>
1031    inline bool
1032    operator>(const _CharT* __lhs,
1033	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1034    {
1035      __glibcxx_check_string(__lhs);
1036      return __lhs > __rhs._M_base();
1037    }
1038
1039  template<typename _CharT, typename _Traits, typename _Allocator>
1040    inline bool
1041    operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1042	      const _CharT* __rhs)
1043    {
1044      __glibcxx_check_string(__rhs);
1045      return __lhs._M_base() > __rhs;
1046    }
1047
1048  // 21.3.7.8:
1049  template<typename _CharT, typename _Traits, typename _Allocator>
1050    inline void
1051    swap(basic_string<_CharT,_Traits,_Allocator>& __lhs,
1052	 basic_string<_CharT,_Traits,_Allocator>& __rhs)
1053    { __lhs.swap(__rhs); }
1054
1055  template<typename _CharT, typename _Traits, typename _Allocator>
1056    std::basic_ostream<_CharT, _Traits>&
1057    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
1058	       const basic_string<_CharT, _Traits, _Allocator>& __str)
1059    { return __os << __str._M_base(); }
1060
1061  template<typename _CharT, typename _Traits, typename _Allocator>
1062    std::basic_istream<_CharT,_Traits>&
1063    operator>>(std::basic_istream<_CharT,_Traits>& __is,
1064	       basic_string<_CharT,_Traits,_Allocator>& __str)
1065    {
1066      std::basic_istream<_CharT,_Traits>& __res = __is >> __str._M_base();
1067      __str._M_invalidate_all();
1068      return __res;
1069    }
1070
1071  template<typename _CharT, typename _Traits, typename _Allocator>
1072    std::basic_istream<_CharT,_Traits>&
1073    getline(std::basic_istream<_CharT,_Traits>& __is,
1074	    basic_string<_CharT,_Traits,_Allocator>& __str, _CharT __delim)
1075    {
1076      std::basic_istream<_CharT,_Traits>& __res = getline(__is,
1077							  __str._M_base(),
1078							__delim);
1079      __str._M_invalidate_all();
1080      return __res;
1081    }
1082
1083  template<typename _CharT, typename _Traits, typename _Allocator>
1084    std::basic_istream<_CharT,_Traits>&
1085    getline(std::basic_istream<_CharT,_Traits>& __is,
1086	    basic_string<_CharT,_Traits,_Allocator>& __str)
1087    {
1088      std::basic_istream<_CharT,_Traits>& __res = getline(__is,
1089							  __str._M_base());
1090      __str._M_invalidate_all();
1091      return __res;
1092    }
1093
1094  typedef basic_string<char>    string;
1095
1096#ifdef _GLIBCXX_USE_WCHAR_T
1097  typedef basic_string<wchar_t> wstring;
1098#endif
1099
1100} // namespace __gnu_debug
1101
1102#endif
1103