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