1 // Components for manipulating sequences of characters -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
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 2, or (at your option)
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.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 // ISO C++ 14882: 21 Strings library
34 /** @file basic_string.h
35 * This is an internal header file, included by other library headers.
36 * You should not attempt to use it directly.
39 #ifndef _CPP_BITS_STRING_H
40 #define _CPP_BITS_STRING_H 1
42 #pragma GCC system_header
44 #include <bits/atomicity.h>
48 // Documentation? What's that?
49 // Nathan Myers <ncm@cantrip.org>.
51 // A string looks like this:
55 // [basic_string<char_type>] _M_capacity
56 // _M_dataplus _M_state
57 // _M_p ----------------> unnamed array of char_type
59 // Where the _M_p points to the first character in the string, and
60 // you cast it to a pointer-to-_Rep and subtract 1 to get a
61 // pointer to the header.
63 // This approach has the enormous advantage that a string object
64 // requires only one allocation. All the ugliness is confined
65 // within a single pair of inline functions, which each compile to
66 // a single "add" instruction: _Rep::_M_data(), and
67 // string::_M_rep(); and the allocation function which gets a
68 // block of raw bytes and with room enough and constructs a _Rep
69 // object at the front.
71 // The reason you want _M_data pointing to the character array and
72 // not the _Rep is so that the debugger can see the string
73 // contents. (Probably we should add a non-inline member to get
74 // the _Rep for the debugger to use, so users can check the actual
77 // Note that the _Rep object is a POD so that you can have a
78 // static "empty string" _Rep object already "constructed" before
79 // static constructors have run. The reference-count encoding is
80 // chosen so that a 0 indicates one reference, so you never try to
81 // destroy the empty-string _Rep object.
83 // All but the last paragraph is considered pretty conventional
84 // for a C++ string implementation.
86 // 21.3 Template class basic_string
87 template<typename _CharT, typename _Traits, typename _Alloc>
92 typedef _Traits traits_type;
93 typedef typename _Traits::char_type value_type;
94 typedef _Alloc allocator_type;
95 typedef typename _Alloc::size_type size_type;
96 typedef typename _Alloc::difference_type difference_type;
97 typedef typename _Alloc::reference reference;
98 typedef typename _Alloc::const_reference const_reference;
99 typedef typename _Alloc::pointer pointer;
100 typedef typename _Alloc::const_pointer const_pointer;
101 typedef __normal_iterator<pointer, basic_string> iterator;
102 typedef __normal_iterator<const_pointer, basic_string> const_iterator;
103 typedef reverse_iterator<const_iterator> const_reverse_iterator;
104 typedef reverse_iterator<iterator> reverse_iterator;
107 // _Rep: string representation
109 // 1. String really contains _M_length + 1 characters; last is set
110 // to 0 only on call to c_str(). We avoid instantiating
111 // _CharT() where the interface does not require it.
112 // 2. _M_capacity >= _M_length
113 // Allocated memory is always _M_capacity + (1 * sizeof(_CharT)).
114 // 3. _M_references has three states:
115 // -1: leaked, one reference, no ref-copies allowed, non-const.
116 // 0: one reference, non-const.
117 // n>0: n + 1 references, operations require a lock, const.
118 // 4. All fields==0 is an empty string, given the extra storage
119 // beyond-the-end for a null terminator; thus, the shared
120 // empty string representation needs no constructor.
125 typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc;
127 // (Public) Data members:
129 // The maximum number of individual char_type elements of an
130 // individual string is determined by _S_max_size. This is the
131 // value that will be returned by max_size(). (Whereas npos
132 // is the maximum number of bytes the allocator can allocate.)
133 // If one was to divvy up the theoretical largest size string,
134 // with a terminating character and m _CharT elements, it'd
136 // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
138 // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
139 // In addition, this implementation quarters this ammount.
140 static const size_type _S_max_size;
141 static const _CharT _S_terminal;
144 size_type _M_capacity;
145 _Atomic_word _M_references;
149 { return _M_references < 0; }
153 { return _M_references > 0; }
157 { _M_references = -1; }
161 { _M_references = 0; }
165 { return reinterpret_cast<_CharT*> (this + 1); }
168 operator[](size_t __s) throw()
169 { return _M_refdata() [__s]; }
172 _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
173 { return (!_M_is_leaked() && __alloc1 == __alloc2) ?
174 _M_refcopy() : _M_clone(__alloc1); }
178 _S_create(size_t, const _Alloc&);
181 _M_dispose(const _Alloc& __a)
183 if (__exchange_and_add(&_M_references, -1) <= 0)
188 _M_destroy(const _Alloc&) throw();
193 __atomic_add(&_M_references, 1);
198 _M_clone(const _Alloc&, size_type __res = 0);
201 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
202 struct _Alloc_hider : _Alloc
204 _Alloc_hider(_CharT* __dat, const _Alloc& __a)
205 : _Alloc(__a), _M_p(__dat) { }
207 _CharT* _M_p; // The actual data.
211 // Data Members (public):
212 // NB: This is an unsigned type, and thus represents the maximum
213 // size that the allocator can hold.
214 static const size_type npos = static_cast<size_type>(-1);
217 // Data Members (private):
218 mutable _Alloc_hider _M_dataplus;
220 // The following storage is init'd to 0 by the linker, resulting
221 // (carefully) in an empty string with one reference.
222 static size_type _S_empty_rep_storage[(sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
226 { return _M_dataplus._M_p; }
230 { return (_M_dataplus._M_p = __p); }
234 { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
236 // For the internal use we have functions similar to `begin'/`end'
237 // but they do not call _M_leak.
239 _M_ibegin() const { return iterator(_M_data()); }
242 _M_iend() const { return iterator(_M_data() + this->size()); }
245 _M_leak() // for use in begin() & non-const op[]
247 if (!_M_rep()->_M_is_leaked())
252 _M_check(size_type __pos) const
254 if (__pos > this->size())
255 __throw_out_of_range("basic_string::_M_check");
256 return _M_ibegin() + __pos;
259 // NB: _M_fold doesn't check for a bad __pos1 value.
261 _M_fold(size_type __pos, size_type __off) const
263 bool __testoff = __off < this->size() - __pos;
264 size_type __newoff = __testoff ? __off : this->size() - __pos;
265 return (_M_ibegin() + __pos + __newoff);
268 // _S_copy_chars is a separate template to permit specialization
269 // to optimize for the common case of pointers as iterators.
270 template<class _Iterator>
272 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
274 for (; __k1 != __k2; ++__k1, ++__p)
275 traits_type::assign(*__p, *__k1); // These types are off.
279 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
280 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
283 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
284 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
287 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
288 { traits_type::copy(__p, __k1, __k2 - __k1); }
291 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
292 { traits_type::copy(__p, __k1, __k2 - __k1); }
295 _M_mutate(size_type __pos, size_type __len1, size_type __len2);
302 { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); }
305 // Construct/copy/destroy:
306 // NB: We overload ctors in some cases instead of using default
307 // arguments, per 17.4.4.4 para. 2 item 2.
313 basic_string(const _Alloc& __a);
315 // NB: per LWG issue 42, semantics different from IS:
316 basic_string(const basic_string& __str);
317 basic_string(const basic_string& __str, size_type __pos,
318 size_type __n = npos);
319 basic_string(const basic_string& __str, size_type __pos,
320 size_type __n, const _Alloc& __a);
322 basic_string(const _CharT* __s, size_type __n,
323 const _Alloc& __a = _Alloc());
324 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
325 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
327 template<class _InputIterator>
328 basic_string(_InputIterator __beg, _InputIterator __end,
329 const _Alloc& __a = _Alloc());
332 { _M_rep()->_M_dispose(this->get_allocator()); }
335 operator=(const basic_string& __str) { return this->assign(__str); }
338 operator=(const _CharT* __s) { return this->assign(__s); }
341 operator=(_CharT __c) { return this->assign(1, __c); }
348 return iterator(_M_data());
353 { return const_iterator(_M_data()); }
359 return iterator(_M_data() + this->size());
364 { return const_iterator(_M_data() + this->size()); }
368 { return reverse_iterator(this->end()); }
370 const_reverse_iterator
372 { return const_reverse_iterator(this->end()); }
376 { return reverse_iterator(this->begin()); }
378 const_reverse_iterator
380 { return const_reverse_iterator(this->begin()); }
385 size() const { return _M_rep()->_M_length; }
388 length() const { return _M_rep()->_M_length; }
391 max_size() const { return _Rep::_S_max_size; }
394 resize(size_type __n, _CharT __c);
397 resize(size_type __n) { this->resize(__n, _CharT()); }
400 capacity() const { return _M_rep()->_M_capacity; }
403 reserve(size_type __res_arg = 0);
406 clear() { _M_mutate(0, this->size(), 0); }
409 empty() const { return this->size() == 0; }
413 operator[] (size_type __pos) const
414 { return _M_data()[__pos]; }
417 operator[](size_type __pos)
420 return _M_data()[__pos];
424 at(size_type __n) const
426 if (__n >= this->size())
427 __throw_out_of_range("basic_string::at");
428 return _M_data()[__n];
435 __throw_out_of_range("basic_string::at");
437 return _M_data()[__n];
442 operator+=(const basic_string& __str) { return this->append(__str); }
445 operator+=(const _CharT* __s) { return this->append(__s); }
448 operator+=(_CharT __c) { return this->append(size_type(1), __c); }
451 append(const basic_string& __str);
454 append(const basic_string& __str, size_type __pos, size_type __n);
457 append(const _CharT* __s, size_type __n);
460 append(const _CharT* __s)
461 { return this->append(__s, traits_type::length(__s)); }
464 append(size_type __n, _CharT __c);
466 template<class _InputIterator>
468 append(_InputIterator __first, _InputIterator __last)
469 { return this->replace(_M_iend(), _M_iend(), __first, __last); }
472 push_back(_CharT __c)
473 { this->replace(_M_iend(), _M_iend(), 1, __c); }
476 assign(const basic_string& __str);
479 assign(const basic_string& __str, size_type __pos, size_type __n)
481 const size_type __strsize = __str.size();
482 if (__pos > __strsize)
483 __throw_out_of_range("basic_string::assign");
484 const bool __testn = __n < __strsize - __pos;
485 const size_type __newsize = __testn ? __n : __strsize - __pos;
486 return this->assign(__str._M_data() + __pos, __newsize);
490 assign(const _CharT* __s, size_type __n)
492 if (__n > this->max_size())
493 __throw_length_error("basic_string::assign");
494 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
495 || less<const _CharT*>()(_M_data() + this->size(), __s))
496 return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n);
500 const size_type __pos = __s - _M_data();
502 traits_type::copy(_M_data(), __s, __n);
504 traits_type::move(_M_data(), __s, __n);
505 _M_rep()->_M_length = __n;
506 _M_data()[__n] = _Rep::_S_terminal;
512 assign(const _CharT* __s)
513 { return this->assign(__s, traits_type::length(__s)); }
516 assign(size_type __n, _CharT __c)
517 { return this->replace(_M_ibegin(), _M_iend(), __n, __c); }
519 template<class _InputIterator>
521 assign(_InputIterator __first, _InputIterator __last)
522 { return this->replace(_M_ibegin(), _M_iend(), __first, __last); }
525 insert(iterator __p, size_type __n, _CharT __c)
526 { this->replace(__p, __p, __n, __c); }
528 template<class _InputIterator>
529 void insert(iterator __p, _InputIterator __beg, _InputIterator __end)
530 { this->replace(__p, __p, __beg, __end); }
533 insert(size_type __pos1, const basic_string& __str)
535 iterator __p = _M_check(__pos1);
536 this->replace(__p, __p, __str._M_ibegin(), __str._M_iend());
541 insert(size_type __pos1, const basic_string& __str,
542 size_type __pos2, size_type __n)
544 iterator __p = _M_check(__pos1);
545 this->replace(__p, __p, __str._M_check(__pos2),
546 __str._M_fold(__pos2, __n));
551 insert(size_type __pos, const _CharT* __s, size_type __n)
553 iterator __p = _M_check(__pos);
554 this->replace(__p, __p, __s, __s + __n);
559 insert(size_type __pos, const _CharT* __s)
560 { return this->insert(__pos, __s, traits_type::length(__s)); }
563 insert(size_type __pos, size_type __n, _CharT __c)
565 this->insert(_M_check(__pos), __n, __c);
570 insert(iterator __p, _CharT __c = _CharT())
572 size_type __pos = __p - _M_ibegin();
573 this->insert(_M_check(__pos), size_type(1), __c);
574 _M_rep()->_M_set_leaked();
575 return this->_M_ibegin() + __pos;
579 erase(size_type __pos = 0, size_type __n = npos)
581 return this->replace(_M_check(__pos), _M_fold(__pos, __n),
582 _M_data(), _M_data());
586 erase(iterator __position)
588 size_type __i = __position - _M_ibegin();
589 this->replace(__position, __position + 1, _M_data(), _M_data());
590 _M_rep()->_M_set_leaked();
591 return _M_ibegin() + __i;
595 erase(iterator __first, iterator __last)
597 size_type __i = __first - _M_ibegin();
598 this->replace(__first, __last, _M_data(), _M_data());
599 _M_rep()->_M_set_leaked();
600 return _M_ibegin() + __i;
604 replace(size_type __pos, size_type __n, const basic_string& __str)
606 return this->replace(_M_check(__pos), _M_fold(__pos, __n),
607 __str.begin(), __str.end());
611 replace(size_type __pos1, size_type __n1, const basic_string& __str,
612 size_type __pos2, size_type __n2);
615 replace(size_type __pos, size_type __n1, const _CharT* __s,
618 return this->replace(_M_check(__pos), _M_fold(__pos, __n1),
623 replace(size_type __pos, size_type __n1, const _CharT* __s)
625 return this->replace(_M_check(__pos), _M_fold(__pos, __n1),
626 __s, __s + traits_type::length(__s));
630 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
632 return this->replace(_M_check(__pos), _M_fold(__pos, __n1), __n2, __c);
636 replace(iterator __i1, iterator __i2, const basic_string& __str)
637 { return this->replace(__i1, __i2, __str.begin(), __str.end()); }
640 replace(iterator __i1, iterator __i2,
641 const _CharT* __s, size_type __n)
642 { return this->replace(__i1, __i2, __s, __s + __n); }
645 replace(iterator __i1, iterator __i2, const _CharT* __s)
646 { return this->replace(__i1, __i2, __s,
647 __s + traits_type::length(__s)); }
650 replace(iterator __i1, iterator __i2, size_type __n, _CharT __c);
652 template<class _InputIterator>
654 replace(iterator __i1, iterator __i2,
655 _InputIterator __k1, _InputIterator __k2)
656 { return _M_replace(__i1, __i2, __k1, __k2,
657 typename iterator_traits<_InputIterator>::iterator_category()); }
660 template<class _InputIterator>
662 _M_replace(iterator __i1, iterator __i2, _InputIterator __k1,
663 _InputIterator __k2, input_iterator_tag);
665 template<class _ForwardIterator>
667 _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1,
668 _ForwardIterator __k2);
670 // _S_construct_aux is used to implement the 21.3.1 para 15 which
671 // requires special behaviour if _InIter is an integral type
672 template<class _InIter>
674 _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a,
677 typedef typename iterator_traits<_InIter>::iterator_category _Tag;
678 return _S_construct(__beg, __end, __a, _Tag());
681 template<class _InIter>
683 _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a,
686 return _S_construct(static_cast<size_type>(__beg),
687 static_cast<value_type>(__end), __a);
690 template<class _InIter>
692 _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a)
694 typedef typename _Is_integer<_InIter>::_Integral _Integral;
695 return _S_construct_aux(__beg, __end, __a, _Integral());
698 // For Input Iterators, used in istreambuf_iterators, etc.
699 template<class _InIter>
701 _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
704 // For forward_iterators up to random_access_iterators, used for
705 // string::iterator, _CharT*, etc.
706 template<class _FwdIter>
708 _S_construct(_FwdIter __end, _FwdIter __beg, const _Alloc& __a,
709 forward_iterator_tag);
712 _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
717 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
720 swap(basic_string<_CharT, _Traits, _Alloc>& __s);
722 // String operations:
726 // MT: This assumes concurrent writes are OK.
727 size_type __n = this->size();
728 traits_type::assign(_M_data()[__n], _Rep::_S_terminal);
733 data() const { return _M_data(); }
736 get_allocator() const { return _M_dataplus; }
739 find(const _CharT* __s, size_type __pos, size_type __n) const;
742 find(const basic_string& __str, size_type __pos = 0) const
743 { return this->find(__str.data(), __pos, __str.size()); }
746 find(const _CharT* __s, size_type __pos = 0) const
747 { return this->find(__s, __pos, traits_type::length(__s)); }
750 find(_CharT __c, size_type __pos = 0) const;
753 rfind(const basic_string& __str, size_type __pos = npos) const
754 { return this->rfind(__str.data(), __pos, __str.size()); }
757 rfind(const _CharT* __s, size_type __pos, size_type __n) const;
760 rfind(const _CharT* __s, size_type __pos = npos) const
761 { return this->rfind(__s, __pos, traits_type::length(__s)); }
764 rfind(_CharT __c, size_type __pos = npos) const;
767 find_first_of(const basic_string& __str, size_type __pos = 0) const
768 { return this->find_first_of(__str.data(), __pos, __str.size()); }
771 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
774 find_first_of(const _CharT* __s, size_type __pos = 0) const
775 { return this->find_first_of(__s, __pos, traits_type::length(__s)); }
778 find_first_of(_CharT __c, size_type __pos = 0) const
779 { return this->find(__c, __pos); }
782 find_last_of(const basic_string& __str, size_type __pos = npos) const
783 { return this->find_last_of(__str.data(), __pos, __str.size()); }
786 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
789 find_last_of(const _CharT* __s, size_type __pos = npos) const
790 { return this->find_last_of(__s, __pos, traits_type::length(__s)); }
793 find_last_of(_CharT __c, size_type __pos = npos) const
794 { return this->rfind(__c, __pos); }
797 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
798 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
801 find_first_not_of(const _CharT* __s, size_type __pos,
802 size_type __n) const;
805 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
806 { return this->find_first_not_of(__s, __pos, traits_type::length(__s)); }
809 find_first_not_of(_CharT __c, size_type __pos = 0) const;
812 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
813 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
816 find_last_not_of(const _CharT* __s, size_type __pos,
817 size_type __n) const;
819 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
820 { return this->find_last_not_of(__s, __pos, traits_type::length(__s)); }
823 find_last_not_of(_CharT __c, size_type __pos = npos) const;
826 substr(size_type __pos = 0, size_type __n = npos) const
828 if (__pos > this->size())
829 __throw_out_of_range("basic_string::substr");
830 return basic_string(*this, __pos, __n);
834 compare(const basic_string& __str) const
836 size_type __size = this->size();
837 size_type __osize = __str.size();
838 size_type __len = min(__size, __osize);
840 int __r = traits_type::compare(_M_data(), __str.data(), __len);
842 __r = __size - __osize;
847 compare(size_type __pos, size_type __n, const basic_string& __str) const;
850 compare(size_type __pos1, size_type __n1, const basic_string& __str,
851 size_type __pos2, size_type __n2) const;
854 compare(const _CharT* __s) const;
856 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
857 // 5. String::compare specification questionable
859 compare(size_type __pos, size_type __n1, const _CharT* __s) const;
862 compare(size_type __pos, size_type __n1, const _CharT* __s,
863 size_type __n2) const;
868 template<typename _CharT, typename _Traits, typename _Alloc>
869 inline basic_string<_CharT, _Traits, _Alloc>::
871 : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { }
874 template<typename _CharT, typename _Traits, typename _Alloc>
875 basic_string<_CharT, _Traits, _Alloc>
876 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
877 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
879 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
884 template<typename _CharT, typename _Traits, typename _Alloc>
885 basic_string<_CharT,_Traits,_Alloc>
886 operator+(const _CharT* __lhs,
887 const basic_string<_CharT,_Traits,_Alloc>& __rhs);
889 template<typename _CharT, typename _Traits, typename _Alloc>
890 basic_string<_CharT,_Traits,_Alloc>
891 operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
893 template<typename _CharT, typename _Traits, typename _Alloc>
894 inline basic_string<_CharT, _Traits, _Alloc>
895 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
898 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
903 template<typename _CharT, typename _Traits, typename _Alloc>
904 inline basic_string<_CharT, _Traits, _Alloc>
905 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
907 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
908 typedef typename __string_type::size_type __size_type;
909 __string_type __str(__lhs);
910 __str.append(__size_type(1), __rhs);
915 template<typename _CharT, typename _Traits, typename _Alloc>
917 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
918 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
919 { return __lhs.compare(__rhs) == 0; }
921 template<typename _CharT, typename _Traits, typename _Alloc>
923 operator==(const _CharT* __lhs,
924 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
925 { return __rhs.compare(__lhs) == 0; }
927 template<typename _CharT, typename _Traits, typename _Alloc>
929 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
931 { return __lhs.compare(__rhs) == 0; }
934 template<typename _CharT, typename _Traits, typename _Alloc>
936 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
937 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
938 { return __rhs.compare(__lhs) != 0; }
940 template<typename _CharT, typename _Traits, typename _Alloc>
942 operator!=(const _CharT* __lhs,
943 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
944 { return __rhs.compare(__lhs) != 0; }
946 template<typename _CharT, typename _Traits, typename _Alloc>
948 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
950 { return __lhs.compare(__rhs) != 0; }
953 template<typename _CharT, typename _Traits, typename _Alloc>
955 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
956 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
957 { return __lhs.compare(__rhs) < 0; }
959 template<typename _CharT, typename _Traits, typename _Alloc>
961 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
963 { return __lhs.compare(__rhs) < 0; }
965 template<typename _CharT, typename _Traits, typename _Alloc>
967 operator<(const _CharT* __lhs,
968 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
969 { return __rhs.compare(__lhs) > 0; }
972 template<typename _CharT, typename _Traits, typename _Alloc>
974 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
975 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
976 { return __lhs.compare(__rhs) > 0; }
978 template<typename _CharT, typename _Traits, typename _Alloc>
980 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
982 { return __lhs.compare(__rhs) > 0; }
984 template<typename _CharT, typename _Traits, typename _Alloc>
986 operator>(const _CharT* __lhs,
987 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
988 { return __rhs.compare(__lhs) < 0; }
991 template<typename _CharT, typename _Traits, typename _Alloc>
993 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
994 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
995 { return __lhs.compare(__rhs) <= 0; }
997 template<typename _CharT, typename _Traits, typename _Alloc>
999 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
1000 const _CharT* __rhs)
1001 { return __lhs.compare(__rhs) <= 0; }
1003 template<typename _CharT, typename _Traits, typename _Alloc>
1005 operator<=(const _CharT* __lhs,
1006 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1007 { return __rhs.compare(__lhs) >= 0; }
1010 template<typename _CharT, typename _Traits, typename _Alloc>
1012 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
1013 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1014 { return __lhs.compare(__rhs) >= 0; }
1016 template<typename _CharT, typename _Traits, typename _Alloc>
1018 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
1019 const _CharT* __rhs)
1020 { return __lhs.compare(__rhs) >= 0; }
1022 template<typename _CharT, typename _Traits, typename _Alloc>
1024 operator>=(const _CharT* __lhs,
1025 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1026 { return __rhs.compare(__lhs) <= 0; }
1029 template<typename _CharT, typename _Traits, typename _Alloc>
1031 swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
1032 basic_string<_CharT, _Traits, _Alloc>& __rhs)
1033 { __lhs.swap(__rhs); }
1035 template<typename _CharT, typename _Traits, typename _Alloc>
1036 basic_istream<_CharT, _Traits>&
1037 operator>>(basic_istream<_CharT, _Traits>& __is,
1038 basic_string<_CharT, _Traits, _Alloc>& __str);
1040 template<typename _CharT, typename _Traits, typename _Alloc>
1041 basic_ostream<_CharT, _Traits>&
1042 operator<<(basic_ostream<_CharT, _Traits>& __os,
1043 const basic_string<_CharT, _Traits, _Alloc>& __str);
1045 template<typename _CharT, typename _Traits, typename _Alloc>
1046 basic_istream<_CharT,_Traits>&
1047 getline(basic_istream<_CharT, _Traits>& __is,
1048 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
1050 template<typename _CharT, typename _Traits, typename _Alloc>
1051 inline basic_istream<_CharT,_Traits>&
1052 getline(basic_istream<_CharT, _Traits>& __is,
1053 basic_string<_CharT, _Traits, _Alloc>& __str);
1056 #endif /* _CPP_BITS_STRING_H */