1 // Main templates for the -*- C++ -*- string classes. 2 // Copyright (C) 1994, 1995, 1999 Free Software Foundation 3 4 // This file is part of the GNU ANSI C++ Library. This library is free 5 // software; you can redistribute it and/or modify it under the 6 // terms of the GNU General Public License as published by the 7 // Free Software Foundation; either version 2, or (at your option) 8 // any later version. 9 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with this library; see the file COPYING. If not, write to the Free 17 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 // As a special exception, if you link this library with files 20 // compiled with a GNU compiler to produce an executable, this does not cause 21 // the resulting executable to be covered by the GNU General Public License. 22 // This exception does not however invalidate any other reasons why 23 // the executable file might be covered by the GNU General Public License. 24 25 // Written by Jason Merrill based upon the specification by Takanori Adachi 26 // in ANSI X3J16/94-0013R2. 27 28 #ifndef __BASTRING__ 29 #define __BASTRING__ 30 31 #ifdef __GNUG__ 32 #pragma interface 33 #endif 34 35 #include <cstddef> 36 #include <std/straits.h> 37 38 // NOTE : This does NOT conform to the draft standard and is likely to change 39 #include <alloc.h> 40 41 extern "C++" { 42 class istream; class ostream; 43 44 #include <iterator> 45 46 #ifdef __STL_USE_EXCEPTIONS 47 48 extern void __out_of_range (const char *); 49 extern void __length_error (const char *); 50 51 #define OUTOFRANGE(cond) \ 52 do { if (cond) __out_of_range (#cond); } while (0) 53 #define LENGTHERROR(cond) \ 54 do { if (cond) __length_error (#cond); } while (0) 55 56 #else 57 58 #include <cassert> 59 #define OUTOFRANGE(cond) assert (!(cond)) 60 #define LENGTHERROR(cond) assert (!(cond)) 61 62 #endif 63 64 #ifdef __BEOS__ 65 // Needed for atomic_add(): 66 typedef long int32; 67 typedef volatile long vint32; 68 extern "C" int32 atomic_add(vint32* value, int32 addvalue); 69 #endif /* __BEOS__ */ 70 71 template <class charT, class traits = string_char_traits<charT>, 72 class Allocator = alloc > 73 class basic_string 74 { 75 private: 76 struct Rep { 77 size_t len, res, ref; 78 bool selfish; 79 80 charT* data () { return reinterpret_cast<charT *>(this + 1); } 81 charT& operator[] (size_t s) { return data () [s]; } 82 #ifdef __BEOS__ 83 charT* grab () { if (selfish) return clone (); atomic_add((vint32*) &ref, 1); return data (); } 84 void release() { if (atomic_add((int32*) &ref, -1) == 1) delete this; } 85 #else 86 charT* grab () { if (selfish) return clone (); ++ref; return data (); } 87 #if defined __i486__ || defined __i586__ || defined __i686__ 88 void release () 89 { 90 size_t __val; 91 // This opcode exists as a .byte instead of as a mnemonic for the 92 // benefit of SCO OpenServer 5. The system assembler (which is 93 // essentially required on this target) can't assemble xaddl in 94 //COFF mode. 95 asm (".byte 0xf0, 0x0f, 0xc1, 0x02" // lock; xaddl %eax, (%edx) 96 : "=a" (__val) 97 : "0" (-1), "m" (ref), "d" (&ref) 98 : "memory"); 99 100 if (__val == 1) 101 delete this; 102 } 103 #elif defined __sparcv9__ 104 void release () 105 { 106 size_t __newval, __oldval = ref; 107 do 108 { 109 __newval = __oldval - 1; 110 __asm__ ("cas [%4], %2, %0" 111 : "=r" (__oldval), "=m" (ref) 112 : "r" (__oldval), "m" (ref), "r"(&(ref)), "0" (__newval)); 113 } 114 while (__newval != __oldval); 115 116 if (__oldval == 0) 117 delete this; 118 } 119 #else 120 void release () { if (--ref == 0) delete this; } 121 #endif 122 #endif /* __BEOS__ */ 123 inline static void * operator new (size_t, size_t); 124 inline static void operator delete (void *); 125 inline static Rep* create (size_t); 126 charT* clone (); 127 128 inline void copy (size_t, const charT *, size_t); 129 inline void move (size_t, const charT *, size_t); 130 inline void set (size_t, const charT, size_t); 131 132 inline static bool excess_slop (size_t, size_t); 133 inline static size_t frob_size (size_t); 134 135 private: 136 Rep &operator= (const Rep &); 137 }; 138 139 public: 140 // types: 141 typedef traits traits_type; 142 typedef typename traits::char_type value_type; 143 typedef Allocator allocator_type; 144 145 typedef size_t size_type; 146 typedef ptrdiff_t difference_type; 147 typedef charT& reference; 148 typedef const charT& const_reference; 149 typedef charT* pointer; 150 typedef const charT* const_pointer; 151 typedef pointer iterator; 152 typedef const_pointer const_iterator; 153 typedef ::reverse_iterator<iterator> reverse_iterator; 154 typedef ::reverse_iterator<const_iterator> const_reverse_iterator; 155 static const size_type npos = static_cast<size_type>(-1); 156 157 private: 158 Rep *rep () const { return reinterpret_cast<Rep *>(dat) - 1; } 159 void repup (Rep *p) { rep ()->release (); dat = p->data (); } 160 161 public: 162 const charT* data () const 163 { return rep ()->data(); } 164 size_type length () const 165 { return rep ()->len; } 166 size_type size () const 167 { return rep ()->len; } 168 size_type capacity () const 169 { return rep ()->res; } 170 size_type max_size () const 171 { return (npos - 1)/sizeof (charT); } // XXX 172 bool empty () const 173 { return size () == 0; } 174 175 // _lib.string.cons_ construct/copy/destroy: 176 basic_string& operator= (const basic_string& str) 177 { 178 if (&str != this) { rep ()->release (); dat = str.rep ()->grab (); } 179 return *this; 180 } 181 182 explicit basic_string (): dat (nilRep.grab ()) { } 183 basic_string (const basic_string& _str): dat (_str.rep ()->grab ()) { } 184 basic_string (const basic_string& _str, size_type pos, size_type n = npos) 185 : dat (nilRep.grab ()) { assign (_str, pos, n); } 186 basic_string (const charT* s, size_type n) 187 : dat (nilRep.grab ()) { assign (s, n); } 188 basic_string (const charT* s) 189 : dat (nilRep.grab ()) { assign (s); } 190 basic_string (size_type n, charT c) 191 : dat (nilRep.grab ()) { assign (n, c); } 192 #ifdef __STL_MEMBER_TEMPLATES 193 template<class InputIterator> 194 basic_string(InputIterator __begin, InputIterator __end) 195 #else 196 basic_string(const_iterator __begin, const_iterator __end) 197 #endif 198 : dat (nilRep.grab ()) { assign (__begin, __end); } 199 200 ~basic_string () 201 { rep ()->release (); } 202 203 void swap (basic_string &s) { charT *d = dat; dat = s.dat; s.dat = d; } 204 205 basic_string& append (const basic_string& _str, size_type pos = 0, 206 size_type n = npos) 207 { return replace (length (), 0, _str, pos, n); } 208 basic_string& append (const charT* s, size_type n) 209 { return replace (length (), 0, s, n); } 210 basic_string& append (const charT* s) 211 { return append (s, traits::length (s)); } 212 basic_string& append (size_type n, charT c) 213 { return replace (length (), 0, n, c); } 214 #ifdef __STL_MEMBER_TEMPLATES 215 template<class InputIterator> 216 basic_string& append(InputIterator first, InputIterator last) 217 #else 218 basic_string& append(const_iterator first, const_iterator last) 219 #endif 220 { return replace (iend (), iend (), first, last); } 221 222 void push_back(charT __c) 223 { append(1, __c); } 224 225 basic_string& assign (const basic_string& str, size_type pos = 0, 226 size_type n = npos) 227 { return replace (0, npos, str, pos, n); } 228 basic_string& assign (const charT* s, size_type n) 229 { return replace (0, npos, s, n); } 230 basic_string& assign (const charT* s) 231 { return assign (s, traits::length (s)); } 232 basic_string& assign (size_type n, charT c) 233 { return replace (0, npos, n, c); } 234 #ifdef __STL_MEMBER_TEMPLATES 235 template<class InputIterator> 236 basic_string& assign(InputIterator first, InputIterator last) 237 #else 238 basic_string& assign(const_iterator first, const_iterator last) 239 #endif 240 { return replace (ibegin (), iend (), first, last); } 241 242 basic_string& operator= (const charT* s) 243 { return assign (s); } 244 basic_string& operator= (charT c) 245 { return assign (1, c); } 246 247 basic_string& operator+= (const basic_string& rhs) 248 { return append (rhs); } 249 basic_string& operator+= (const charT* s) 250 { return append (s); } 251 basic_string& operator+= (charT c) 252 { return append (1, c); } 253 254 basic_string& insert (size_type pos1, const basic_string& str, 255 size_type pos2 = 0, size_type n = npos) 256 { return replace (pos1, 0, str, pos2, n); } 257 basic_string& insert (size_type pos, const charT* s, size_type n) 258 { return replace (pos, 0, s, n); } 259 basic_string& insert (size_type pos, const charT* s) 260 { return insert (pos, s, traits::length (s)); } 261 basic_string& insert (size_type pos, size_type n, charT c) 262 { return replace (pos, 0, n, c); } 263 iterator insert(iterator p, charT c) 264 { size_type __o = p - ibegin (); 265 insert (p - ibegin (), 1, c); selfish (); 266 return ibegin () + __o; } 267 iterator insert(iterator p, size_type n, charT c) 268 { size_type __o = p - ibegin (); 269 insert (p - ibegin (), n, c); selfish (); 270 return ibegin () + __o; } 271 #ifdef __STL_MEMBER_TEMPLATES 272 template<class InputIterator> 273 void insert(iterator p, InputIterator first, InputIterator last) 274 #else 275 void insert(iterator p, const_iterator first, const_iterator last) 276 #endif 277 { replace (p, p, first, last); } 278 279 basic_string& erase (size_type pos = 0, size_type n = npos) 280 { return replace (pos, n, (size_type)0, (charT)0); } 281 iterator erase(iterator p) 282 { size_type __o = p - begin(); 283 replace (__o, 1, (size_type)0, (charT)0); selfish (); 284 return ibegin() + __o; } 285 iterator erase(iterator f, iterator l) 286 { size_type __o = f - ibegin(); 287 replace (__o, l-f, (size_type)0, (charT)0);selfish (); 288 return ibegin() + __o; } 289 290 basic_string& replace (size_type pos1, size_type n1, const basic_string& str, 291 size_type pos2 = 0, size_type n2 = npos); 292 basic_string& replace (size_type pos, size_type n1, const charT* s, 293 size_type n2); 294 basic_string& replace (size_type pos, size_type n1, const charT* s) 295 { return replace (pos, n1, s, traits::length (s)); } 296 basic_string& replace (size_type pos, size_type n1, size_type n2, charT c); 297 basic_string& replace (size_type pos, size_type n, charT c) 298 { return replace (pos, n, 1, c); } 299 basic_string& replace (iterator i1, iterator i2, const basic_string& str) 300 { return replace (i1 - ibegin (), i2 - i1, str); } 301 basic_string& replace (iterator i1, iterator i2, const charT* s, size_type n) 302 { return replace (i1 - ibegin (), i2 - i1, s, n); } 303 basic_string& replace (iterator i1, iterator i2, const charT* s) 304 { return replace (i1 - ibegin (), i2 - i1, s); } 305 basic_string& replace (iterator i1, iterator i2, size_type n, charT c) 306 { return replace (i1 - ibegin (), i2 - i1, n, c); } 307 #ifdef __STL_MEMBER_TEMPLATES 308 template<class InputIterator> 309 basic_string& replace(iterator i1, iterator i2, 310 InputIterator j1, InputIterator j2); 311 #else 312 basic_string& replace(iterator i1, iterator i2, 313 const_iterator j1, const_iterator j2); 314 #endif 315 316 private: 317 static charT eos () { return traits::eos (); } 318 void unique () { if (rep ()->ref > 1) alloc (length (), true); } 319 void selfish () { unique (); rep ()->selfish = true; } 320 321 public: 322 charT operator[] (size_type pos) const 323 { 324 if (pos == length ()) 325 return eos (); 326 return data ()[pos]; 327 } 328 329 reference operator[] (size_type pos) 330 { selfish (); return (*rep ())[pos]; } 331 332 reference at (size_type pos) 333 { 334 OUTOFRANGE (pos >= length ()); 335 return (*this)[pos]; 336 } 337 const_reference at (size_type pos) const 338 { 339 OUTOFRANGE (pos >= length ()); 340 return data ()[pos]; 341 } 342 343 private: 344 void terminate () const 345 { traits::assign ((*rep ())[length ()], eos ()); } 346 347 public: 348 const charT* c_str () const 349 { if (length () == 0) return ""; terminate (); return data (); } 350 void resize (size_type n, charT c); 351 void resize (size_type n) 352 { resize (n, eos ()); } 353 void reserve (size_type) { } 354 355 size_type copy (charT* s, size_type n, size_type pos = 0) const; 356 357 size_type find (const basic_string& str, size_type pos = 0) const 358 { return find (str.data(), pos, str.length()); } 359 size_type find (const charT* s, size_type pos, size_type n) const; 360 size_type find (const charT* _s, size_type pos = 0) const 361 { return find (_s, pos, traits::length (_s)); } 362 size_type find (charT c, size_type pos = 0) const; 363 364 size_type rfind (const basic_string& str, size_type pos = npos) const 365 { return rfind (str.data(), pos, str.length()); } 366 size_type rfind (const charT* s, size_type pos, size_type n) const; 367 size_type rfind (const charT* s, size_type pos = npos) const 368 { return rfind (s, pos, traits::length (s)); } 369 size_type rfind (charT c, size_type pos = npos) const; 370 371 size_type find_first_of (const basic_string& str, size_type pos = 0) const 372 { return find_first_of (str.data(), pos, str.length()); } 373 size_type find_first_of (const charT* s, size_type pos, size_type n) const; 374 size_type find_first_of (const charT* s, size_type pos = 0) const 375 { return find_first_of (s, pos, traits::length (s)); } 376 size_type find_first_of (charT c, size_type pos = 0) const 377 { return find (c, pos); } 378 379 size_type find_last_of (const basic_string& str, size_type pos = npos) const 380 { return find_last_of (str.data(), pos, str.length()); } 381 size_type find_last_of (const charT* s, size_type pos, size_type n) const; 382 size_type find_last_of (const charT* s, size_type pos = npos) const 383 { return find_last_of (s, pos, traits::length (s)); } 384 size_type find_last_of (charT c, size_type pos = npos) const 385 { return rfind (c, pos); } 386 387 size_type find_first_not_of (const basic_string& str, size_type pos = 0) const 388 { return find_first_not_of (str.data(), pos, str.length()); } 389 size_type find_first_not_of (const charT* s, size_type pos, size_type n) const; 390 size_type find_first_not_of (const charT* s, size_type pos = 0) const 391 { return find_first_not_of (s, pos, traits::length (s)); } 392 size_type find_first_not_of (charT c, size_type pos = 0) const; 393 394 size_type find_last_not_of (const basic_string& str, size_type pos = npos) const 395 { return find_last_not_of (str.data(), pos, str.length()); } 396 size_type find_last_not_of (const charT* s, size_type pos, size_type n) const; 397 size_type find_last_not_of (const charT* s, size_type pos = npos) const 398 { return find_last_not_of (s, pos, traits::length (s)); } 399 size_type find_last_not_of (charT c, size_type pos = npos) const; 400 401 basic_string substr (size_type pos = 0, size_type n = npos) const 402 { return basic_string (*this, pos, n); } 403 404 int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const; 405 // There is no 'strncmp' equivalent for charT pointers. 406 int compare (const charT* s, size_type pos, size_type n) const; 407 int compare (const charT* s, size_type pos = 0) const 408 { return compare (s, pos, traits::length (s)); } 409 410 iterator begin () { selfish (); return &(*this)[0]; } 411 iterator end () { selfish (); return &(*this)[length ()]; } 412 413 private: 414 iterator ibegin () const { return &(*rep ())[0]; } 415 iterator iend () const { return &(*rep ())[length ()]; } 416 417 public: 418 const_iterator begin () const { return ibegin (); } 419 const_iterator end () const { return iend (); } 420 421 reverse_iterator rbegin() { return reverse_iterator (end ()); } 422 const_reverse_iterator rbegin() const 423 { return const_reverse_iterator (end ()); } 424 reverse_iterator rend() { return reverse_iterator (begin ()); } 425 const_reverse_iterator rend() const 426 { return const_reverse_iterator (begin ()); } 427 428 private: 429 void alloc (size_type size, bool save); 430 static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len); 431 inline bool check_realloc (size_type s) const; 432 433 static Rep nilRep; 434 charT *dat; 435 }; 436 437 #ifdef __STL_MEMBER_TEMPLATES 438 template <class charT, class traits, class Allocator> template <class InputIterator> 439 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>:: 440 replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2) 441 #else 442 template <class charT, class traits, class Allocator> 443 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>:: 444 replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2) 445 #endif 446 { 447 const size_type len = length (); 448 size_type pos = i1 - ibegin (); 449 size_type n1 = i2 - i1; 450 size_type n2 = j2 - j1; 451 452 OUTOFRANGE (pos > len); 453 if (n1 > len - pos) 454 n1 = len - pos; 455 LENGTHERROR (len - n1 > max_size () - n2); 456 size_t newlen = len - n1 + n2; 457 458 if (check_realloc (newlen)) 459 { 460 Rep *p = Rep::create (newlen); 461 p->copy (0, data (), pos); 462 p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); 463 for (; j1 != j2; ++j1, ++pos) 464 traits::assign ((*p)[pos], *j1); 465 repup (p); 466 } 467 else 468 { 469 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1)); 470 for (; j1 != j2; ++j1, ++pos) 471 traits::assign ((*rep ())[pos], *j1); 472 } 473 rep ()->len = newlen; 474 475 return *this; 476 } 477 478 template <class charT, class traits, class Allocator> 479 inline basic_string <charT, traits, Allocator> 480 operator+ (const basic_string <charT, traits, Allocator>& lhs, 481 const basic_string <charT, traits, Allocator>& rhs) 482 { 483 basic_string <charT, traits, Allocator> _str (lhs); 484 _str.append (rhs); 485 return _str; 486 } 487 488 template <class charT, class traits, class Allocator> 489 inline basic_string <charT, traits, Allocator> 490 operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 491 { 492 basic_string <charT, traits, Allocator> _str (lhs); 493 _str.append (rhs); 494 return _str; 495 } 496 497 template <class charT, class traits, class Allocator> 498 inline basic_string <charT, traits, Allocator> 499 operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs) 500 { 501 basic_string <charT, traits, Allocator> _str (1, lhs); 502 _str.append (rhs); 503 return _str; 504 } 505 506 template <class charT, class traits, class Allocator> 507 inline basic_string <charT, traits, Allocator> 508 operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 509 { 510 basic_string <charT, traits, Allocator> _str (lhs); 511 _str.append (rhs); 512 return _str; 513 } 514 515 template <class charT, class traits, class Allocator> 516 inline basic_string <charT, traits, Allocator> 517 operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs) 518 { 519 basic_string <charT, traits, Allocator> str (lhs); 520 str.append (1, rhs); 521 return str; 522 } 523 524 template <class charT, class traits, class Allocator> 525 inline bool 526 operator== (const basic_string <charT, traits, Allocator>& lhs, 527 const basic_string <charT, traits, Allocator>& rhs) 528 { 529 return (lhs.compare (rhs) == 0); 530 } 531 532 template <class charT, class traits, class Allocator> 533 inline bool 534 operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 535 { 536 return (rhs.compare (lhs) == 0); 537 } 538 539 template <class charT, class traits, class Allocator> 540 inline bool 541 operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 542 { 543 return (lhs.compare (rhs) == 0); 544 } 545 546 template <class charT, class traits, class Allocator> 547 inline bool 548 operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 549 { 550 return (rhs.compare (lhs) != 0); 551 } 552 553 template <class charT, class traits, class Allocator> 554 inline bool 555 operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 556 { 557 return (lhs.compare (rhs) != 0); 558 } 559 560 template <class charT, class traits, class Allocator> 561 inline bool 562 operator< (const basic_string <charT, traits, Allocator>& lhs, 563 const basic_string <charT, traits, Allocator>& rhs) 564 { 565 return (lhs.compare (rhs) < 0); 566 } 567 568 template <class charT, class traits, class Allocator> 569 inline bool 570 operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 571 { 572 return (rhs.compare (lhs) > 0); 573 } 574 575 template <class charT, class traits, class Allocator> 576 inline bool 577 operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 578 { 579 return (lhs.compare (rhs) < 0); 580 } 581 582 template <class charT, class traits, class Allocator> 583 inline bool 584 operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 585 { 586 return (rhs.compare (lhs) < 0); 587 } 588 589 template <class charT, class traits, class Allocator> 590 inline bool 591 operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 592 { 593 return (lhs.compare (rhs) > 0); 594 } 595 596 template <class charT, class traits, class Allocator> 597 inline bool 598 operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 599 { 600 return (rhs.compare (lhs) >= 0); 601 } 602 603 template <class charT, class traits, class Allocator> 604 inline bool 605 operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 606 { 607 return (lhs.compare (rhs) <= 0); 608 } 609 610 template <class charT, class traits, class Allocator> 611 inline bool 612 operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 613 { 614 return (rhs.compare (lhs) <= 0); 615 } 616 617 template <class charT, class traits, class Allocator> 618 inline bool 619 operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 620 { 621 return (lhs.compare (rhs) >= 0); 622 } 623 624 template <class charT, class traits, class Allocator> 625 inline bool 626 operator!= (const basic_string <charT, traits, Allocator>& lhs, 627 const basic_string <charT, traits, Allocator>& rhs) 628 { 629 return (lhs.compare (rhs) != 0); 630 } 631 632 template <class charT, class traits, class Allocator> 633 inline bool 634 operator> (const basic_string <charT, traits, Allocator>& lhs, 635 const basic_string <charT, traits, Allocator>& rhs) 636 { 637 return (lhs.compare (rhs) > 0); 638 } 639 640 template <class charT, class traits, class Allocator> 641 inline bool 642 operator<= (const basic_string <charT, traits, Allocator>& lhs, 643 const basic_string <charT, traits, Allocator>& rhs) 644 { 645 return (lhs.compare (rhs) <= 0); 646 } 647 648 template <class charT, class traits, class Allocator> 649 inline bool 650 operator>= (const basic_string <charT, traits, Allocator>& lhs, 651 const basic_string <charT, traits, Allocator>& rhs) 652 { 653 return (lhs.compare (rhs) >= 0); 654 } 655 656 class istream; class ostream; 657 template <class charT, class traits, class Allocator> istream& 658 operator>> (istream&, basic_string <charT, traits, Allocator>&); 659 template <class charT, class traits, class Allocator> ostream& 660 operator<< (ostream&, const basic_string <charT, traits, Allocator>&); 661 template <class charT, class traits, class Allocator> istream& 662 getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n'); 663 664 } // extern "C++" 665 666 #include <std/bastring.cc> 667 668 #endif 669