Documentation fix. Ticket 6499
[boost:cmake.git] / boost / container / string.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 // Copyright (c) 1996,1997
11 // Silicon Graphics Computer Systems, Inc.
12 //
13 // Permission to use, copy, modify, distribute and sell this software
14 // and its documentation for any purpose is hereby granted without fee,
15 // provided that the above copyright notice appear in all copies and
16 // that both that copyright notice and this permission notice appear
17 // in supporting documentation.  Silicon Graphics makes no
18 // representations about the suitability of this software for any
19 // purpose.  It is provided "as is" without express or implied warranty.
20 //
21 //
22 // Copyright (c) 1994
23 // Hewlett-Packard Company
24 //
25 // Permission to use, copy, modify, distribute and sell this software
26 // and its documentation for any purpose is hereby granted without fee,
27 // provided that the above copyright notice appear in all copies and
28 // that both that copyright notice and this permission notice appear
29 // in supporting documentation.  Hewlett-Packard Company makes no
30 // representations about the suitability of this software for any
31 // purpose.  It is provided "as is" without express or implied warranty.
32
33 #ifndef BOOST_CONTAINER_STRING_HPP
34 #define BOOST_CONTAINER_STRING_HPP
35
36 #include <boost/container/detail/config_begin.hpp>
37 #include <boost/container/detail/workaround.hpp>
38
39 #include <boost/container/detail/workaround.hpp>
40 #include <boost/container/container_fwd.hpp>
41 #include <boost/container/detail/utilities.hpp>
42 #include <boost/container/detail/iterators.hpp>
43 #include <boost/container/detail/algorithms.hpp>
44 #include <boost/container/detail/version_type.hpp>
45 #include <boost/container/detail/allocation_type.hpp>
46 #include <boost/container/allocator/allocator_traits.hpp>
47 #include <boost/container/detail/mpl.hpp>
48 #include <boost/move/move.hpp>
49 #include <boost/static_assert.hpp>
50
51 #include <functional>
52 #include <string>
53 #include <stdexcept>      
54 #include <utility>  
55 #include <iterator>
56 #include <memory>
57 #include <algorithm>
58 #include <iosfwd>
59 #include <istream>
60 #include <ostream>
61 #include <ios>
62 #include <locale>
63 #include <cstddef>
64 #include <climits>
65 #include <boost/container/detail/type_traits.hpp>
66 #include <boost/detail/no_exceptions_support.hpp>
67 #include <boost/type_traits/has_trivial_destructor.hpp>
68 #include <boost/aligned_storage.hpp>
69
70 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
71 namespace boost {
72 namespace container {
73 #else
74 namespace boost {
75 namespace container {
76 #endif
77
78 /// @cond
79 namespace container_detail {
80 // ------------------------------------------------------------
81 // Class basic_string_base.  
82
83 // basic_string_base is a helper class that makes it it easier to write
84 // an exception-safe version of basic_string.  The constructor allocates,
85 // but does not initialize, a block of memory.  The destructor
86 // deallocates, but does not destroy elements within, a block of
87 // memory.  The destructor assumes that the memory either is the internal buffer, 
88 // or else points to a block of memory that was allocated using _String_base's 
89 // allocator and whose size is this->m_storage.
90 template <class A>
91 class basic_string_base
92 {
93    BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_string_base)
94
95    typedef allocator_traits<A> allocator_traits_type;
96  public:
97    typedef A allocator_type;
98    //! The stored allocator type
99    typedef allocator_type                          stored_allocator_type;
100    typedef typename allocator_traits_type::pointer     pointer;
101    typedef typename allocator_traits_type::value_type  value_type;
102    typedef typename allocator_traits_type::size_type   size_type;
103
104    basic_string_base()
105       : members_()
106    {  init(); }
107
108    basic_string_base(const allocator_type& a)
109       : members_(a)
110    {  init(); }
111
112    basic_string_base(const allocator_type& a, size_type n)
113       : members_(a)
114    {  
115       this->init(); 
116       this->allocate_initial_block(n);
117    }
118
119    basic_string_base(BOOST_RV_REF(basic_string_base) b)
120       :  members_(boost::move(b.alloc()))
121    {  
122       this->init();
123       this->swap_data(b); 
124    }
125
126    ~basic_string_base() 
127    {  
128       if(!this->is_short()){
129          this->deallocate_block(); 
130          allocator_traits_type::destroy
131             ( this->alloc()
132             , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
133             );
134       }
135    }
136
137    private:
138
139    //This is the structure controlling a long string 
140    struct long_t
141    {
142       size_type      is_short  : 1;
143       size_type      length    : (sizeof(size_type)*CHAR_BIT - 1);
144       size_type      storage;
145       pointer        start;
146
147       long_t()
148       {}
149
150       long_t(const long_t &other)
151       {
152          this->is_short = other.is_short;
153          length   = other.length;
154          storage  = other.storage;
155          start    = other.start;
156       }
157
158       long_t &operator =(const long_t &other)
159       {
160          this->is_short = other.is_short;
161          length   = other.length;
162          storage  = other.storage;
163          start    = other.start;
164          return *this;
165       }
166    };
167
168    //This type is the first part of the structure controlling a short string
169    //The "data" member stores
170    struct short_header
171    {
172       unsigned char  is_short  : 1;
173       unsigned char  length    : (CHAR_BIT - 1);
174    };
175
176    //This type has the same alignment and size as long_t but it's POD
177    //so, unlike long_t, it can be placed in a union
178    
179    typedef typename boost::aligned_storage< sizeof(long_t), 
180        container_detail::alignment_of<long_t>::value>::type   long_raw_t;
181
182    protected:
183    static const size_type  MinInternalBufferChars = 8;
184    static const size_type  AlignmentOfValueType =
185       alignment_of<value_type>::value;
186    static const size_type  ShortDataOffset =
187       container_detail::ct_rounded_size<sizeof(short_header),  AlignmentOfValueType>::value;
188    static const size_type  ZeroCostInternalBufferChars =
189       (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
190    static const size_type  UnalignedFinalInternalBufferChars = 
191       (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
192                 ZeroCostInternalBufferChars : MinInternalBufferChars;
193
194    struct short_t
195    {
196       short_header   h; 
197       value_type     data[UnalignedFinalInternalBufferChars];
198    };
199
200    union repr_t
201    {
202       long_raw_t  r;
203       short_t     s;
204
205       short_t &short_repr() const
206       {  return *const_cast<short_t *>(&s);  }
207
208       long_t &long_repr() const
209       {  return *const_cast<long_t*>(reinterpret_cast<const long_t*>(&r));  }
210    };
211
212    struct members_holder
213       :  public A
214    {
215       members_holder()
216          : A()
217       {}
218
219       template<class AllocatorConvertible>
220       explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
221          :  A(boost::forward<AllocatorConvertible>(a))
222       {}
223
224       repr_t m_repr;
225    } members_;
226
227    const A &alloc() const
228    {  return members_;  }
229
230    A &alloc()
231    {  return members_;  }
232
233    static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
234
235    private:
236
237    static const size_type MinAllocation = InternalBufferChars*2;
238
239    protected:
240    bool is_short() const
241    {  return static_cast<bool>(this->members_.m_repr.s.h.is_short != 0);  }
242
243    void is_short(bool yes)
244    {  
245       if(yes && !this->is_short()){
246          allocator_traits_type::destroy
247             ( this->alloc()
248             , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
249             );
250       }
251       else{
252          allocator_traits_type::construct
253             ( this->alloc()
254             , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
255             );
256       }
257       this->members_.m_repr.s.h.is_short = yes;
258    }
259
260    private:
261    void init()
262    {
263       this->members_.m_repr.s.h.is_short = 1;
264       this->members_.m_repr.s.h.length   = 0;
265    }
266
267    protected:
268
269    typedef container_detail::integral_constant<unsigned, 1>      allocator_v1;
270    typedef container_detail::integral_constant<unsigned, 2>      allocator_v2;
271    typedef container_detail::integral_constant<unsigned,
272       boost::container::container_detail::version<A>::value> alloc_version;
273
274    std::pair<pointer, bool>
275       allocation_command(allocation_type command,
276                          size_type limit_size, 
277                          size_type preferred_size,
278                          size_type &received_size, pointer reuse = 0)
279    {
280       if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
281          reuse = pointer(0);
282          command &= ~(expand_fwd | expand_bwd);
283       }
284       return this->allocation_command
285          (command, limit_size, preferred_size, received_size, reuse, alloc_version());
286    }
287
288    std::pair<pointer, bool>
289       allocation_command(allocation_type command,
290                          size_type limit_size, 
291                          size_type preferred_size,
292                          size_type &received_size,
293                          const pointer &reuse,
294                          allocator_v1)
295    {
296       (void)limit_size;
297       (void)reuse;
298       if(!(command & allocate_new))
299          return std::pair<pointer, bool>(pointer(0), false);
300       received_size = preferred_size;
301       return std::make_pair(this->alloc().allocate(received_size), false);
302    }
303
304    std::pair<pointer, bool>
305       allocation_command(allocation_type command,
306                          size_type limit_size, 
307                          size_type preferred_size,
308                          size_type &received_size,
309                          pointer reuse,
310                          allocator_v2)
311    {
312       return this->alloc().allocation_command(command, limit_size, preferred_size, 
313                                               received_size, reuse);
314    }
315
316    size_type next_capacity(size_type additional_objects) const
317    {  return get_next_capacity(allocator_traits_type::max_size(this->alloc()), this->priv_storage(), additional_objects);  }
318
319    void deallocate(pointer p, size_type n) 
320    {  
321       if (p && (n > InternalBufferChars))
322          this->alloc().deallocate(p, n);
323    }
324
325    void construct(pointer p, const value_type &value = value_type())
326    {
327       allocator_traits_type::construct
328          ( this->alloc()
329          , container_detail::to_raw_pointer(p)
330          , value
331          );
332    }
333
334    void destroy(pointer p, size_type n)
335    {
336       for(; n--; ++p){
337          allocator_traits_type::destroy
338             ( this->alloc()
339             , container_detail::to_raw_pointer(p)
340             );
341       }
342    }
343
344    void destroy(pointer p)
345    {
346       allocator_traits_type::destroy
347          ( this->alloc()
348          , container_detail::to_raw_pointer(p)
349          );
350    }
351
352    void allocate_initial_block(size_type n)
353    {
354       if (n <= this->max_size()) {
355          if(n > InternalBufferChars){
356             size_type new_cap = this->next_capacity(n);
357             pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first;
358             this->is_short(false);
359             this->priv_long_addr(p);
360             this->priv_size(0);
361             this->priv_storage(new_cap);
362          }
363       }
364       else
365          throw_length_error();
366    }
367
368    void deallocate_block() 
369    {  this->deallocate(this->priv_addr(), this->priv_storage());  }
370       
371    size_type max_size() const
372    {  return allocator_traits_type::max_size(this->alloc()) - 1; }
373
374    // Helper functions for exception handling.
375    void throw_length_error() const
376    {  throw(std::length_error("basic_string"));  }
377
378    void throw_out_of_range() const
379    {  throw(std::out_of_range("basic_string"));  }
380
381    protected:
382    size_type priv_capacity() const
383    { return this->priv_storage() - 1; }
384
385    pointer priv_short_addr() const
386    {  return pointer(&this->members_.m_repr.short_repr().data[0]);  }
387
388    pointer priv_long_addr() const
389    {  return this->members_.m_repr.long_repr().start;  }
390
391    pointer priv_addr() const
392    {  return this->is_short() ? pointer(&this->members_.m_repr.short_repr().data[0]) : this->members_.m_repr.long_repr().start;  }
393
394    void priv_long_addr(pointer addr)
395    {  this->members_.m_repr.long_repr().start = addr;  }
396
397    size_type priv_storage() const
398    {  return this->is_short() ? priv_short_storage() : priv_long_storage();  }
399
400    size_type priv_short_storage() const
401    {  return InternalBufferChars;  }
402
403    size_type priv_long_storage() const
404    {  return this->members_.m_repr.long_repr().storage;  }
405
406    void priv_storage(size_type storage)
407    {  
408       if(!this->is_short())
409          this->priv_long_storage(storage);
410    }
411
412    void priv_long_storage(size_type storage)
413    {  
414       this->members_.m_repr.long_repr().storage = storage;
415    }
416
417    size_type priv_size() const
418    {  return this->is_short() ? priv_short_size() : priv_long_size();  }
419
420    size_type priv_short_size() const
421    {  return this->members_.m_repr.short_repr().h.length;  }
422
423    size_type priv_long_size() const
424    {  return this->members_.m_repr.long_repr().length;  }
425
426    void priv_size(size_type sz)
427    {  
428       if(this->is_short())
429          this->priv_short_size(sz);
430       else
431          this->priv_long_size(sz);
432    }
433
434    void priv_short_size(size_type sz)
435    {  
436       this->members_.m_repr.s.h.length = (unsigned char)sz;
437    }
438
439    void priv_long_size(size_type sz)
440    {  
441       this->members_.m_repr.long_repr().length = static_cast<typename allocator_traits_type::size_type>(sz);
442    }
443
444    void swap_data(basic_string_base& other)
445    {
446       if(this->is_short()){
447          if(other.is_short()){
448             container_detail::do_swap(this->members_.m_repr, other.members_.m_repr);
449          }
450          else{
451             repr_t copied(this->members_.m_repr);
452             this->members_.m_repr.long_repr() = other.members_.m_repr.long_repr();
453             other.members_.m_repr = copied;
454          }
455       }
456       else{
457          if(other.is_short()){
458             repr_t copied(other.members_.m_repr);
459             other.members_.m_repr.long_repr() = this->members_.m_repr.long_repr();
460             this->members_.m_repr = copied;
461          }
462          else{
463             container_detail::do_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
464          }
465       }
466    }
467 };
468
469 }  //namespace container_detail {
470
471 /// @endcond
472
473 //! The basic_string class represents a Sequence of characters. It contains all the 
474 //! usual operations of a Sequence, and, additionally, it contains standard string 
475 //! operations such as search and concatenation.
476 //!
477 //! The basic_string class is parameterized by character type, and by that type's 
478 //! Character Traits.
479 //! 
480 //! This class has performance characteristics very much like vector<>, meaning, 
481 //! for example, that it does not perform reference-count or copy-on-write, and that
482 //! concatenation of two strings is an O(N) operation. 
483 //! 
484 //! Some of basic_string's member functions use an unusual method of specifying positions 
485 //! and ranges. In addition to the conventional method using iterators, many of 
486 //! basic_string's member functions use a single value pos of type size_type to represent a 
487 //! position (in which case the position is begin() + pos, and many of basic_string's 
488 //! member functions use two values, pos and n, to represent a range. In that case pos is 
489 //! the beginning of the range and n is its size. That is, the range is 
490 //! [begin() + pos, begin() + pos + n). 
491 //! 
492 //! Note that the C++ standard does not specify the complexity of basic_string operations. 
493 //! In this implementation, basic_string has performance characteristics very similar to 
494 //! those of vector: access to a single character is O(1), while copy and concatenation 
495 //! are O(N).
496 //! 
497 //! In this implementation, begin(), 
498 //! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
499 //! In this implementation, iterators are only invalidated by member functions that
500 //! explicitly change the string's contents. 
501 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
502 template <class CharT, class Traits = std::char_traits<CharT>, class A = std::allocator<CharT> >
503 #else
504 template <class CharT, class Traits, class A>
505 #endif
506 class basic_string
507    :  private container_detail::basic_string_base<A> 
508 {
509    /// @cond
510    private:
511    typedef allocator_traits<A> allocator_traits_type;
512    BOOST_COPYABLE_AND_MOVABLE(basic_string)
513    typedef container_detail::basic_string_base<A> base_t;
514    static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
515
516    protected:
517    // A helper class to use a char_traits as a function object.
518
519    template <class Tr>
520    struct Eq_traits
521       : public std::binary_function<typename Tr::char_type,
522                                     typename Tr::char_type,
523                                     bool>
524    {
525       bool operator()(const typename Tr::char_type& x,
526                       const typename Tr::char_type& y) const
527          { return Tr::eq(x, y); }
528    };
529
530    template <class Tr>
531    struct Not_within_traits
532       : public std::unary_function<typename Tr::char_type, bool>
533    {
534       typedef const typename Tr::char_type* Pointer;
535       const Pointer m_first;
536       const Pointer m_last;
537
538       Not_within_traits(Pointer f, Pointer l) 
539          : m_first(f), m_last(l) {}
540
541       bool operator()(const typename Tr::char_type& x) const 
542       {
543          return std::find_if(m_first, m_last, 
544                         std::bind1st(Eq_traits<Tr>(), x)) == m_last;
545       }
546    };
547    /// @endcond
548
549    public:
550
551    //! The allocator type
552    typedef A                                       allocator_type;
553    //! The stored allocator type
554    typedef allocator_type                          stored_allocator_type;
555    //! The type of object, CharT, stored in the string
556    typedef CharT                                   value_type;
557    //! The second template parameter Traits
558    typedef Traits                                  traits_type;
559    //! Pointer to CharT
560    typedef typename allocator_traits_type::pointer pointer;
561    //! Const pointer to CharT 
562    typedef typename allocator_traits_type::const_pointer               const_pointer;
563    //! Reference to CharT 
564    typedef typename allocator_traits_type::reference                   reference;
565    //! Const reference to CharT 
566    typedef typename allocator_traits_type::const_reference             const_reference;
567    //! An unsigned integral type
568    typedef typename allocator_traits_type::size_type                   size_type;
569    //! A signed integral type
570    typedef typename allocator_traits_type::difference_type             difference_type;
571    //! Iterator used to iterate through a string. It's a Random Access Iterator
572    typedef pointer                                 iterator;
573    //! Const iterator used to iterate through a string. It's a Random Access Iterator
574    typedef const_pointer                           const_iterator;
575    //! Iterator used to iterate backwards through a string
576    typedef std::reverse_iterator<iterator>       reverse_iterator;
577    //! Const iterator used to iterate backwards through a string
578    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
579    //! The largest possible value of type size_type. That is, size_type(-1). 
580    static const size_type npos;
581
582    /// @cond
583    private:
584    typedef constant_iterator<CharT, difference_type> cvalue_iterator;
585    typedef typename base_t::allocator_v1  allocator_v1;
586    typedef typename base_t::allocator_v2  allocator_v2;
587    typedef typename base_t::alloc_version  alloc_version;
588    /// @endcond
589
590    public:                         // Constructor, destructor, assignment.
591    /// @cond
592    struct reserve_t {};
593
594    basic_string(reserve_t, size_type n,
595                 const allocator_type& a = allocator_type())
596       //Select allocator as in copy constructor as reserve_t-based constructors
597       //are two step copies optimized for capacity
598       : base_t( allocator_traits_type::select_on_container_copy_construction(a)
599               , n + 1)
600    { this->priv_terminate_string(); }
601
602    /// @endcond
603
604    //! <b>Effects</b>: Default constructs a basic_string.
605    //! 
606    //! <b>Throws</b>: If allocator_type's default constructor throws.
607    basic_string()
608       : base_t()
609    { this->priv_terminate_string(); }
610
611
612    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
613    //! 
614    //! <b>Throws</b>: If allocator_type's copy constructor throws.
615    explicit basic_string(const allocator_type& a)
616       : base_t(a)
617    { this->priv_terminate_string(); }
618
619    //! <b>Effects</b>: Copy constructs a basic_string.
620    //!
621    //! <b>Postcondition</b>: x == *this.
622    //! 
623    //! <b>Throws</b>: If allocator_type's default constructor or copy constructor throws.
624    basic_string(const basic_string& s) 
625       :  base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
626    { this->priv_range_initialize(s.begin(), s.end()); }
627
628    //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
629    //!
630    //! <b>Throws</b>: If allocator_type's copy constructor throws.
631    //! 
632    //! <b>Complexity</b>: Constant.
633    basic_string(BOOST_RV_REF(basic_string) s) 
634       : base_t(boost::move((base_t&)s))
635    {}
636
637    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
638    //!   and is initialized by a specific number of characters of the s string. 
639    basic_string(const basic_string& s, size_type pos, size_type n = npos,
640                const allocator_type& a = allocator_type()) 
641       : base_t(a) 
642    {
643       if (pos > s.size())
644          this->throw_out_of_range();
645       else
646          this->priv_range_initialize
647             (s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos));
648    }
649
650    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
651    //!   and is initialized by a specific number of characters of the s c-string.
652    basic_string(const CharT* s, size_type n,
653                const allocator_type& a = allocator_type()) 
654       : base_t(a) 
655    { this->priv_range_initialize(s, s + n); }
656
657    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
658    //!   and is initialized by the null-terminated s c-string.
659    basic_string(const CharT* s,
660                 const allocator_type& a = allocator_type())
661       : base_t(a) 
662    { this->priv_range_initialize(s, s + Traits::length(s)); }
663
664    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
665    //!   and is initialized by n copies of c.
666    basic_string(size_type n, CharT c,
667                 const allocator_type& a = allocator_type())
668       : base_t(a)
669    {  
670       this->priv_range_initialize(cvalue_iterator(c, n),
671                                   cvalue_iterator());
672    }
673
674    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
675    //!   and a range of iterators.
676    template <class InputIterator>
677    basic_string(InputIterator f, InputIterator l,
678                const allocator_type& a = allocator_type())
679       : base_t(a)
680    {
681       //Dispatch depending on integer/iterator
682       const bool aux_boolean = container_detail::is_convertible<InputIterator, size_type>::value;
683       typedef container_detail::bool_<aux_boolean> Result;
684       this->priv_initialize_dispatch(f, l, Result());
685    }
686
687    //! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
688    //!
689    //! <b>Throws</b>: Nothing.
690    //!
691    //! <b>Complexity</b>: Constant.
692    ~basic_string() 
693    {}
694       
695    //! <b>Effects</b>: Copy constructs a string.
696    //!
697    //! <b>Postcondition</b>: x == *this.
698    //! 
699    //! <b>Complexity</b>: Linear to the elements x contains.
700    basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
701    {
702       if (&x != this){
703          allocator_type &this_alloc     = this->alloc();
704          const allocator_type &x_alloc  = x.alloc();
705          container_detail::bool_<allocator_traits_type::
706             propagate_on_container_copy_assignment::value> flag;
707          if(flag && this_alloc != x_alloc){
708             if(!this->is_short()){
709                this->deallocate_block();
710                this->is_short(true);
711                Traits::assign(*this->priv_addr(), this->priv_null());
712                this->priv_size(0);
713             }
714          }
715          container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
716          this->assign(x.begin(), x.end());
717       }
718       return *this;
719    }
720
721    //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
722    //!
723    //! <b>Throws</b>: If allocator_type's copy constructor throws.
724    //! 
725    //! <b>Complexity</b>: Constant.
726    basic_string& operator=(BOOST_RV_REF(basic_string) x)
727    {
728       if (&x != this){
729          allocator_type &this_alloc = this->alloc();
730          allocator_type &x_alloc    = x.alloc();
731          //If allocators are equal we can just swap pointers
732          if(this_alloc == x_alloc){
733             //Destroy objects but retain memory in case x reuses it in the future
734             this->clear();
735             this->swap_data(x);
736             //Move allocator if needed
737             container_detail::bool_<allocator_traits_type::
738                propagate_on_container_move_assignment::value> flag;
739             container_detail::move_alloc(this_alloc, x_alloc, flag);
740          }
741          //If unequal allocators, then do a one by one move
742          else{
743             this->assign( x.begin(), x.end());
744          }
745       }
746       return *this;
747    }
748
749    //! <b>Effects</b>: Assignment from a null-terminated c-string.
750    basic_string& operator=(const CharT* s) 
751    { return this->assign(s, s + Traits::length(s)); }
752
753    //! <b>Effects</b>: Assignment from character.
754    basic_string& operator=(CharT c)
755    { return this->assign(static_cast<size_type>(1), c); }
756
757    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
758    //! 
759    //! <b>Throws</b>: Nothing.
760    //! 
761    //! <b>Complexity</b>: Constant.
762    iterator begin()
763    { return this->priv_addr(); }
764
765    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
766    //! 
767    //! <b>Throws</b>: Nothing.
768    //! 
769    //! <b>Complexity</b>: Constant.
770    const_iterator begin() const
771    { return this->priv_addr(); }
772
773    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
774    //! 
775    //! <b>Throws</b>: Nothing.
776    //! 
777    //! <b>Complexity</b>: Constant.
778    const_iterator cbegin() const
779    { return this->priv_addr(); }
780
781    //! <b>Effects</b>: Returns an iterator to the end of the vector.
782    //! 
783    //! <b>Throws</b>: Nothing.
784    //! 
785    //! <b>Complexity</b>: Constant.
786    iterator end()
787    { return this->priv_addr() + this->priv_size(); }
788
789    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
790    //! 
791    //! <b>Throws</b>: Nothing.
792    //! 
793    //! <b>Complexity</b>: Constant.
794    const_iterator end() const 
795    { return this->priv_addr() + this->priv_size(); }  
796
797    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
798    //! 
799    //! <b>Throws</b>: Nothing.
800    //! 
801    //! <b>Complexity</b>: Constant.
802    const_iterator cend() const 
803    { return this->priv_addr() + this->priv_size(); }  
804
805    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning 
806    //! of the reversed vector. 
807    //! 
808    //! <b>Throws</b>: Nothing.
809    //! 
810    //! <b>Complexity</b>: Constant.
811    reverse_iterator rbegin()             
812    { return reverse_iterator(this->priv_addr() + this->priv_size()); }
813
814    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 
815    //! of the reversed vector. 
816    //! 
817    //! <b>Throws</b>: Nothing.
818    //! 
819    //! <b>Complexity</b>: Constant.
820    const_reverse_iterator rbegin() const 
821    { return this->crbegin(); }
822
823    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 
824    //! of the reversed vector. 
825    //! 
826    //! <b>Throws</b>: Nothing.
827    //! 
828    //! <b>Complexity</b>: Constant.
829    const_reverse_iterator crbegin() const 
830    { return const_reverse_iterator(this->priv_addr() + this->priv_size()); }
831
832    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
833    //! of the reversed vector. 
834    //! 
835    //! <b>Throws</b>: Nothing.
836    //! 
837    //! <b>Complexity</b>: Constant.
838    reverse_iterator rend()               
839    { return reverse_iterator(this->priv_addr()); }
840
841    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
842    //! of the reversed vector. 
843    //! 
844    //! <b>Throws</b>: Nothing.
845    //! 
846    //! <b>Complexity</b>: Constant.
847    const_reverse_iterator rend()   const 
848    { return this->crend(); }
849
850    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
851    //! of the reversed vector. 
852    //! 
853    //! <b>Throws</b>: Nothing.
854    //! 
855    //! <b>Complexity</b>: Constant.
856    const_reverse_iterator crend()   const 
857    { return const_reverse_iterator(this->priv_addr()); }
858
859    //! <b>Effects</b>: Returns a copy of the internal allocator.
860    //! 
861    //! <b>Throws</b>: If allocator's copy constructor throws.
862    //! 
863    //! <b>Complexity</b>: Constant.
864    allocator_type get_allocator() const 
865    { return this->alloc(); }
866
867    //! <b>Effects</b>: Returns a reference to the internal allocator.
868    //! 
869    //! <b>Throws</b>: Nothing
870    //! 
871    //! <b>Complexity</b>: Constant.
872    //! 
873    //! <b>Note</b>: Non-standard extension.
874    const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
875    {  return this->alloc(); }
876
877    //! <b>Effects</b>: Returns a reference to the internal allocator.
878    //! 
879    //! <b>Throws</b>: Nothing
880    //! 
881    //! <b>Complexity</b>: Constant.
882    //! 
883    //! <b>Note</b>: Non-standard extension.
884    stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
885    {  return this->alloc(); }
886
887    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
888    //! 
889    //! <b>Throws</b>: Nothing.
890    //! 
891    //! <b>Complexity</b>: Constant.
892    size_type size() const    
893    { return this->priv_size(); }
894
895    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
896    //! 
897    //! <b>Throws</b>: Nothing.
898    //! 
899    //! <b>Complexity</b>: Constant.
900    size_type length() const
901    { return this->size(); }
902
903    //! <b>Effects</b>: Returns the largest possible size of the vector.
904    //! 
905    //! <b>Throws</b>: Nothing.
906    //! 
907    //! <b>Complexity</b>: Constant.
908    size_type max_size() const
909    { return base_t::max_size(); }
910
911    //! <b>Effects</b>: Inserts or erases elements at the end such that
912    //!   the size becomes n. New elements are copy constructed from x.
913    //!
914    //! <b>Throws</b>: If memory allocation throws
915    //!
916    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
917    void resize(size_type n, CharT c)
918    {
919       if (n <= size())
920          this->erase(this->begin() + n, this->end());
921       else
922          this->append(n - this->size(), c);
923    }
924
925    //! <b>Effects</b>: Inserts or erases elements at the end such that
926    //!   the size becomes n. New elements are default constructed.
927    //!
928    //! <b>Throws</b>: If memory allocation throws
929    //!
930    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
931    void resize(size_type n)
932    { resize(n, this->priv_null()); }
933
934    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
935    //!   effect. Otherwise, it is a request for allocation of additional memory.
936    //!   If the request is successful, then capacity() is greater than or equal to
937    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
938    //! 
939    //! <b>Throws</b>: If memory allocation allocation throws
940    void reserve(size_type res_arg)
941    {
942       if (res_arg > this->max_size())
943          this->throw_length_error();
944
945       if (this->capacity() < res_arg){
946          size_type n = container_detail::max_value(res_arg, this->size()) + 1;
947          size_type new_cap = this->next_capacity(n);
948          pointer new_start = this->allocation_command
949             (allocate_new, n, new_cap, new_cap).first;
950          size_type new_length = 0;
951
952          new_length += priv_uninitialized_copy
953             (this->priv_addr(), this->priv_addr() + this->priv_size(), new_start);
954          this->priv_construct_null(new_start + new_length);
955          this->deallocate_block();
956          this->is_short(false);
957          this->priv_long_addr(new_start);
958          this->priv_size(new_length);
959          this->priv_storage(new_cap);
960       }
961    }
962
963    //! <b>Effects</b>: Number of elements for which memory has been allocated.
964    //!   capacity() is always greater than or equal to size().
965    //! 
966    //! <b>Throws</b>: Nothing.
967    //! 
968    //! <b>Complexity</b>: Constant.
969    size_type capacity() const
970    { return this->priv_capacity(); }
971
972    //! <b>Effects</b>: Erases all the elements of the vector.
973    //!
974    //! <b>Throws</b>: Nothing.
975    //!
976    //! <b>Complexity</b>: Linear to the number of elements in the vector.
977    void clear()
978    {
979       if (!empty()) {
980          Traits::assign(*this->priv_addr(), this->priv_null());
981          this->priv_size(0);
982       }
983    }
984
985    //! <b>Effects</b>: Tries to deallocate the excess of memory created
986    //!   with previous allocations. The size of the string is unchanged
987    //!
988    //! <b>Throws</b>: Nothing
989    //!
990    //! <b>Complexity</b>: Linear to size().
991    void shrink_to_fit()
992    {
993       //Check if shrinking is possible
994       if(this->priv_storage() > InternalBufferChars){
995          //Check if we should pass from dynamically allocated buffer
996          //to the internal storage
997          if(this->priv_size() < (InternalBufferChars)){
998             //Dynamically allocated buffer attributes
999             pointer   long_addr    = this->priv_long_addr();
1000             size_type long_storage = this->priv_long_storage();
1001             size_type long_size    = this->priv_long_size();
1002             //Shrink from allocated buffer to the internal one, including trailing null
1003             Traits::copy( container_detail::to_raw_pointer(this->priv_short_addr())
1004                         , container_detail::to_raw_pointer(long_addr)
1005                         , long_size+1);
1006             this->is_short(true);
1007             this->alloc().deallocate(long_addr, long_storage);
1008          }
1009          else{
1010             //Shrinking in dynamic buffer
1011             this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
1012          }
1013       }
1014    }
1015
1016    //! <b>Effects</b>: Returns true if the vector contains no elements.
1017    //! 
1018    //! <b>Throws</b>: Nothing.
1019    //! 
1020    //! <b>Complexity</b>: Constant.
1021    bool empty() const
1022    { return !this->priv_size(); }
1023
1024    //! <b>Requires</b>: size() > n.
1025    //!
1026    //! <b>Effects</b>: Returns a reference to the nth element 
1027    //!   from the beginning of the container.
1028    //! 
1029    //! <b>Throws</b>: Nothing.
1030    //! 
1031    //! <b>Complexity</b>: Constant.
1032    reference operator[](size_type n)
1033       { return *(this->priv_addr() + n); }
1034
1035    //! <b>Requires</b>: size() > n.
1036    //!
1037    //! <b>Effects</b>: Returns a const reference to the nth element 
1038    //!   from the beginning of the container.
1039    //! 
1040    //! <b>Throws</b>: Nothing.
1041    //! 
1042    //! <b>Complexity</b>: Constant.
1043    const_reference operator[](size_type n) const
1044       { return *(this->priv_addr() + n); }
1045
1046    //! <b>Requires</b>: size() > n.
1047    //!
1048    //! <b>Effects</b>: Returns a reference to the nth element 
1049    //!   from the beginning of the container.
1050    //! 
1051    //! <b>Throws</b>: std::range_error if n >= size()
1052    //! 
1053    //! <b>Complexity</b>: Constant.
1054    reference at(size_type n) {
1055       if (n >= size())
1056       this->throw_out_of_range();
1057       return *(this->priv_addr() + n);
1058    }
1059
1060    //! <b>Requires</b>: size() > n.
1061    //!
1062    //! <b>Effects</b>: Returns a const reference to the nth element 
1063    //!   from the beginning of the container.
1064    //! 
1065    //! <b>Throws</b>: std::range_error if n >= size()
1066    //! 
1067    //! <b>Complexity</b>: Constant.
1068    const_reference at(size_type n) const {
1069       if (n >= size())
1070          this->throw_out_of_range();
1071       return *(this->priv_addr() + n);
1072    }
1073
1074    //! <b>Effects</b>: Calls append(str.data, str.size()).
1075    //!
1076    //! <b>Returns</b>: *this
1077    basic_string& operator+=(const basic_string& s)
1078    {  return this->append(s); }
1079
1080    //! <b>Effects</b>: Calls append(s).
1081    //!
1082    //! <b>Returns</b>: *this
1083    basic_string& operator+=(const CharT* s)
1084    {  return this->append(s); }
1085
1086    //! <b>Effects</b>: Calls append(1, c).
1087    //!
1088    //! <b>Returns</b>: *this
1089    basic_string& operator+=(CharT c)
1090    {  this->push_back(c); return *this;   }
1091
1092    //! <b>Effects</b>: Calls append(str.data(), str.size()).
1093    //!
1094    //! <b>Returns</b>: *this
1095    basic_string& append(const basic_string& s) 
1096    {  return this->append(s.begin(), s.end());  }
1097
1098    //! <b>Requires</b>: pos <= str.size()
1099    //!
1100    //! <b>Effects</b>: Determines the effective length rlen of the string to append 
1101    //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen).
1102    //!
1103    //! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
1104    //!
1105    //! <b>Returns</b>: *this
1106    basic_string& append(const basic_string& s, size_type pos, size_type n)
1107    {
1108       if (pos > s.size())
1109       this->throw_out_of_range();
1110       return this->append(s.begin() + pos,
1111                           s.begin() + pos + container_detail::min_value(n, s.size() - pos));
1112    }
1113
1114    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1115    //!
1116    //! <b>Effects</b>: The function replaces the string controlled by *this with
1117    //!   a string of length size() + n whose irst size() elements are a copy of the
1118    //!   original string controlled by *this and whose remaining
1119    //!   elements are a copy of the initial n elements of s.
1120    //!
1121    //! <b>Throws</b>: If memory allocation throws length_error if size() + n > max_size().
1122    //!
1123    //! <b>Returns</b>: *this
1124    basic_string& append(const CharT* s, size_type n) 
1125    {  return this->append(s, s + n);  }
1126
1127    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1128    //!
1129    //! <b>Effects</b>: Calls append(s, traits::length(s)).
1130    //!
1131    //! <b>Returns</b>: *this
1132    basic_string& append(const CharT* s) 
1133    {  return this->append(s, s + Traits::length(s));  }
1134
1135    //! <b>Effects</b>: Equivalent to append(basic_string(n, c)).
1136    //!
1137    //! <b>Returns</b>: *this
1138    basic_string& append(size_type n, CharT c)
1139    {  return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
1140
1141    //! <b>Requires</b>: [first,last) is a valid range.
1142    //!
1143    //! <b>Effects</b>: Equivalent to append(basic_string(first, last)).
1144    //!
1145    //! <b>Returns</b>: *this
1146    template <class InputIter>
1147    basic_string& append(InputIter first, InputIter last)
1148    {  this->insert(this->end(), first, last);   return *this;  }
1149
1150    //! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
1151    void push_back(CharT c)
1152    {
1153       if (this->priv_size() < this->capacity()){
1154          this->priv_construct_null(this->priv_addr() + (this->priv_size() + 1));
1155          Traits::assign(this->priv_addr()[this->priv_size()], c);
1156          this->priv_size(this->priv_size()+1);
1157       }
1158       else{
1159          //No enough memory, insert a new object at the end
1160          this->append((size_type)1, c);
1161       }
1162    }
1163
1164    //! <b>Effects</b>: Equivalent to assign(str, 0, npos).
1165    //!
1166    //! <b>Returns</b>: *this
1167    basic_string& assign(const basic_string& s) 
1168    {  return this->operator=(s); }
1169
1170    //! <b>Effects</b>: The function replaces the string controlled by *this
1171    //!    with a string of length str.size() whose elements are a copy of the string 
1172    //!   controlled by str. Leaves str in a valid but unspecified state.
1173    //!
1174    //! <b>Throws</b>: Nothing
1175    //!
1176    //! <b>Returns</b>: *this
1177    basic_string& assign(BOOST_RV_REF(basic_string) ms) 
1178    {  return this->swap_data(ms), *this;  }
1179
1180    //! <b>Requires</b>: pos <= str.size()
1181    //!
1182    //! <b>Effects</b>: Determines the effective length rlen of the string to assign as
1183    //!   the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen).
1184    //!
1185    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
1186    //!
1187    //! <b>Returns</b>: *this
1188    basic_string& assign(const basic_string& s, 
1189                         size_type pos, size_type n) {
1190       if (pos > s.size())
1191       this->throw_out_of_range();
1192       return this->assign(s.begin() + pos, 
1193                           s.begin() + pos + container_detail::min_value(n, s.size() - pos));
1194    }
1195
1196    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1197    //!
1198    //! <b>Effects</b>: Replaces the string controlled by *this with a string of
1199    //! length n whose elements are a copy of those pointed to by s.
1200    //!
1201    //! <b>Throws</b>: If memory allocation throws or length_error if n > max_size().
1202    //!    
1203    //! <b>Returns</b>: *this
1204    basic_string& assign(const CharT* s, size_type n)
1205    {  return this->assign(s, s + n);   }
1206
1207    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1208    //!
1209    //! <b>Effects</b>: Calls assign(s, traits::length(s)).
1210    //!
1211    //! <b>Returns</b>: *this
1212    basic_string& assign(const CharT* s)
1213    { return this->assign(s, s + Traits::length(s)); }
1214
1215    //! <b>Effects</b>: Equivalent to assign(basic_string(n, c)).
1216    //!
1217    //! <b>Returns</b>: *this
1218    basic_string& assign(size_type n, CharT c)
1219    {  return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
1220
1221    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1222    //!
1223    //! <b>Returns</b>: *this
1224    template <class InputIter>
1225    basic_string& assign(InputIter first, InputIter last) 
1226    {
1227       //Dispatch depending on integer/iterator
1228       const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
1229       typedef container_detail::bool_<aux_boolean> Result;
1230       return this->priv_assign_dispatch(first, last, Result());
1231    }
1232
1233    //! <b>Requires</b>: pos <= size().
1234    //!
1235    //! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
1236    //!
1237    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
1238    //!
1239    //! <b>Returns</b>: *this
1240    basic_string& insert(size_type pos, const basic_string& s) 
1241    {
1242       if (pos > size())
1243          this->throw_out_of_range();
1244       if (this->size() > this->max_size() - s.size())
1245          this->throw_length_error();
1246       this->insert(this->priv_addr() + pos, s.begin(), s.end());
1247       return *this;
1248    }
1249
1250    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
1251    //!
1252    //! <b>Effects</b>: Determines the effective length rlen of the string to insert as
1253    //!   the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen).
1254    //!
1255    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
1256    //!
1257    //! <b>Returns</b>: *this
1258    basic_string& insert(size_type pos1, const basic_string& s,
1259                         size_type pos2, size_type n) 
1260    {
1261       if (pos1 > this->size() || pos2 > s.size())
1262          this->throw_out_of_range();
1263       size_type len = container_detail::min_value(n, s.size() - pos2);
1264       if (this->size() > this->max_size() - len)
1265          this->throw_length_error();
1266       const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
1267       const CharT *end_ptr = beg_ptr + len;
1268       this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
1269       return *this;
1270    }
1271
1272    //! <b>Requires</b>: s points to an array of at least n elements of CharT and pos <= size().
1273    //!
1274    //! <b>Effects</b>: Replaces the string controlled by *this with a string of length size() + n
1275    //!   whose first pos elements are a copy of the initial elements of the original string
1276    //!   controlled by *this and whose next n elements are a copy of the elements in s and whose
1277    //!   remaining elements are a copy of the remaining elements of the original string controlled by *this.
1278    //!
1279    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size() or
1280    //!   length_error if size() + n > max_size().
1281    //!
1282    //! <b>Returns</b>: *this
1283    basic_string& insert(size_type pos, const CharT* s, size_type n) 
1284    {
1285       if (pos > this->size())
1286          this->throw_out_of_range();
1287       if (this->size() > this->max_size() - n)
1288          this->throw_length_error();
1289       this->insert(this->priv_addr() + pos, s, s + n);
1290       return *this;
1291    }
1292
1293    //! <b>Requires</b>: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT
1294    //!
1295    //! <b>Effects</b>: Calls insert(pos, s, traits::length(s)).
1296    //!
1297    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1298    //!   length_error if size() > max_size() - Traits::length(s)
1299    //!
1300    //! <b>Returns</b>: *this
1301    basic_string& insert(size_type pos, const CharT* s) 
1302    {
1303       if (pos > size())
1304          this->throw_out_of_range();
1305       size_type len = Traits::length(s);
1306       if (this->size() > this->max_size() - len)
1307          this->throw_length_error();
1308       this->insert(this->priv_addr() + pos, s, s + len);
1309       return *this;
1310    }
1311
1312    //! <b>Effects</b>: Equivalent to insert(pos, basic_string(n, c)).
1313    //!
1314    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1315    //!   length_error if size() > max_size() - n
1316    //!
1317    //! <b>Returns</b>: *this
1318    basic_string& insert(size_type pos, size_type n, CharT c) 
1319    {
1320       if (pos > this->size())
1321          this->throw_out_of_range();
1322       if (this->size() > this->max_size() - n)
1323          this->throw_length_error();
1324       this->insert(const_iterator(this->priv_addr() + pos), n, c);
1325       return *this;
1326    }
1327
1328    //! <b>Requires</b>: p is a valid iterator on *this.
1329    //!
1330    //! <b>Effects</b>: inserts a copy of c before the character referred to by p.
1331    //!
1332    //! <b>Returns</b>: An iterator which refers to the copy of the inserted character.
1333    iterator insert(const_iterator p, CharT c) 
1334    {
1335       size_type new_offset = p - this->priv_addr() + 1;
1336       this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
1337       return this->priv_addr() + new_offset;
1338    }
1339
1340
1341    //! <b>Requires</b>: p is a valid iterator on *this.
1342    //!
1343    //! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
1344    //!
1345    //! <b>Returns</b>: An iterator which refers to the copy of the first
1346    //!   inserted character, or p if n == 0.
1347    void insert(const_iterator p, size_type n, CharT c)
1348    {
1349       this->insert(p, cvalue_iterator(c, n), cvalue_iterator());
1350    }
1351
1352    //! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
1353    //!
1354    //! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
1355    //!
1356    //! <b>Returns</b>: An iterator which refers to the copy of the first
1357    //!   inserted character, or p if first == last.
1358    template <class InputIter>
1359    void insert(const_iterator p, InputIter first, InputIter last) 
1360    {
1361       //Dispatch depending on integer/iterator
1362       const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
1363       typedef container_detail::bool_<aux_boolean> Result;
1364       this->priv_insert_dispatch(p, first, last, Result());
1365    }
1366
1367    //! <b>Requires</b>: pos <= size()
1368    //!
1369    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
1370    //!   The function then replaces the string controlled by *this with a string of length size() - xlen
1371    //!   whose first pos elements are a copy of the initial elements of the original string controlled by *this,
1372    //!   and whose remaining elements are a copy of the elements of the original string controlled by *this
1373    //!   beginning at position pos + xlen.
1374    //!
1375    //! <b>Throws</b>: out_of_range if pos > size().
1376    //!
1377    //! <b>Returns</b>: *this
1378    basic_string& erase(size_type pos = 0, size_type n = npos) 
1379    {
1380       if (pos > size())
1381          this->throw_out_of_range();
1382       erase(this->priv_addr() + pos, this->priv_addr() + pos + container_detail::min_value(n, size() - pos));
1383       return *this;
1384    }  
1385
1386    //! <b>Effects</b>: Removes the character referred to by p.
1387    //!
1388    //! <b>Throws</b>: Nothing
1389    //!
1390    //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
1391    //!    erased. If no such element exists, end() is returned.
1392    iterator erase(const_iterator p) 
1393    {
1394       // The move includes the terminating null.
1395       CharT *ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
1396       Traits::move(ptr,
1397                    container_detail::to_raw_pointer(p + 1), 
1398                    this->priv_size() - (p - this->priv_addr()));
1399       this->priv_size(this->priv_size()-1);
1400       return iterator(ptr);
1401    }
1402
1403    //! <b>Requires</b>: first and last are valid iterators on *this, defining a range [first,last).
1404    //!
1405    //! <b>Effects</b>: Removes the characters in the range [first,last).
1406    //!
1407    //! <b>Throws</b>: Nothing
1408    //!
1409    //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
1410    //!   the other elements being erased. If no such element exists, end() is returned.
1411    iterator erase(const_iterator first, const_iterator last)
1412    {
1413       CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first));
1414       if (first != last) { // The move includes the terminating null.
1415          size_type num_erased = last - first;
1416          Traits::move(f,
1417                       container_detail::to_raw_pointer(last), 
1418                       (this->priv_size() + 1)-(last - this->priv_addr()));
1419          size_type new_length = this->priv_size() - num_erased;
1420          this->priv_size(new_length);
1421       }
1422       return iterator(f);
1423    }
1424
1425    //! <b>Requires</b>: !empty()
1426    //!
1427    //! <b>Throws</b>: Nothing
1428    //!
1429    //! <b>Effects</b>: Equivalent to erase(size() - 1, 1).
1430    void pop_back()
1431    {
1432       Traits::assign(this->priv_addr()[this->priv_size()-1], this->priv_null());
1433       this->priv_size(this->priv_size()-1);;
1434    }
1435
1436    //! <b>Requires</b>: pos1 <= size().
1437    //!
1438    //! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
1439    //!
1440    //! <b>Throws</b>: if memory allocation throws or out_of_range if pos1 > size().
1441    //!
1442    //! <b>Returns</b>: *this
1443    basic_string& replace(size_type pos1, size_type n1, const basic_string& str) 
1444    {
1445       if (pos1 > size())
1446          this->throw_out_of_range();
1447       const size_type len = container_detail::min_value(n1, size() - pos1);
1448       if (this->size() - len >= this->max_size() - str.size())
1449          this->throw_length_error();
1450       return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, 
1451                            str.begin(), str.end());
1452    }
1453
1454    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
1455    //!
1456    //! <b>Effects</b>: Determines the effective length rlen of the string to be
1457    //!   inserted as the smaller of n2 and str.size() - pos2 and calls
1458    //!   replace(pos1, n1, str.data() + pos2, rlen).
1459    //!
1460    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size().
1461    //!
1462    //! <b>Returns</b>: *this
1463    basic_string& replace(size_type pos1, size_type n1,
1464                          const basic_string& str, size_type pos2, size_type n2) 
1465    {
1466       if (pos1 > size() || pos2 > str.size())
1467          this->throw_out_of_range();
1468       const size_type len1 = container_detail::min_value(n1, size() - pos1);
1469       const size_type len2 = container_detail::min_value(n2, str.size() - pos2);
1470       if (this->size() - len1 >= this->max_size() - len2)
1471          this->throw_length_error();
1472       return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len1,
1473                      str.priv_addr() + pos2, str.priv_addr() + pos2 + len2);
1474    }
1475
1476    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
1477    //!
1478    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the 
1479    //!   smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. 
1480    //!   Otherwise, the function replaces the string controlled by *this with a string of 
1481    //!   length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements 
1482    //!   of the original string controlled by *this, whose next n2 elements are a copy of the 
1483    //!   initial n2 elements of s, and whose remaining elements are a copy of the elements of 
1484    //!   the original string controlled by *this beginning at position pos + xlen.
1485    //!
1486    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error 
1487    //!   if the length of the  resulting string would exceed max_size()
1488    //!
1489    //! <b>Returns</b>: *this
1490    basic_string& replace(size_type pos1, size_type n1,
1491                         const CharT* s, size_type n2) 
1492    {
1493       if (pos1 > size())
1494          this->throw_out_of_range();
1495       const size_type len = container_detail::min_value(n1, size() - pos1);
1496       if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
1497          this->throw_length_error();
1498       return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len,
1499                      s, s + n2);
1500    }
1501
1502    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
1503    //!
1504    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller
1505    //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise,
1506    //! the function replaces the string controlled by *this with a string of length size() - xlen + n2
1507    //! whose first pos1 elements are a copy of the initial elements of the original string controlled
1508    //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose
1509    //! remaining elements are a copy of the elements of the original string controlled by *this
1510    //! beginning at position pos + xlen.
1511    //!
1512    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error 
1513    //!   if the length of the resulting string would exceed max_size()
1514    //!
1515    //! <b>Returns</b>: *this
1516    basic_string& replace(size_type pos, size_type n1, const CharT* s) 
1517    {
1518       if (pos > size())
1519          this->throw_out_of_range();
1520       const size_type len = container_detail::min_value(n1, size() - pos);
1521       const size_type n2 = Traits::length(s);
1522       if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
1523          this->throw_length_error();
1524       return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len,
1525                      s, s + Traits::length(s));
1526    }
1527
1528    //! <b>Requires</b>: pos1 <= size().
1529    //!
1530    //! <b>Effects</b>: Equivalent to replace(pos1, n1, basic_string(n2, c)).
1531    //!
1532    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error 
1533    //!   if the length of the  resulting string would exceed max_size()
1534    //!
1535    //! <b>Returns</b>: *this
1536    basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c) 
1537    {
1538       if (pos1 > size())
1539          this->throw_out_of_range();
1540       const size_type len = container_detail::min_value(n1, size() - pos1);
1541       if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
1542          this->throw_length_error();
1543       return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, n2, c);
1544    }
1545
1546    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
1547    //!
1548    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, str).
1549    //!
1550    //! <b>Throws</b>: if memory allocation throws
1551    //!
1552    //! <b>Returns</b>: *this
1553    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str) 
1554    { return this->replace(i1, i2, str.begin(), str.end()); }
1555
1556    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and 
1557    //!   s points to an array of at least n elements
1558    //!
1559    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, n).
1560    //!
1561    //! <b>Throws</b>: if memory allocation throws
1562    //!
1563    //! <b>Returns</b>: *this
1564    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n) 
1565    { return this->replace(i1, i2, s, s + n); }
1566
1567    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and s points to an
1568    //!   array of at least traits::length(s) + 1 elements of CharT.
1569    //!
1570    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)).
1571    //!
1572    //! <b>Throws</b>: if memory allocation throws
1573    //!
1574    //! <b>Returns</b>: *this
1575    basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s) 
1576    {  return this->replace(i1, i2, s, s + Traits::length(s));   }
1577
1578    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
1579    //!
1580    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)).
1581    //!
1582    //! <b>Throws</b>: if memory allocation throws
1583    //!
1584    //! <b>Returns</b>: *this
1585    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
1586    {
1587       const size_type len = static_cast<size_type>(i2 - i1);
1588       if (len >= n) {
1589          Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), n, c);
1590          erase(i1 + n, i2);
1591       }
1592       else {
1593          Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), len, c);
1594          insert(i2, n - len, c);
1595       }
1596       return *this;
1597    }
1598
1599    //! <b>Requires</b>: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges.
1600    //!
1601    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)).
1602    //!
1603    //! <b>Throws</b>: if memory allocation throws
1604    //!
1605    //! <b>Returns</b>: *this
1606    template <class InputIter>
1607    basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2) 
1608    {
1609       //Dispatch depending on integer/iterator
1610       const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
1611       typedef container_detail::bool_<aux_boolean> Result;
1612       return this->priv_replace_dispatch(i1, i2, j1, j2,  Result());
1613    }
1614
1615    //! <b>Requires</b>: pos <= size()
1616    //!
1617    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
1618    //!   smaller of n and size() - pos. s shall designate an array of at least rlen elements.
1619    //!   The function then replaces the string designated by s with a string of length rlen 
1620    //!   whose elements are a copy of the string controlled by *this beginning at position pos.
1621    //!   The function does not append a null object to the string designated by s.
1622    //!
1623    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos > size().
1624    //!
1625    //! <b>Returns</b>: rlen
1626    size_type copy(CharT* s, size_type n, size_type pos = 0) const 
1627    {
1628       if (pos > size())
1629          this->throw_out_of_range();
1630       const size_type len = container_detail::min_value(n, size() - pos);
1631       Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
1632       return len;
1633    }
1634
1635    //! <b>Effects</b>: *this contains the same sequence of characters that was in s, 
1636    //!   s contains the same sequence of characters that was in *this.
1637    //!
1638    //! <b>Throws</b>: Nothing
1639    void swap(basic_string& x)
1640    {
1641       this->base_t::swap_data(x);
1642       container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
1643       container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
1644    }
1645
1646    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
1647    //!
1648    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
1649    //!
1650    //! <b>Complexity</b>: constant time.
1651    const CharT* c_str() const 
1652    {  return container_detail::to_raw_pointer(this->priv_addr()); }
1653
1654    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
1655    //!
1656    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
1657    //!
1658    //! <b>Complexity</b>: constant time.
1659    const CharT* data()  const 
1660    {  return container_detail::to_raw_pointer(this->priv_addr()); }
1661
1662    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both 
1663    //!   of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size();
1664    //!   2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
1665    //!
1666    //! <b>Throws</b>: Nothing
1667    //!
1668    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1669    size_type find(const basic_string& s, size_type pos = 0) const 
1670    { return find(s.c_str(), pos, s.size()); }
1671
1672    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1673    //!
1674    //! <b>Throws</b>: Nothing
1675    //!
1676    //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(s,n),pos).
1677    size_type find(const CharT* s, size_type pos, size_type n) const
1678    {
1679       if (pos + n > size())
1680          return npos;
1681       else {
1682          pointer finish = this->priv_addr() + this->priv_size();
1683          const const_iterator result =
1684             std::search(container_detail::to_raw_pointer(this->priv_addr() + pos), 
1685                    container_detail::to_raw_pointer(finish),
1686                    s, s + n, Eq_traits<Traits>());
1687          return result != finish ? result - begin() : npos;
1688       }
1689    }
1690
1691    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1692    //!
1693    //! <b>Throws</b>: Nothing
1694    //!
1695    //! <b>Returns</b>: find(basic_string(s), pos).
1696    size_type find(const CharT* s, size_type pos = 0) const 
1697    { return find(s, pos, Traits::length(s)); }
1698
1699    //! <b>Throws</b>: Nothing
1700    //!
1701    //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(1,c), pos).
1702    size_type find(CharT c, size_type pos = 0) const
1703    {
1704       if (pos >= size())
1705          return npos;
1706       else {
1707          pointer finish = this->priv_addr() + this->priv_size();
1708          const const_iterator result =
1709             std::find_if(this->priv_addr() + pos, finish,
1710                   std::bind2nd(Eq_traits<Traits>(), c));
1711          return result != finish ? result - begin() : npos;
1712       }
1713    }
1714
1715    //! <b>Effects</b>: Determines the highest position xpos, if possible, such 
1716    //!   that both of the following conditions obtain:
1717    //!   a) xpos <= pos and xpos + str.size() <= size();
1718    //!   b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
1719    //!
1720    //! <b>Throws</b>: Nothing
1721    //!
1722    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1723    size_type rfind(const basic_string& str, size_type pos = npos) const 
1724       { return rfind(str.c_str(), pos, str.size()); }
1725
1726    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1727    //!
1728    //! <b>Throws</b>: Nothing
1729    //!
1730    //! <b>Returns</b>: rfind(basic_string(s, n), pos).
1731    size_type rfind(const CharT* s, size_type pos, size_type n) const
1732    {
1733       const size_type len = size();
1734
1735       if (n > len)
1736          return npos;
1737       else if (n == 0)
1738          return container_detail::min_value(len, pos);
1739       else {
1740          const const_iterator last = begin() + container_detail::min_value(len - n, pos) + n;
1741          const const_iterator result = find_end(begin(), last,
1742                                                 s, s + n,
1743                                                 Eq_traits<Traits>());
1744          return result != last ? result - begin() : npos;
1745       }
1746    }
1747
1748    //! <b>Requires</b>: pos <= size() and s points to an array of at least 
1749    //!   traits::length(s) + 1 elements of CharT.
1750    //!
1751    //! <b>Throws</b>: Nothing
1752    //!
1753    //! <b>Returns</b>: rfind(basic_string(s), pos).
1754    size_type rfind(const CharT* s, size_type pos = npos) const 
1755       { return rfind(s, pos, Traits::length(s)); }
1756
1757    //! <b>Throws</b>: Nothing
1758    //!
1759    //! <b>Returns</b>: rfind(basic_string<CharT,traits,Allocator>(1,c),pos).
1760    size_type rfind(CharT c, size_type pos = npos) const
1761    {
1762       const size_type len = size();
1763
1764       if (len < 1)
1765          return npos;
1766       else {
1767          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
1768          const_reverse_iterator rresult =
1769             std::find_if(const_reverse_iterator(last), rend(),
1770                   std::bind2nd(Eq_traits<Traits>(), c));
1771          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
1772       }
1773    }
1774
1775    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
1776    //!   following conditions obtain: a) pos <= xpos and xpos < size();
1777    //!   b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
1778    //!
1779    //! <b>Throws</b>: Nothing
1780    //!
1781    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1782    size_type find_first_of(const basic_string& s, size_type pos = 0) const 
1783       { return find_first_of(s.c_str(), pos, s.size()); }
1784
1785    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1786    //!
1787    //! <b>Throws</b>: Nothing
1788    //!
1789    //! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
1790    size_type find_first_of(const CharT* s, size_type pos, size_type n) const
1791    {
1792       if (pos >= size())
1793          return npos;
1794       else {
1795          pointer finish = this->priv_addr() + this->priv_size();
1796          const_iterator result = std::find_first_of(this->priv_addr() + pos, finish,
1797                                                     s, s + n,
1798                                                     Eq_traits<Traits>());
1799          return result != finish ? result - begin() : npos;
1800       }
1801    }
1802
1803    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1804    //!
1805    //! <b>Throws</b>: Nothing
1806    //!
1807    //! <b>Returns</b>: find_first_of(basic_string(s), pos).
1808    size_type find_first_of(const CharT* s, size_type pos = 0) const 
1809       { return find_first_of(s, pos, Traits::length(s)); }
1810
1811    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1812    //!
1813    //! <b>Throws</b>: Nothing
1814    //!
1815    //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos).
1816    size_type find_first_of(CharT c, size_type pos = 0) const 
1817     { return find(c, pos); }
1818
1819    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of 
1820    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
1821    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
1822    //!
1823    //! <b>Throws</b>: Nothing
1824    //!
1825    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1826    size_type find_last_of(const basic_string& str, size_type pos = npos) const
1827       { return find_last_of(str.c_str(), pos, str.size()); }
1828
1829    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1830    //!
1831    //! <b>Throws</b>: Nothing
1832    //!
1833    //! <b>Returns</b>: find_last_of(basic_string(s, n), pos).
1834    size_type find_last_of(const CharT* s, size_type pos, size_type n) const
1835    {
1836       const size_type len = size();
1837
1838       if (len < 1)
1839          return npos;
1840       else {
1841          const const_iterator last = this->priv_addr() + container_detail::min_value(len - 1, pos) + 1;
1842          const const_reverse_iterator rresult =
1843             std::find_first_of(const_reverse_iterator(last), rend(),
1844                                s, s + n,
1845                                Eq_traits<Traits>());
1846          return rresult != rend() ? (rresult.base() - 1) - this->priv_addr() : npos;
1847       }
1848    }
1849
1850    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1851    //!
1852    //! <b>Throws</b>: Nothing
1853    //!
1854    //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,Allocator>(1,c),pos).
1855    size_type find_last_of(const CharT* s, size_type pos = npos) const 
1856       { return find_last_of(s, pos, Traits::length(s)); }
1857
1858    //! <b>Throws</b>: Nothing
1859    //!
1860    //! <b>Returns</b>: find_last_of(basic_string(s), pos).
1861    size_type find_last_of(CharT c, size_type pos = npos) const 
1862       {  return rfind(c, pos);   }
1863
1864    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that 
1865    //!   both of the following conditions obtain:
1866    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no
1867    //!   element I of the string controlled by str.
1868    //!
1869    //! <b>Throws</b>: Nothing
1870    //!
1871    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1872    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const 
1873       { return find_first_not_of(str.c_str(), pos, str.size()); }
1874
1875    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1876    //!
1877    //! <b>Throws</b>: Nothing
1878    //!
1879    //! <b>Returns</b>: find_first_not_of(basic_string(s, n), pos).
1880    size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
1881    {
1882       if (pos > size())
1883          return npos;
1884       else {
1885          pointer finish = this->priv_addr() + this->priv_size();
1886          const_iterator result = std::find_if(this->priv_addr() + pos, finish,
1887                                     Not_within_traits<Traits>(s, s + n));
1888          return result != finish ? result - this->priv_addr() : npos;
1889       }
1890    }
1891
1892    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1893    //!
1894    //! <b>Throws</b>: Nothing
1895    //!
1896    //! <b>Returns</b>: find_first_not_of(basic_string(s), pos).
1897    size_type find_first_not_of(const CharT* s, size_type pos = 0) const 
1898       { return find_first_not_of(s, pos, Traits::length(s)); }
1899
1900    //! <b>Throws</b>: Nothing
1901    //!
1902    //! <b>Returns</b>: find_first_not_of(basic_string(1, c), pos).
1903    size_type find_first_not_of(CharT c, size_type pos = 0) const
1904    {
1905       if (pos > size())
1906          return npos;
1907       else {
1908          pointer finish = this->priv_addr() + this->priv_size();
1909          const_iterator result
1910             = std::find_if(this->priv_addr() + pos, finish,
1911                      std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
1912          return result != finish ? result - begin() : npos;
1913       }
1914    }
1915
1916    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
1917    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size(); 
1918    //!   b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str.
1919    //!
1920    //! <b>Throws</b>: Nothing
1921    //!
1922    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
1923    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
1924       { return find_last_not_of(str.c_str(), pos, str.size()); }
1925
1926    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1927    //!
1928    //! <b>Throws</b>: Nothing
1929    //!
1930    //! <b>Returns</b>: find_last_not_of(basic_string(s, n), pos).
1931    size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
1932    {
1933       const size_type len = size();
1934
1935       if (len < 1)
1936          return npos;
1937       else {
1938          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
1939          const const_reverse_iterator rresult =
1940             std::find_if(const_reverse_iterator(last), rend(),
1941                     Not_within_traits<Traits>(s, s + n));
1942          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
1943       }
1944    }
1945
1946    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1947    //!
1948    //! <b>Throws</b>: Nothing
1949    //!
1950    //! <b>Returns</b>: find_last_not_of(basic_string(s), pos).
1951    size_type find_last_not_of(const CharT* s, size_type pos = npos) const
1952       { return find_last_not_of(s, pos, Traits::length(s)); }
1953
1954    //! <b>Throws</b>: Nothing
1955    //!
1956    //! <b>Returns</b>: find_last_not_of(basic_string(1, c), pos).
1957    size_type find_last_not_of(CharT c, size_type pos = npos) const
1958    {
1959       const size_type len = size();
1960
1961       if (len < 1)
1962          return npos;
1963       else {
1964          const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
1965          const_reverse_iterator rresult =
1966             std::find_if(const_reverse_iterator(last), rend(),
1967                   std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
1968          return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
1969       }
1970    }
1971
1972    //! <b>Requires</b>: Requires: pos <= size()
1973    //!
1974    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
1975    //!   the smaller of n and size() - pos.
1976    //!
1977    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
1978    //!
1979    //! <b>Returns</b>: basic_string<CharT,traits,Allocator>(data()+pos,rlen).
1980    basic_string substr(size_type pos = 0, size_type n = npos) const 
1981    {
1982       if (pos > size())
1983          this->throw_out_of_range();
1984       return basic_string(this->priv_addr() + pos, 
1985                           this->priv_addr() + pos + container_detail::min_value(n, size() - pos), this->alloc());
1986    }
1987
1988    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
1989    //!   the smaller of size() and str.size(). The function then compares the two strings by
1990    //!   calling traits::compare(data(), str.data(), rlen).
1991    //!
1992    //! <b>Throws</b>: Nothing
1993    //!
1994    //! <b>Returns</b>: The nonzero result if the result of the comparison is nonzero.
1995    //!   Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(),
1996    //!   and value > 0 if size() > str.size()
1997    int compare(const basic_string& str) const 
1998    { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), str.priv_addr(), str.priv_addr() + str.priv_size()); }
1999
2000    //! <b>Requires</b>: pos1 <= size()
2001    //!
2002    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2003    //!   the smaller of
2004    //!
2005    //! <b>Throws</b>: out_of_range if pos1 > size()
2006    //!
2007    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(str).
2008    int compare(size_type pos1, size_type n1, const basic_string& str) const 
2009    {
2010       if (pos1 > size())
2011          this->throw_out_of_range();
2012       return s_compare(this->priv_addr() + pos1, 
2013                         this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
2014                         str.priv_addr(), str.priv_addr() + str.priv_size());
2015    }
2016
2017    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size() 
2018    //!
2019    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2020    //!   the smaller of
2021    //!
2022    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
2023    //!
2024    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
2025    int compare(size_type pos1, size_type n1, 
2026                const basic_string& str, size_type pos2, size_type n2) const {
2027       if (pos1 > size() || pos2 > str.size())
2028          this->throw_out_of_range();
2029       return s_compare(this->priv_addr() + pos1, 
2030                         this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
2031                         str.priv_addr() + pos2, 
2032                         str.priv_addr() + pos2 + container_detail::min_value(n2, size() - pos2));
2033    }
2034
2035    //! <b>Throws</b>: Nothing
2036    //!
2037    //! <b>Returns</b>: compare(basic_string(s)).
2038    int compare(const CharT* s) const 
2039    {  return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), s, s + Traits::length(s));   }
2040
2041
2042    //! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
2043    //!
2044    //! <b>Throws</b>: out_of_range if pos1 > size()
2045    //!
2046    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2047    int compare(size_type pos1, size_type n1,
2048                const CharT* s, size_type n2 = npos) const 
2049    {
2050       if (pos1 > size())
2051          this->throw_out_of_range();
2052       return s_compare(this->priv_addr() + pos1, 
2053                         this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
2054                         s, s + n2);
2055    }
2056
2057    //! <b>Requires</b>: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT.
2058    //!
2059    //! <b>Throws</b>: out_of_range if pos1 > size()
2060    //!
2061    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2062    int compare(size_type pos1, size_type n1, const CharT* s) const 
2063    {  return this->compare(pos1, n1, s, Traits::length(s)); }
2064
2065    /// @cond
2066    private:
2067    static int s_compare(const_pointer f1, const_pointer l1,
2068                         const_pointer f2, const_pointer l2) 
2069    {
2070       const difference_type n1 = l1 - f1;
2071       const difference_type n2 = l2 - f2;
2072       const int cmp = Traits::compare(container_detail::to_raw_pointer(f1), 
2073                                       container_detail::to_raw_pointer(f2), 
2074                                       container_detail::min_value(n1, n2));
2075       return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
2076    }
2077
2078    template<class AllocVersion>
2079    void priv_shrink_to_fit_dynamic_buffer
2080       ( AllocVersion
2081       , typename container_detail::enable_if<container_detail::is_same<AllocVersion, allocator_v1> >::type* = 0)
2082    {
2083       //Allocate a new buffer.
2084       size_type real_cap = 0;
2085       pointer   long_addr    = this->priv_long_addr();
2086       size_type long_size    = this->priv_long_size();
2087       size_type long_storage = this->priv_long_storage();
2088       //We can make this nothrow as chars are always NoThrowCopyables
2089       try{
2090          std::pair<pointer, bool> ret = this->allocation_command
2091                (allocate_new, long_size+1, long_size+1, real_cap, long_addr);
2092          //Copy and update
2093          Traits::copy( container_detail::to_raw_pointer(ret.first)
2094                      , container_detail::to_raw_pointer(this->priv_long_addr())
2095                      , long_size+1);
2096          this->priv_long_addr(ret.first);
2097          this->priv_storage(real_cap);
2098          //And release old buffer
2099          this->alloc().deallocate(long_addr, long_storage);
2100       }
2101       catch(...){
2102          return;
2103       }
2104    }
2105
2106    template<class AllocVersion>
2107    void priv_shrink_to_fit_dynamic_buffer
2108       ( AllocVersion 
2109       , typename container_detail::enable_if<container_detail::is_same<AllocVersion, allocator_v2> >::type* = 0)
2110    {
2111       size_type received_size;
2112       if(this->alloc().allocation_command
2113          ( shrink_in_place | nothrow_allocation
2114          , this->priv_long_storage(), this->priv_long_size()+1
2115          , received_size, this->priv_long_addr()).first){
2116          this->priv_storage(received_size);
2117       }
2118    }
2119
2120    void priv_construct_null(pointer p)
2121    {  this->construct(p, 0);  }
2122
2123    static CharT priv_null()
2124    {  return (CharT) 0; }
2125
2126    // Helper functions used by constructors.  It is a severe error for
2127    // any of them to be called anywhere except from within constructors.
2128    void priv_terminate_string() 
2129    {  this->priv_construct_null(this->priv_addr() + this->priv_size());  }
2130
2131    template <class InputIter>
2132    void priv_range_initialize(InputIter f, InputIter l,
2133                               std::input_iterator_tag)
2134    {
2135       this->allocate_initial_block(InternalBufferChars);
2136       this->priv_construct_null(this->priv_addr() + this->priv_size());
2137       this->append(f, l);
2138    }
2139
2140    template <class ForwardIter>
2141    void priv_range_initialize(ForwardIter f, ForwardIter l, 
2142                               std::forward_iterator_tag)
2143    {
2144       difference_type n = std::distance(f, l);
2145       this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
2146       priv_uninitialized_copy(f, l, this->priv_addr());
2147       this->priv_size(n);
2148       this->priv_terminate_string();
2149    }
2150
2151    template <class InputIter>
2152    void priv_range_initialize(InputIter f, InputIter l)
2153    {
2154       typedef typename std::iterator_traits<InputIter>::iterator_category Category;
2155       this->priv_range_initialize(f, l, Category());
2156    }
2157
2158    template <class Integer>
2159    void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
2160    {
2161       this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
2162       priv_uninitialized_fill_n(this->priv_addr(), n, x);
2163       this->priv_size(n);
2164       this->priv_terminate_string();
2165    }
2166
2167    template <class InputIter>
2168    void priv_initialize_dispatch(InputIter f, InputIter l, container_detail::false_)
2169    {  this->priv_range_initialize(f, l);  }
2170  
2171    template<class FwdIt, class Count> inline
2172    void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
2173    {
2174       //Save initial position
2175       FwdIt init = first;
2176
2177       BOOST_TRY{
2178          //Construct objects
2179          for (; count--; ++first){
2180             this->construct(first, val);
2181          }
2182       }
2183       BOOST_CATCH(...){
2184          //Call destructors
2185          for (; init != first; ++init){
2186             this->destroy(init);
2187          }
2188          BOOST_RETHROW
2189       }
2190       BOOST_CATCH_END
2191    }
2192
2193    template<class InpIt, class FwdIt> inline
2194    size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
2195    {
2196       //Save initial destination position
2197       FwdIt dest_init = dest;
2198       size_type constructed = 0;
2199
2200       BOOST_TRY{
2201          //Try to build objects
2202          for (; first != last; ++dest, ++first, ++constructed){
2203             this->construct(dest, *first);
2204          }
2205       }
2206       BOOST_CATCH(...){
2207          //Call destructors
2208          for (; constructed--; ++dest_init){
2209             this->destroy(dest_init);
2210          }
2211          BOOST_RETHROW
2212       }
2213       BOOST_CATCH_END
2214       return (constructed);
2215    }
2216
2217    template <class Integer>
2218    basic_string& priv_assign_dispatch(Integer n, Integer x, container_detail::true_) 
2219    {  return this->assign((size_type) n, (CharT) x);   }
2220
2221    template <class InputIter>
2222    basic_string& priv_assign_dispatch(InputIter f, InputIter l,
2223                                       container_detail::false_)
2224    {
2225       size_type cur = 0;
2226       CharT *ptr = container_detail::to_raw_pointer(this->priv_addr());
2227       while (f != l && cur != this->priv_size()) {
2228          Traits::assign(*ptr, *f);
2229          ++f;
2230          ++cur;
2231          ++ptr;
2232       }
2233       if (f == l)
2234          this->erase(this->priv_addr() + cur, this->priv_addr() + this->priv_size());
2235       else
2236          this->append(f, l);
2237       return *this;
2238    }
2239
2240    template <class InputIter>
2241    void priv_insert(const_iterator p, InputIter first, InputIter last, std::input_iterator_tag)
2242    {
2243       for ( ; first != last; ++first, ++p) {
2244          p = this->insert(p, *first);
2245       }
2246    }
2247
2248    template <class ForwardIter>
2249    void priv_insert(const_iterator position, ForwardIter first, 
2250                     ForwardIter last,  std::forward_iterator_tag)
2251    {
2252       if (first != last) {
2253          size_type n = std::distance(first, last);
2254          size_type remaining = this->capacity() - this->priv_size();
2255          const size_type old_size = this->size();
2256          pointer old_start = this->priv_addr();
2257          bool enough_capacity = false;
2258          std::pair<pointer, bool> allocation_ret;
2259          size_type new_cap = 0;
2260
2261          //Check if we have enough capacity
2262          if (remaining >= n){
2263             enough_capacity = true;            
2264          }
2265          else {
2266             //Otherwise expand current buffer or allocate new storage
2267             new_cap  = this->next_capacity(n);
2268             allocation_ret = this->allocation_command
2269                   (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, 
2270                      new_cap, new_cap, old_start);
2271
2272             //Check forward expansion
2273             if(old_start == allocation_ret.first){
2274                enough_capacity = true;
2275                this->priv_storage(new_cap);
2276             }
2277          }
2278
2279          //Reuse same buffer
2280          if(enough_capacity){
2281             const size_type elems_after =
2282                this->priv_size() - (position - this->priv_addr());
2283             size_type old_length = this->priv_size();
2284             if (elems_after >= n) {
2285                pointer pointer_past_last = this->priv_addr() + this->priv_size() + 1;
2286                priv_uninitialized_copy(this->priv_addr() + (this->priv_size() - n + 1),
2287                                        pointer_past_last, pointer_past_last);
2288
2289                this->priv_size(this->priv_size()+n);
2290                Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(position + n)),
2291                            container_detail::to_raw_pointer(position),
2292                            (elems_after - n) + 1);
2293                this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
2294             }
2295             else {
2296                ForwardIter mid = first;
2297                std::advance(mid, elems_after + 1);
2298
2299                priv_uninitialized_copy(mid, last, this->priv_addr() + this->priv_size() + 1);
2300                this->priv_size(this->priv_size() + (n - elems_after));
2301                priv_uninitialized_copy
2302                   (position, const_iterator(this->priv_addr() + old_length + 1),
2303                   this->priv_addr() + this->priv_size());
2304                this->priv_size(this->priv_size() + elems_after);
2305                this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
2306             }
2307          }
2308          else{
2309             pointer new_start = allocation_ret.first;
2310             if(!allocation_ret.second){
2311                //Copy data to new buffer
2312                size_type new_length = 0;
2313                //This can't throw, since characters are POD
2314                new_length += priv_uninitialized_copy
2315                               (const_iterator(this->priv_addr()), position, new_start);
2316                new_length += priv_uninitialized_copy
2317                               (first, last, new_start + new_length);
2318                new_length += priv_uninitialized_copy
2319                               (position, const_iterator(this->priv_addr() + this->priv_size()),
2320                               new_start + new_length);
2321                this->priv_construct_null(new_start + new_length);
2322
2323                this->deallocate_block();
2324                this->is_short(false);
2325                this->priv_long_addr(new_start);
2326                this->priv_long_size(new_length);
2327                this->priv_long_storage(new_cap);
2328             }
2329             else{
2330                //value_type is POD, so backwards expansion is much easier 
2331                //than with vector<T>
2332                value_type *oldbuf = container_detail::to_raw_pointer(old_start);
2333                value_type *newbuf = container_detail::to_raw_pointer(new_start);
2334                const value_type *pos    = container_detail::to_raw_pointer(position);
2335                size_type  before  = pos - oldbuf;
2336
2337                //First move old data
2338                Traits::move(newbuf, oldbuf, before);
2339                Traits::move(newbuf + before + n, pos, old_size - before);
2340                //Now initialize the new data
2341                priv_uninitialized_copy(first, last, new_start + before);
2342                this->priv_construct_null(new_start + (old_size + n));
2343                this->is_short(false);
2344                this->priv_long_addr(new_start);
2345                this->priv_long_size(old_size + n);
2346                this->priv_long_storage(new_cap);
2347             }
2348          }
2349       }
2350    }
2351
2352    template <class Integer>
2353    void priv_insert_dispatch(const_iterator p, Integer n, Integer x,
2354                            container_detail::true_) 
2355    {  insert(p, (size_type) n, (CharT) x);   }
2356
2357    template <class InputIter>
2358    void priv_insert_dispatch(const_iterator p, InputIter first, InputIter last,
2359                            container_detail::false_) 
2360    {
2361       typedef typename std::iterator_traits<InputIter>::iterator_category Category;
2362       priv_insert(p, first, last, Category());
2363    }
2364
2365    template <class InputIterator, class OutIterator>
2366    void priv_copy(InputIterator first, InputIterator last, OutIterator result)
2367    {
2368       for ( ; first != last; ++first, ++result)
2369          Traits::assign(*result, *first);
2370    }
2371
2372    void priv_copy(const CharT* first, const CharT* last, CharT* result) 
2373    {  Traits::copy(result, first, last - first);  }
2374
2375    template <class Integer>
2376    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
2377                                        Integer n, Integer x,
2378                                        container_detail::true_) 
2379    {  return this->replace(first, last, (size_type) n, (CharT) x);   }
2380
2381    template <class InputIter>
2382    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
2383                                        InputIter f, InputIter l,
2384                                        container_detail::false_) 
2385    {
2386       typedef typename std::iterator_traits<InputIter>::iterator_category Category;
2387       return this->priv_replace(first, last, f, l, Category());
2388    }
2389
2390
2391    template <class InputIter>
2392    basic_string& priv_replace(const_iterator first, const_iterator last,
2393                               InputIter f, InputIter l, std::input_iterator_tag)
2394    {
2395       for ( ; first != last && f != l; ++first, ++f)
2396          Traits::assign(*first, *f);
2397
2398       if (f == l)
2399          this->erase(first, last);
2400       else
2401          this->insert(last, f, l);
2402       return *this;
2403    }
2404
2405    template <class ForwardIter>
2406    basic_string& priv_replace(const_iterator first, const_iterator last,
2407                               ForwardIter f, ForwardIter l, 
2408                               std::forward_iterator_tag)
2409    {
2410       difference_type n = std::distance(f, l);
2411       const difference_type len = last - first;
2412       if (len >= n) {
2413          this->priv_copy(f, l, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
2414          this->erase(first + n, last);
2415       }
2416       else {
2417          ForwardIter m = f;
2418          std::advance(m, len);
2419          this->priv_copy(f, m, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
2420          this->insert(last, m, l);
2421       }
2422       return *this;
2423    }
2424    /// @endcond
2425 };
2426
2427 //!Typedef for a basic_string of
2428 //!narrow characters
2429 typedef basic_string
2430    <char
2431    ,std::char_traits<char>
2432    ,std::allocator<char> >
2433 string;
2434
2435 //!Typedef for a basic_string of
2436 //!narrow characters
2437 typedef basic_string
2438    <wchar_t
2439    ,std::char_traits<wchar_t>
2440    ,std::allocator<wchar_t> >
2441 wstring;
2442
2443 /// @cond
2444
2445 template <class CharT, class Traits, class A> 
2446 const typename basic_string<CharT,Traits,A>::size_type 
2447 basic_string<CharT,Traits,A>::npos 
2448   = (typename basic_string<CharT,Traits,A>::size_type) -1;
2449
2450 /// @endcond
2451
2452 // ------------------------------------------------------------
2453 // Non-member functions.
2454
2455 // Operator+
2456
2457 template <class CharT, class Traits, class A>
2458 inline basic_string<CharT,Traits,A>
2459 operator+(const basic_string<CharT,Traits,A>& x,
2460           const basic_string<CharT,Traits,A>& y)
2461 {
2462    typedef basic_string<CharT,Traits,A> str_t;
2463    typedef typename str_t::reserve_t reserve_t;
2464    reserve_t reserve;
2465    str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
2466    result.append(x);
2467    result.append(y);
2468    return boost::move(result);
2469 }
2470
2471 template <class CharT, class Traits, class A> inline
2472 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2473    operator+(
2474    BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
2475    , BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
2476 {
2477    mx += my;
2478    return boost::move(mx);
2479 }
2480
2481 template <class CharT, class Traits, class A> inline
2482 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2483    operator+(
2484    BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
2485    , const basic_string<CharT,Traits,A>& y)
2486 {
2487    mx += y;
2488    return boost::move(mx);
2489 }
2490
2491 template <class CharT, class Traits, class A> inline
2492 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2493    operator+(const basic_string<CharT,Traits,A>& x,
2494          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
2495 {
2496    typedef typename basic_string<CharT,Traits,A>::size_type size_type;
2497    my.replace(size_type(0), size_type(0), x);
2498    return boost::move(my);
2499 }
2500
2501 template <class CharT, class Traits, class A>
2502 inline basic_string<CharT,Traits,A>
2503 operator+(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2504 {
2505    typedef basic_string<CharT, Traits, A> str_t;
2506    typedef typename str_t::reserve_t reserve_t;
2507    reserve_t reserve;
2508    const typename str_t::size_type n = Traits::length(s);
2509    str_t result(reserve, n + y.size());
2510    result.append(s, s + n);
2511    result.append(y);
2512    return boost::move(result);
2513 }
2514
2515 template <class CharT, class Traits, class A> inline
2516 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2517 operator+(const CharT* s,
2518          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
2519 {
2520    typedef typename basic_string<CharT,Traits,A>::size_type size_type;
2521    return boost::move(my.replace(size_type(0), size_type(0), s));
2522 }
2523
2524 template <class CharT, class Traits, class A>
2525 inline basic_string<CharT,Traits,A>
2526 operator+(CharT c, const basic_string<CharT,Traits,A>& y) 
2527 {
2528    typedef basic_string<CharT,Traits,A> str_t;
2529    typedef typename str_t::reserve_t reserve_t;
2530    reserve_t reserve;
2531    str_t result(reserve, 1 + y.size());
2532    result.push_back(c);
2533    result.append(y);
2534    return boost::move(result);
2535 }
2536
2537 template <class CharT, class Traits, class A> inline
2538 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2539 operator+(CharT c,
2540          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
2541 {
2542    typedef typename basic_string<CharT,Traits,A>::size_type size_type;
2543    return boost::move(my.replace(size_type(0), size_type(0), &c, &c + 1));
2544 }
2545
2546 template <class CharT, class Traits, class A>
2547 inline basic_string<CharT,Traits,A>
2548 operator+(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2549 {
2550    typedef basic_string<CharT,Traits,A> str_t;
2551    typedef typename str_t::reserve_t reserve_t;
2552    reserve_t reserve;
2553    const typename str_t::size_type n = Traits::length(s);
2554    str_t result(reserve, x.size() + n, x.get_stored_allocator());
2555    result.append(x);
2556    result.append(s, s + n);
2557    return boost::move(result);
2558 }
2559
2560 template <class CharT, class Traits, class A>
2561 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2562 operator+(BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
2563          , const CharT* s)
2564 {
2565    mx += s;
2566    return boost::move(mx);
2567 }
2568
2569 template <class CharT, class Traits, class A>
2570 inline basic_string<CharT,Traits,A>
2571 operator+(const basic_string<CharT,Traits,A>& x, const CharT c) 
2572 {
2573    typedef basic_string<CharT,Traits,A> str_t;
2574    typedef typename str_t::reserve_t reserve_t;
2575    reserve_t reserve;
2576    str_t result(reserve, x.size() + 1, x.get_stored_allocator());
2577    result.append(x);
2578    result.push_back(c);
2579    return boost::move(result);
2580 }
2581
2582 template <class CharT, class Traits, class A>
2583 BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
2584 operator+( BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
2585          , const CharT c)
2586 {
2587    mx += c;
2588    return boost::move(mx);
2589 }
2590
2591 // Operator== and operator!=
2592
2593 template <class CharT, class Traits, class A>
2594 inline bool
2595 operator==(const basic_string<CharT,Traits,A>& x,
2596            const basic_string<CharT,Traits,A>& y) 
2597 {
2598    return x.size() == y.size() &&
2599           Traits::compare(x.data(), y.data(), x.size()) == 0;
2600 }
2601
2602 template <class CharT, class Traits, class A>
2603 inline bool
2604 operator==(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2605 {
2606    typename basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
2607    return n == y.size() && Traits::compare(s, y.data(), n) == 0;
2608 }
2609
2610 template <class CharT, class Traits, class A>
2611 inline bool
2612 operator==(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2613 {
2614    typename basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
2615    return x.size() == n && Traits::compare(x.data(), s, n) == 0;
2616 }
2617
2618 template <class CharT, class Traits, class A>
2619 inline bool
2620 operator!=(const basic_string<CharT,Traits,A>& x,
2621            const basic_string<CharT,Traits,A>& y) 
2622    {  return !(x == y);  }
2623
2624 template <class CharT, class Traits, class A>
2625 inline bool
2626 operator!=(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2627    {  return !(s == y); }
2628
2629 template <class CharT, class Traits, class A>
2630 inline bool
2631 operator!=(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2632    {  return !(x == s);   }
2633
2634
2635 // Operator< (and also >, <=, and >=).
2636
2637 template <class CharT, class Traits, class A>
2638 inline bool
2639 operator<(const basic_string<CharT,Traits,A>& x, const basic_string<CharT,Traits,A>& y) 
2640 {
2641    return x.compare(y) < 0;
2642 //   return basic_string<CharT,Traits,A>
2643 //      ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
2644 }
2645
2646 template <class CharT, class Traits, class A>
2647 inline bool
2648 operator<(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2649 {
2650    return y.compare(s) > 0;
2651 //   basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
2652 //   return basic_string<CharT,Traits,A>
2653 //          ::s_compare(s, s + n, y.begin(), y.end()) < 0;
2654 }
2655
2656 template <class CharT, class Traits, class A>
2657 inline bool
2658 operator<(const basic_string<CharT,Traits,A>& x,
2659           const CharT* s) 
2660 {
2661    return x.compare(s) < 0;
2662 //   basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
2663 //   return basic_string<CharT,Traits,A>
2664 //      ::s_compare(x.begin(), x.end(), s, s + n) < 0;
2665 }
2666
2667 template <class CharT, class Traits, class A>
2668 inline bool
2669 operator>(const basic_string<CharT,Traits,A>& x,
2670           const basic_string<CharT,Traits,A>& y) {
2671    return y < x;
2672 }
2673
2674 template <class CharT, class Traits, class A>
2675 inline bool
2676 operator>(const CharT* s, const basic_string<CharT,Traits,A>& y) {
2677    return y < s;
2678 }
2679
2680 template <class CharT, class Traits, class A>
2681 inline bool
2682 operator>(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2683 {
2684    return s < x;
2685 }
2686
2687 template <class CharT, class Traits, class A>
2688 inline bool
2689 operator<=(const basic_string<CharT,Traits,A>& x,
2690            const basic_string<CharT,Traits,A>& y) 
2691 {
2692   return !(y < x);
2693 }
2694
2695 template <class CharT, class Traits, class A>
2696 inline bool
2697 operator<=(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2698    {  return !(y < s);  }
2699
2700 template <class CharT, class Traits, class A>
2701 inline bool
2702 operator<=(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2703    {  return !(s < x);  }
2704
2705 template <class CharT, class Traits, class A>
2706 inline bool
2707 operator>=(const basic_string<CharT,Traits,A>& x,
2708            const basic_string<CharT,Traits,A>& y) 
2709    {  return !(x < y);  }
2710
2711 template <class CharT, class Traits, class A>
2712 inline bool
2713 operator>=(const CharT* s, const basic_string<CharT,Traits,A>& y) 
2714    {  return !(s < y);  }
2715
2716 template <class CharT, class Traits, class A>
2717 inline bool
2718 operator>=(const basic_string<CharT,Traits,A>& x, const CharT* s) 
2719    {  return !(x < s);  }
2720
2721 // Swap.
2722 template <class CharT, class Traits, class A>
2723 inline void swap(basic_string<CharT,Traits,A>& x, basic_string<CharT,Traits,A>& y) 
2724 {  x.swap(y);  }
2725
2726 /// @cond
2727 // I/O.  
2728 namespace container_detail {
2729
2730 template <class CharT, class Traits>
2731 inline bool
2732 string_fill(std::basic_ostream<CharT, Traits>& os,
2733                   std::basic_streambuf<CharT, Traits>* buf,
2734                   std::size_t n)
2735 {
2736    CharT f = os.fill();
2737    std::size_t i;
2738    bool ok = true;
2739
2740    for (i = 0; i < n; i++)
2741       ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
2742    return ok;
2743 }
2744
2745 }  //namespace container_detail {
2746 /// @endcond
2747
2748 template <class CharT, class Traits, class A>
2749 std::basic_ostream<CharT, Traits>&
2750 operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,A>& s)
2751 {
2752    typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
2753    bool ok = false;
2754
2755    if (sentry) {
2756       ok = true;
2757       typename basic_string<CharT,Traits,A>::size_type n = s.size();
2758       typename basic_string<CharT,Traits,A>::size_type pad_len = 0;
2759       const bool left = (os.flags() & std::ios::left) != 0;
2760       const std::size_t w = os.width(0);
2761       std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
2762
2763       if (w != 0 && n < w)
2764          pad_len = w - n;
2765        
2766       if (!left)
2767          ok = container_detail::string_fill(os, buf, pad_len);    
2768
2769       ok = ok && 
2770             buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
2771
2772       if (left)
2773          ok = ok && container_detail::string_fill(os, buf, pad_len);
2774    }
2775
2776    if (!ok)
2777       os.setstate(std::ios_base::failbit);
2778
2779    return os;
2780 }
2781
2782
2783 template <class CharT, class Traits, class A>
2784 std::basic_istream<CharT, Traits>& 
2785 operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>& s)
2786 {
2787    typename std::basic_istream<CharT, Traits>::sentry sentry(is);
2788
2789    if (sentry) {
2790       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
2791       const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
2792
2793       s.clear();
2794       std::size_t n = is.width(0);
2795       if (n == 0)
2796          n = static_cast<std::size_t>(-1);
2797       else
2798          s.reserve(n);
2799
2800       while (n-- > 0) {
2801          typename Traits::int_type c1 = buf->sbumpc();
2802
2803          if (Traits::eq_int_type(c1, Traits::eof())) {
2804             is.setstate(std::ios_base::eofbit);
2805             break;
2806          }
2807          else {
2808             CharT c = Traits::to_char_type(c1);
2809
2810             if (ctype.is(std::ctype<CharT>::space, c)) {
2811                if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
2812                   is.setstate(std::ios_base::failbit);
2813                break;
2814             }
2815             else
2816                s.push_back(c);
2817          }
2818       }
2819       
2820       // If we have read no characters, then set failbit.
2821       if (s.size() == 0)
2822          is.setstate(std::ios_base::failbit);
2823    }
2824    else
2825       is.setstate(std::ios_base::failbit);
2826
2827    return is;
2828 }
2829
2830 template <class CharT, class Traits, class A>    
2831 std::basic_istream<CharT, Traits>& 
2832 getline(std::istream& is, basic_string<CharT,Traits,A>& s,CharT delim)
2833 {
2834    typename basic_string<CharT,Traits,A>::size_type nread = 0;
2835    typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
2836    if (sentry) {
2837       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
2838       s.clear();
2839
2840       while (nread < s.max_size()) {
2841          int c1 = buf->sbumpc();
2842          if (Traits::eq_int_type(c1, Traits::eof())) {
2843             is.setstate(std::ios_base::eofbit);
2844             break;
2845          }
2846          else {
2847             ++nread;
2848             CharT c = Traits::to_char_type(c1);
2849             if (!Traits::eq(c, delim)) 
2850                s.push_back(c);
2851             else
2852                break;              // Character is extracted but not appended.
2853          }
2854       }
2855    }
2856    if (nread == 0 || nread >= s.max_size())
2857       is.setstate(std::ios_base::failbit);
2858
2859    return is;
2860 }
2861
2862 template <class CharT, class Traits, class A>    
2863 inline std::basic_istream<CharT, Traits>& 
2864 getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>& s)
2865 {
2866    return getline(is, s, '\n');
2867 }
2868
2869 template <class Ch, class A>
2870 inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, A> const& v)
2871 {
2872    return hash_range(v.begin(), v.end());
2873 }
2874
2875 }}
2876
2877 /// @cond
2878
2879 namespace boost {
2880 /*
2881 //!has_trivial_destructor_after_move<> == true_type
2882 //!specialization for optimizations
2883 template <class C, class T, class A>
2884 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, A> >
2885 {
2886    static const bool value = has_trivial_destructor<A>::value;
2887 };
2888 */
2889 }
2890
2891 /// @endcond
2892
2893 #include <boost/container/detail/config_end.hpp>
2894
2895 #endif // BOOST_CONTAINER_STRING_HPP