Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:37:08

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_CONTAINER_STRING_HPP
0012 #define BOOST_CONTAINER_STRING_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 #  pragma once
0020 #endif
0021 
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 #include <boost/container/container_fwd.hpp>
0025 // container
0026 #include <boost/container/allocator_traits.hpp>
0027 #include <boost/container/new_allocator.hpp> //new_allocator
0028 #include <boost/container/throw_exception.hpp>
0029 // container/detail
0030 #include <boost/container/detail/alloc_helpers.hpp>
0031 #include <boost/container/detail/allocator_version_traits.hpp>
0032 #include <boost/container/detail/allocation_type.hpp>
0033 #include <boost/container/detail/iterator.hpp>
0034 #include <boost/container/detail/iterators.hpp>
0035 #include <boost/container/detail/min_max.hpp>
0036 #include <boost/container/detail/mpl.hpp>
0037 #include <boost/container/detail/next_capacity.hpp>
0038 #include <boost/move/detail/to_raw_pointer.hpp>
0039 #include <boost/container/detail/version_type.hpp>
0040 #include <boost/container/detail/type_traits.hpp>
0041 #include <boost/container/detail/algorithm.hpp>
0042 #include <boost/container/detail/minimal_char_traits_header.hpp>  // for char_traits
0043 //intrusive
0044 #include <boost/intrusive/pointer_traits.hpp>
0045 #include <boost/intrusive/detail/hash_combine.hpp>
0046 #include <boost/move/detail/launder.hpp>
0047 //move
0048 #include <boost/move/utility_core.hpp>
0049 #include <boost/move/adl_move_swap.hpp>
0050 #include <boost/move/traits.hpp>
0051 
0052 #include <iosfwd> 
0053 #include <istream>   //
0054 #include <ostream>
0055 #include <ios>
0056 #include <locale>
0057 #include <cstddef>
0058 #include <climits>
0059 
0060 //std
0061 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0062 #include <initializer_list>   //for std::initializer_list
0063 #endif
0064 
0065 //GCC 12 has a regression for array-bounds warnings
0066 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
0067 #pragma GCC diagnostic push
0068 #pragma GCC diagnostic ignored "-Warray-bounds"
0069 #endif
0070 
0071 
0072 namespace boost {
0073 namespace container {
0074 
0075 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0076 namespace dtl {
0077 // ------------------------------------------------------------
0078 // Class basic_string_base.
0079 
0080 // basic_string_base is a helper class that makes it it easier to write
0081 // an exception-safe version of basic_string.  The constructor allocates,
0082 // but does not initialize, a block of memory.  The destructor
0083 // deallocates, but does not destroy elements within, a block of
0084 // memory. The destructor assumes that the memory either is the internal buffer,
0085 // or else points to a block of memory that was allocated using string_base's
0086 // allocator and whose size is this->m_storage.
0087 template <class Allocator>
0088 class basic_string_base
0089 {
0090    basic_string_base & operator=(const basic_string_base &);
0091    basic_string_base(const basic_string_base &);
0092 
0093    typedef Allocator allocator_type;
0094  public:
0095    typedef allocator_traits<allocator_type>                 allocator_traits_type;
0096    typedef allocator_type                                   stored_allocator_type;
0097    typedef typename allocator_traits_type::pointer          pointer;
0098    typedef typename allocator_traits_type::value_type       value_type;
0099    typedef typename allocator_traits_type::size_type        size_type;
0100    typedef typename allocator_traits_type::difference_type  difference_type;
0101 
0102    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
0103 
0104    inline basic_string_base()
0105       : members_()
0106    {}
0107 
0108    inline explicit basic_string_base(const allocator_type& a)
0109       : members_(a)
0110    {}
0111 
0112    inline explicit basic_string_base(BOOST_RV_REF(allocator_type) a)
0113       :  members_(boost::move(a))
0114    {}
0115 
0116    inline basic_string_base(const allocator_type& a, size_type n)
0117       : members_(a)
0118    {
0119       this->allocate_initial_block(n);
0120    }
0121 
0122    inline explicit basic_string_base(size_type n)
0123       : members_()
0124    {
0125       this->allocate_initial_block(n);
0126    }
0127 
0128    inline ~basic_string_base()
0129    {
0130       if(!this->is_short()){
0131          this->deallocate(this->priv_long_addr(), this->priv_long_storage());
0132       }
0133    }
0134 
0135    private:
0136 
0137    #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0138    #pragma GCC diagnostic push
0139    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0140    #endif
0141 
0142    //This is the structure controlling a long string
0143    struct long_t
0144    {
0145       size_type      is_short  : 1;
0146       size_type      length    : (sizeof(size_type)*CHAR_BIT - 1);
0147       size_type      storage;
0148       pointer        start;
0149 
0150       inline long_t()
0151          : is_short(0)
0152       {}
0153 
0154       inline long_t(size_type len, size_type stor, pointer ptr)
0155          : is_short(0), length(len), storage(stor), start(ptr)
0156       {}
0157 
0158       inline long_t(const long_t &other)
0159       {
0160          this->is_short = false;
0161          length   = other.length;
0162          storage  = other.storage;
0163          start    = other.start;
0164       }
0165 
0166       inline long_t &operator= (const long_t &other)
0167       {
0168          length   = other.length;
0169          storage  = other.storage;
0170          start    = other.start;
0171          return *this;
0172       }
0173    };
0174 
0175    #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0176    #pragma GCC diagnostic pop
0177    #endif
0178 
0179 
0180    //This type is the first part of the structure controlling a short string
0181    //The "data" member stores
0182    struct short_header
0183    {
0184       unsigned char  is_short  : 1;
0185       unsigned char  length    : (CHAR_BIT - 1);
0186    };
0187 
0188    //This type has the same alignment and size as long_t but it's POD
0189    //so, unlike long_t, it can be placed in a union
0190 
0191    typedef typename dtl::aligned_storage
0192       <sizeof(long_t), dtl::alignment_of<long_t>::value>::type   long_raw_t;
0193 
0194    protected:
0195    BOOST_STATIC_CONSTEXPR size_type  MinInternalBufferChars = 8;
0196    BOOST_STATIC_CONSTEXPR size_type  AlignmentOfValueType =
0197       alignment_of<value_type>::value;
0198    BOOST_STATIC_CONSTEXPR size_type  ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
0199    BOOST_STATIC_CONSTEXPR size_type  ZeroCostInternalBufferChars =
0200       (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
0201    BOOST_STATIC_CONSTEXPR size_type  UnalignedFinalInternalBufferChars =
0202       (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
0203                 ZeroCostInternalBufferChars : MinInternalBufferChars;
0204 
0205    struct short_t
0206    {
0207       short_header   h;
0208       value_type     data[UnalignedFinalInternalBufferChars];
0209    };
0210 
0211    union repr_t_size_t
0212    {
0213       long_raw_t  r;
0214       short_t     s;
0215    };
0216 
0217    union repr_t
0218    {
0219       long_raw_t  r_aligner;
0220       short_t     s_aligner;
0221       unsigned char data[sizeof(repr_t_size_t)];
0222    };
0223 
0224    struct members_holder
0225       :  public allocator_type
0226    {
0227       inline void init()
0228       {
0229          short_t &s = *::new(&this->m_repr) short_t;
0230          s.h.is_short = 1;
0231          s.h.length = 0;
0232       }
0233 
0234       inline members_holder()
0235          : allocator_type()
0236       { this->init(); }
0237 
0238       template<class AllocatorConvertible>
0239       inline explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
0240          :  allocator_type(boost::forward<AllocatorConvertible>(a))
0241       { this->init(); }
0242 
0243       inline const short_t *pshort_repr() const
0244       {  return move_detail::launder_cast<const short_t*>(&m_repr);  }
0245 
0246       inline const long_t *plong_repr() const
0247       {  return move_detail::launder_cast<const long_t*>(&m_repr);  }
0248 
0249       inline short_t *pshort_repr()
0250       {  return move_detail::launder_cast<short_t*>(&m_repr);  }
0251 
0252       inline long_t *plong_repr()
0253       {  return move_detail::launder_cast<long_t*>(&m_repr);  }
0254 
0255       repr_t m_repr;
0256    } members_;
0257 
0258    inline const allocator_type &alloc() const
0259    {  return members_;  }
0260 
0261    inline allocator_type &alloc()
0262    {  return members_;  }
0263 
0264    BOOST_STATIC_CONSTEXPR size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
0265 
0266    private:
0267 
0268    BOOST_STATIC_CONSTEXPR size_type MinAllocation = InternalBufferChars*2;
0269 
0270    protected:
0271    inline bool is_short() const
0272    {
0273       //Access and copy (to avoid UB) the first byte of the union to know if the
0274       //active representation is short or long
0275       short_header hdr;
0276       BOOST_CONTAINER_STATIC_ASSERT((sizeof(short_header) == 1));
0277       *(unsigned char*)&hdr = *(unsigned char*)&this->members_.m_repr;
0278       return hdr.is_short != 0;
0279    }
0280 
0281    inline short_t *construct_short()
0282    {
0283       short_t *ps = ::new(&this->members_.m_repr) short_t;
0284       ps->h.is_short = 1;
0285       return ps;
0286    }
0287 
0288    inline void destroy_short()
0289    {
0290       BOOST_ASSERT(this->is_short());
0291       this->members_.pshort_repr()->~short_t();
0292    }
0293 
0294    short_t *assure_short()
0295    {
0296       if (!this->is_short()){
0297          this->destroy_long();
0298          return construct_short();
0299       }
0300       return this->members_.pshort_repr();
0301    }
0302 
0303    inline long_t *construct_long()
0304    {
0305       long_t *pl = ::new(&this->members_.m_repr) long_t;
0306       //is_short flag is written in the constructor
0307       return pl;
0308    }
0309 
0310    inline void destroy_long()
0311    {
0312       BOOST_ASSERT(!this->is_short());
0313       this->members_.plong_repr()->~long_t();
0314    }
0315 
0316    long_t *assure_long()
0317    {
0318       if (this->is_short()){
0319          this->destroy_short();
0320          return this->construct_long();
0321       }
0322       return this->members_.plong_repr();
0323    }
0324 
0325   
0326    protected:
0327 
0328    typedef dtl::integral_constant<unsigned,
0329       boost::container::dtl::version<allocator_type>::value> alloc_version;
0330 
0331    pointer allocation_command(allocation_type command,
0332                          size_type limit_size,
0333                          size_type &prefer_in_recvd_out_size,
0334                          pointer &reuse)
0335    {
0336       if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
0337          reuse = 0;
0338          command &= ~(expand_fwd | expand_bwd);
0339       }
0340       return dtl::allocator_version_traits<allocator_type>::allocation_command
0341          (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
0342    }
0343 
0344    size_type next_capacity(size_type additional_objects) const
0345    {
0346       return growth_factor_100()
0347             ( this->priv_storage(), additional_objects, allocator_traits_type::max_size(this->alloc()));
0348    }
0349 
0350    void deallocate(pointer p, size_type n)
0351    {
0352       if (p && (n > InternalBufferChars))
0353          this->alloc().deallocate(p, n);
0354    }
0355 
0356    void destroy(pointer p, size_type n)
0357    {
0358       value_type *raw_p = boost::movelib::to_raw_pointer(p);
0359       for(; n--; ++raw_p){
0360          allocator_traits_type::destroy( this->alloc(), raw_p);
0361       }
0362    }
0363 
0364    inline void destroy(pointer p)
0365    {
0366       allocator_traits_type::destroy
0367          ( this->alloc()
0368          , boost::movelib::to_raw_pointer(p)
0369          );
0370    }
0371 
0372    void allocate_initial_block(size_type n)
0373    {
0374       if (n <= this->max_size()) {
0375          if(n > InternalBufferChars){
0376             size_type new_cap = this->next_capacity(n);
0377             pointer reuse = 0;
0378             pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
0379             BOOST_ASSERT(this->is_short());
0380             this->construct_long();
0381             this->priv_long_addr(p);
0382             this->priv_long_size(0);
0383             this->priv_storage(new_cap);
0384          }
0385       }
0386       else{
0387          throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
0388       }
0389    }
0390 
0391    inline void deallocate_block()
0392    {  this->deallocate(this->priv_addr(), this->priv_storage());  }
0393 
0394    inline size_type max_size() const
0395    {  return allocator_traits_type::max_size(this->alloc()) - 1; }
0396 
0397    protected:
0398    inline size_type priv_capacity() const
0399    { return this->priv_storage() - 1; }
0400 
0401    inline pointer priv_short_addr() const
0402    {  return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.pshort_repr()->data[0]));  }
0403 
0404    //GCC seems a bit confused about uninitialized accesses
0405    #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0406    #pragma GCC diagnostic push
0407    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0408    #endif
0409 
0410    inline pointer priv_long_addr() const
0411    {  return this->members_.plong_repr()->start;  }
0412 
0413    inline pointer priv_addr() const
0414    {
0415       return this->is_short()
0416          ? priv_short_addr()
0417          : priv_long_addr()
0418          ;
0419    }
0420 
0421    inline pointer priv_end_addr() const
0422    {
0423       return this->is_short()
0424          ? this->priv_short_addr() + difference_type(this->priv_short_size())
0425          : this->priv_long_addr()  + difference_type(this->priv_long_size())
0426          ;
0427    }
0428 
0429    inline void priv_long_addr(pointer addr)
0430    {  this->members_.plong_repr()->start = addr;  }
0431 
0432    inline size_type priv_storage() const
0433    {  return this->is_short() ? priv_short_storage() : priv_long_storage();  }
0434 
0435    inline size_type priv_short_storage() const
0436    {  return InternalBufferChars;  }
0437 
0438    inline size_type priv_long_storage() const
0439    {  return this->members_.plong_repr()->storage;  }
0440 
0441    inline void priv_storage(size_type storage)
0442    {
0443       if(!this->is_short())
0444          this->priv_long_storage(storage);
0445    }
0446 
0447    inline void priv_long_storage(size_type storage)
0448    {
0449       this->members_.plong_repr()->storage = storage;
0450    }
0451 
0452    inline size_type priv_size() const
0453    {  return this->is_short() ? this->priv_short_size() : this->priv_long_size();  }
0454 
0455    inline size_type priv_short_size() const
0456    {  return this->members_.pshort_repr()->h.length;  }
0457 
0458    inline size_type priv_long_size() const
0459    {  return this->members_.plong_repr()->length;  }
0460 
0461    inline void priv_size(size_type sz)
0462    {
0463       if(this->is_short())
0464          this->priv_short_size(sz);
0465       else
0466          this->priv_long_size(sz);
0467    }
0468 
0469    inline void priv_short_size(size_type sz)
0470    {
0471       typedef unsigned char uchar_type;
0472       BOOST_STATIC_CONSTEXPR uchar_type mask = uchar_type(uchar_type(-1) >> 1U);
0473       BOOST_ASSERT( sz <= mask );
0474       //Make -Wconversion happy
0475       this->members_.pshort_repr()->h.length = uchar_type(uchar_type(sz) & mask);
0476    }
0477 
0478    inline void priv_long_size(size_type sz)
0479    {
0480       BOOST_STATIC_CONSTEXPR size_type mask = size_type(-1) >> 1U;
0481       BOOST_ASSERT( sz <= mask );
0482       //Make -Wconversion happy
0483       this->members_.plong_repr()->length = sz & mask;
0484    }
0485    #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0486    #pragma GCC diagnostic pop
0487    #endif
0488 
0489    void swap_data(basic_string_base& other)
0490    {
0491       if(this->is_short()){
0492          if(other.is_short()){
0493             repr_t tmp(this->members_.m_repr);
0494             this->members_.m_repr = other.members_.m_repr;
0495             other.members_.m_repr = tmp;
0496          }
0497          else{
0498             short_t short_backup(*this->members_.pshort_repr());
0499             this->members_.pshort_repr()->~short_t();
0500             ::new(this->members_.plong_repr()) long_t(*other.members_.plong_repr());
0501             other.members_.plong_repr()->~long_t();
0502             ::new(other.members_.pshort_repr()) short_t(short_backup);
0503          }
0504       }
0505       else{
0506          if(other.is_short()){
0507             short_t short_backup(*other.members_.pshort_repr());
0508             other.members_.pshort_repr()->~short_t();
0509             ::new(other.members_.plong_repr()) long_t(*this->members_.plong_repr());
0510             this->members_.plong_repr()->~long_t();
0511             ::new(this->members_.pshort_repr()) short_t(short_backup);
0512          }
0513          else{
0514             boost::adl_move_swap(*this->members_.plong_repr(), *other.members_.plong_repr());
0515          }
0516       }
0517    }
0518 };
0519 
0520 }  //namespace dtl {
0521 
0522 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0523 
0524 //! The basic_string class represents a Sequence of characters. It contains all the
0525 //! usual operations of a Sequence, and, additionally, it contains standard string
0526 //! operations such as search and concatenation.
0527 //!
0528 //! The basic_string class is parameterized by character type, and by that type's
0529 //! Character Traits.
0530 //!
0531 //! This class has performance characteristics very much like vector<>, meaning,
0532 //! for example, that it does not perform reference-count or copy-on-write, and that
0533 //! concatenation of two strings is an O(N) operation.
0534 //!
0535 //! Some of basic_string's member functions use an unusual method of specifying positions
0536 //! and ranges. In addition to the conventional method using iterators, many of
0537 //! basic_string's member functions use a single value pos of type size_type to represent a
0538 //! position (in which case the position is begin() + pos, and many of basic_string's
0539 //! member functions use two values, pos and n, to represent a range. In that case pos is
0540 //! the beginning of the range and n is its size. That is, the range is
0541 //! [begin() + pos, begin() + pos + n).
0542 //!
0543 //! Note that the C++ standard does not specify the complexity of basic_string operations.
0544 //! In this implementation, basic_string has performance characteristics very similar to
0545 //! those of vector: access to a single character is O(1), while copy and concatenation
0546 //! are O(N).
0547 //!
0548 //! In this implementation, begin(),
0549 //! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
0550 //! In this implementation, iterators are only invalidated by member functions that
0551 //! explicitly change the string's contents.
0552 //!
0553 //! \tparam CharT The type of character it contains.
0554 //! \tparam Traits The Character Traits type, which encapsulates basic character operations
0555 //! \tparam Allocator The allocator, used for internal memory management.
0556 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0557 template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = void >
0558 #else
0559 template <class CharT, class Traits, class Allocator>
0560 #endif
0561 class basic_string
0562    :  private dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type>
0563 {
0564    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0565    private:
0566    BOOST_COPYABLE_AND_MOVABLE(basic_string)
0567    typedef dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type> base_t;
0568    typedef typename base_t::allocator_traits_type allocator_traits_type;
0569    BOOST_STATIC_CONSTEXPR typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
0570 
0571    protected:
0572    // Allocator helper class to use a char_traits as a function object.
0573 
0574    template <class Tr>
0575    struct Eq_traits
0576    {
0577       //Compatibility with std::binary_function
0578       typedef typename Tr::char_type   first_argument_type;
0579       typedef typename Tr::char_type   second_argument_type;
0580       typedef bool   result_type;
0581 
0582       bool operator()(const first_argument_type& x, const second_argument_type& y) const
0583          { return Tr::eq(x, y); }
0584    };
0585 
0586    template <class Tr>
0587    struct Not_within_traits
0588    {
0589       typedef typename Tr::char_type   argument_type;
0590       typedef bool                     result_type;
0591 
0592       typedef const typename Tr::char_type* Pointer;
0593       const Pointer m_first;
0594       const Pointer m_last;
0595 
0596       Not_within_traits(Pointer f, Pointer l)
0597          : m_first(f), m_last(l) {}
0598 
0599       bool operator()(const typename Tr::char_type& x) const
0600       {
0601          return boost::container::find_if(m_first, m_last,
0602                         boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last;
0603       }
0604    };
0605    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0606 
0607    public:
0608    //////////////////////////////////////////////
0609    //
0610    //                    types
0611    //
0612    //////////////////////////////////////////////
0613    typedef Traits                                                                      traits_type;
0614    typedef CharT                                                                       value_type;
0615    typedef typename real_allocator<CharT, Allocator>::type                             allocator_type;
0616    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer           pointer;
0617    typedef typename ::boost::container::allocator_traits<allocator_type>::const_pointer     const_pointer;
0618    typedef typename ::boost::container::allocator_traits<allocator_type>::reference         reference;
0619    typedef typename ::boost::container::allocator_traits<allocator_type>::const_reference   const_reference;
0620    typedef typename ::boost::container::allocator_traits<allocator_type>::size_type         size_type;
0621    typedef typename ::boost::container::allocator_traits<allocator_type>::difference_type   difference_type;
0622    typedef BOOST_CONTAINER_IMPDEF(allocator_type)                                      stored_allocator_type;
0623    typedef BOOST_CONTAINER_IMPDEF(pointer)                                             iterator;
0624    typedef BOOST_CONTAINER_IMPDEF(const_pointer)                                       const_iterator;
0625    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
0626    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
0627    BOOST_STATIC_CONSTEXPR size_type npos = size_type(-1);
0628 
0629    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0630    private:
0631 
0632    //`allocator_type::value_type` must match container's `value type`. If this
0633    //assertion fails, please review your allocator definition. 
0634    BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<value_type, typename allocator_traits<allocator_type>::value_type>::value));
0635 
0636    typedef constant_iterator<CharT> cvalue_iterator;
0637    typedef typename base_t::alloc_version  alloc_version;
0638    typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
0639    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0640 
0641    public:                         // Constructor, destructor, assignment.
0642    //////////////////////////////////////////////
0643    //
0644    //          construct/copy/destroy
0645    //
0646    //////////////////////////////////////////////
0647    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0648    struct reserve_t {};
0649 
0650    basic_string(reserve_t, size_type n,
0651                 const allocator_type& a = allocator_type())
0652       //Select allocator as in copy constructor as reserve_t-based constructors
0653       //are two step copies optimized for capacity
0654       : base_t( allocator_traits_type::select_on_container_copy_construction(a)
0655               , n + 1)
0656    { this->priv_terminate_string(); }
0657 
0658    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0659 
0660    //! <b>Effects</b>: Default constructs a basic_string.
0661    //!
0662    //! <b>Throws</b>: If allocator_type's default constructor throws.
0663    basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0664       : base_t()
0665    { this->priv_terminate_string(); }
0666 
0667 
0668    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
0669    //!
0670    //! <b>Throws</b>: Nothing
0671    explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
0672       : base_t(a)
0673    { this->priv_terminate_string(); }
0674 
0675    //! <b>Effects</b>: Copy constructs a basic_string.
0676    //!
0677    //! <b>Postcondition</b>: x == *this.
0678    //!
0679    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
0680    basic_string(const basic_string& s)
0681       :  base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
0682    {
0683       this->priv_terminate_string();
0684       this->assign(s.begin(), s.end());
0685    }
0686 
0687    //! <b>Effects</b>: Same as basic_string(sv.data(), sv.size(), a).
0688    //!
0689    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
0690    template<template <class, class> class BasicStringView>
0691    explicit basic_string(BasicStringView<CharT, Traits> sv, const allocator_type& a = allocator_type())
0692       :  base_t(allocator_traits_type::select_on_container_copy_construction(a))
0693    {
0694       this->priv_terminate_string();
0695       this->assign(sv);
0696    }
0697 
0698    //! <b>Effects</b>: Move constructor. Moves s's resources to *this.
0699    //!
0700    //! <b>Throws</b>: Nothing.
0701    //!
0702    //! <b>Complexity</b>: Constant.
0703    basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
0704       : base_t(boost::move(s.alloc()))
0705    {
0706       if(s.alloc() == this->alloc()){
0707          this->swap_data(s);
0708       }
0709       else{
0710          this->assign(s.begin(), s.end());
0711       }
0712    }
0713 
0714    //! <b>Effects</b>: Copy constructs a basic_string using the specified allocator.
0715    //!
0716    //! <b>Postcondition</b>: x == *this.
0717    //!
0718    //! <b>Throws</b>: If allocation throws.
0719    basic_string(const basic_string& s, const allocator_type &a)
0720       :  base_t(a)
0721    {
0722       this->priv_terminate_string();
0723       this->assign(s.begin(), s.end());
0724    }
0725 
0726    //! <b>Effects</b>: Move constructor using the specified allocator.
0727    //!                 Moves s's resources to *this.
0728    //!
0729    //! <b>Throws</b>: If allocation throws.
0730    //!
0731    //! <b>Complexity</b>: Constant if a == s.get_allocator(), linear otherwise.
0732    basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
0733       : base_t(a)
0734    {
0735       this->priv_terminate_string();
0736       if(s.alloc() == this->alloc()){
0737          this->swap_data(s);
0738       }
0739       else{
0740          this->assign(s.begin(), s.end());
0741       }
0742    }
0743 
0744    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
0745    //!   and is initialized by a specific number of characters of the s string.
0746    basic_string(const basic_string& s, size_type pos, size_type n = npos)
0747       : base_t()
0748    {
0749       this->priv_terminate_string();
0750       if (pos > s.size())
0751          throw_out_of_range("basic_string::basic_string out of range position");
0752       else
0753          this->assign
0754             (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
0755    }
0756 
0757    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0758    //!   and is initialized by a specific number of characters of the s string.
0759    basic_string(const basic_string& s, size_type pos, size_type n, const allocator_type& a)
0760       : base_t(a)
0761    {
0762       this->priv_terminate_string();
0763       if (pos > s.size())
0764          throw_out_of_range("basic_string::basic_string out of range position");
0765       else
0766          this->assign
0767             (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
0768    }
0769 
0770    //! <b>Effects</b>: Constructs a basic_string taking a default-constructed allocator,
0771    //!   and is initialized by a specific number of characters of the s c-string.
0772    basic_string(const CharT* s, size_type n)
0773       : base_t()
0774    {
0775       this->priv_terminate_string();
0776       this->assign(s, s + difference_type(n));
0777    }
0778 
0779    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0780    //!   and is initialized by a specific number of characters of the s c-string.
0781    basic_string(const CharT* s, size_type n, const allocator_type& a)
0782       : base_t(a)
0783    {
0784       this->priv_terminate_string();
0785       this->assign(s, s + difference_type(n));
0786    }
0787 
0788    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
0789    //!   and is initialized by the null-terminated s c-string.
0790    basic_string(const CharT* s)
0791       : base_t()
0792    {
0793       this->priv_terminate_string();
0794       this->assign(s, s + Traits::length(s));
0795    }
0796 
0797    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0798    //!   and is initialized by the null-terminated s c-string.
0799    basic_string(const CharT* s, const allocator_type& a)
0800       : base_t(a)
0801    {
0802       this->priv_terminate_string();
0803       this->assign(s, s + Traits::length(s));
0804    }
0805 
0806 
0807    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
0808    //!   and is initialized by n copies of c.
0809    basic_string(size_type n, CharT c)
0810       : base_t()
0811    {
0812       this->priv_terminate_string();
0813       this->assign(n, c);
0814    }
0815 
0816    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0817    //!   and is initialized by n copies of c.
0818    basic_string(size_type n, CharT c, const allocator_type& a)
0819       : base_t(a)
0820    {
0821       this->priv_terminate_string();
0822       this->assign(n, c);
0823    }
0824 
0825    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
0826    //!   and is initialized by n default-initialized characters.
0827    basic_string(size_type n, default_init_t)
0828       : base_t(n + 1)
0829    {
0830       this->priv_size(n);
0831       this->priv_terminate_string();
0832    }
0833 
0834    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0835    //!   and is initialized by n default-initialized characters.
0836    basic_string(size_type n, default_init_t, const allocator_type& a)
0837       : base_t(a, n + 1)
0838    {
0839       this->priv_size(n);
0840       this->priv_terminate_string();
0841    }
0842 
0843    //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
0844    //!   and a range of iterators.
0845    template <class InputIterator>
0846    basic_string(InputIterator f, InputIterator l)
0847       : base_t()
0848    {
0849       this->priv_terminate_string();
0850       this->assign(f, l);
0851    }
0852 
0853    //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
0854    //!   and a range of iterators.
0855    template <class InputIterator>
0856    basic_string(InputIterator f, InputIterator l, const allocator_type& a)
0857       : base_t(a)
0858    {
0859       this->priv_terminate_string();
0860       this->assign(f, l);
0861    }
0862 
0863    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0864    //! <b>Effects</b>: Same as basic_string(il.begin(), il.end(), a).
0865    //!
0866    basic_string(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
0867       : base_t(a)
0868    {
0869       this->priv_terminate_string();
0870       this->assign(il.begin(), il.end());
0871    }
0872    #endif
0873 
0874    //! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
0875    //!
0876    //! <b>Throws</b>: Nothing.
0877    //!
0878    //! <b>Complexity</b>: Constant.
0879    ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW
0880    {}
0881 
0882    //! <b>Effects</b>: Copy constructs a string.
0883    //!
0884    //! <b>Postcondition</b>: x == *this.
0885    //!
0886    //! <b>Complexity</b>: Linear to the elements x contains.
0887    basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
0888    {
0889       if (BOOST_LIKELY(this != &x)) {
0890          allocator_type &this_alloc     = this->alloc();
0891          const allocator_type &x_alloc  = x.alloc();
0892          dtl::bool_<allocator_traits_type::
0893             propagate_on_container_copy_assignment::value> flag;
0894          if(flag && this_alloc != x_alloc){
0895             if(!this->is_short()){
0896                this->deallocate_block();
0897                this->assure_short();
0898                Traits::assign(*this->priv_addr(), CharT(0));
0899                this->priv_short_size(0);
0900             }
0901          }
0902          dtl::assign_alloc(this->alloc(), x.alloc(), flag);
0903          this->assign(x.begin(), x.end());
0904       }
0905       return *this;
0906    }
0907 
0908    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
0909    //!
0910    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
0911    //!   is false and allocation throws
0912    //!
0913    //! <b>Complexity</b>: Constant if allocator_traits_type::
0914    //!   propagate_on_container_move_assignment is true or
0915    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
0916    basic_string& operator=(BOOST_RV_REF(basic_string) x)
0917       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
0918                                   || allocator_traits_type::is_always_equal::value)
0919    {
0920       if (BOOST_LIKELY(this != &x)) {
0921          //We know resources can be transferred at comiple time if both allocators are
0922          //always equal or the allocator is going to be propagated
0923          const bool can_steal_resources_alloc
0924             =  allocator_traits_type::propagate_on_container_move_assignment::value
0925             || allocator_traits_type::is_always_equal::value;
0926          dtl::bool_<can_steal_resources_alloc> flag;
0927          this->priv_move_assign(boost::move(x), flag);
0928       }
0929       return *this;
0930    }
0931 
0932    //! <b>Effects</b>: Assignment from a null-terminated c-string.
0933    //!
0934    basic_string& operator=(const CharT* s)
0935    { return this->assign(s, s + Traits::length(s)); }
0936 
0937    //! <b>Effects</b>: Returns *this = basic_string(1, c).
0938    //!
0939    basic_string& operator=(CharT c)
0940    { return this->assign(static_cast<size_type>(1), c); }
0941 
0942    //! <b>Effects</b>: Equivalent to return assign(sv).
0943    //!
0944    template<template <class, class> class BasicStringView>
0945    basic_string& operator=(BasicStringView<CharT, Traits> sv)
0946    { return this->assign(sv.data(), sv.size()); }
0947 
0948    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0949    //! <b>Effects</b>: Returns *this = basic_string(il);
0950    //!
0951    basic_string& operator=(std::initializer_list<CharT> il)
0952    {
0953       return this->assign(il.begin(), il.end());
0954    }
0955    #endif
0956 
0957    //! <b>Effects</b>: Returns a copy of the internal allocator.
0958    //!
0959    //! <b>Throws</b>: If allocator's copy constructor throws.
0960    //!
0961    //! <b>Complexity</b>: Constant.
0962    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0963       allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0964    { return this->alloc(); }
0965 
0966    //! <b>Effects</b>: Returns a reference to the internal allocator.
0967    //!
0968    //! <b>Throws</b>: Nothing
0969    //!
0970    //! <b>Complexity</b>: Constant.
0971    //!
0972    //! <b>Note</b>: Non-standard extension.
0973    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0974       stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
0975    {  return this->alloc(); }
0976 
0977    //! <b>Effects</b>: Returns a reference to the internal allocator.
0978    //!
0979    //! <b>Throws</b>: Nothing
0980    //!
0981    //! <b>Complexity</b>: Constant.
0982    //!
0983    //! <b>Note</b>: Non-standard extension.
0984    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0985       const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0986    {  return this->alloc(); }
0987 
0988    //////////////////////////////////////////////
0989    //
0990    //                iterators
0991    //
0992    //////////////////////////////////////////////
0993 
0994    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
0995    //!
0996    //! <b>Throws</b>: Nothing.
0997    //!
0998    //! <b>Complexity</b>: Constant.
0999    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1000       iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1001    { return this->priv_addr(); }
1002 
1003    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1004    //!
1005    //! <b>Throws</b>: Nothing.
1006    //!
1007    //! <b>Complexity</b>: Constant.
1008    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1009       const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1010    { return this->priv_addr(); }
1011 
1012    //! <b>Effects</b>: Returns an iterator to the end of the vector.
1013    //!
1014    //! <b>Throws</b>: Nothing.
1015    //!
1016    //! <b>Complexity</b>: Constant.
1017    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1018       iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1019    { return this->priv_end_addr(); }
1020 
1021    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1022    //!
1023    //! <b>Throws</b>: Nothing.
1024    //!
1025    //! <b>Complexity</b>: Constant.
1026    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1027       const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1028    { return this->priv_end_addr(); }
1029 
1030    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1031    //! of the reversed vector.
1032    //!
1033    //! <b>Throws</b>: Nothing.
1034    //!
1035    //! <b>Complexity</b>: Constant.
1036    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1037       reverse_iterator rbegin()  BOOST_NOEXCEPT_OR_NOTHROW
1038    { return reverse_iterator(this->priv_end_addr()); }
1039 
1040    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1041    //! of the reversed vector.
1042    //!
1043    //! <b>Throws</b>: Nothing.
1044    //!
1045    //! <b>Complexity</b>: Constant.
1046    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1047       const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1048    { return this->crbegin(); }
1049 
1050    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1051    //! of the reversed vector.
1052    //!
1053    //! <b>Throws</b>: Nothing.
1054    //!
1055    //! <b>Complexity</b>: Constant.
1056    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1057       reverse_iterator rend()  BOOST_NOEXCEPT_OR_NOTHROW
1058    { return reverse_iterator(this->priv_addr()); }
1059 
1060    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1061    //! of the reversed vector.
1062    //!
1063    //! <b>Throws</b>: Nothing.
1064    //!
1065    //! <b>Complexity</b>: Constant.
1066    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1067       const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1068    { return this->crend(); }
1069 
1070    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1071    //!
1072    //! <b>Throws</b>: Nothing.
1073    //!
1074    //! <b>Complexity</b>: Constant.
1075    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1076       const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1077    { return this->priv_addr(); }
1078 
1079    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1080    //!
1081    //! <b>Throws</b>: Nothing.
1082    //!
1083    //! <b>Complexity</b>: Constant.
1084    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1085       const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1086    { return this->priv_end_addr(); }
1087 
1088    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1089    //! of the reversed vector.
1090    //!
1091    //! <b>Throws</b>: Nothing.
1092    //!
1093    //! <b>Complexity</b>: Constant.
1094    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1095       const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1096    { return const_reverse_iterator(this->priv_end_addr()); }
1097 
1098    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1099    //! of the reversed vector.
1100    //!
1101    //! <b>Throws</b>: Nothing.
1102    //!
1103    //! <b>Complexity</b>: Constant.
1104    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1105       const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1106    { return const_reverse_iterator(this->priv_addr()); }
1107 
1108    //////////////////////////////////////////////
1109    //
1110    //                capacity
1111    //
1112    //////////////////////////////////////////////
1113 
1114    //! <b>Effects</b>: Returns true if the vector contains no elements.
1115    //!
1116    //! <b>Throws</b>: Nothing.
1117    //!
1118    //! <b>Complexity</b>: Constant.
1119    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1120       bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1121    { return !this->priv_size(); }
1122 
1123    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1124    //!
1125    //! <b>Throws</b>: Nothing.
1126    //!
1127    //! <b>Complexity</b>: Constant.
1128    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1129       size_type size() const    BOOST_NOEXCEPT_OR_NOTHROW
1130    { return this->priv_size(); }
1131 
1132    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1133    //!
1134    //! <b>Throws</b>: Nothing.
1135    //!
1136    //! <b>Complexity</b>: Constant.
1137    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1138       size_type length() const BOOST_NOEXCEPT_OR_NOTHROW
1139    { return this->size(); }
1140 
1141    //! <b>Effects</b>: Returns the largest possible size of the vector.
1142    //!
1143    //! <b>Throws</b>: Nothing.
1144    //!
1145    //! <b>Complexity</b>: Constant
1146    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1147       size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1148    { return base_t::max_size(); }
1149 
1150    //! <b>Effects</b>: Inserts or erases elements at the end such that
1151    //!   the size becomes n. New elements are copy constructed from x.
1152    //!
1153    //! <b>Throws</b>: If memory allocation throws
1154    //!
1155    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1156    void resize(size_type n, CharT c)
1157    {
1158       if (n <= this->size())
1159          this->erase(this->begin() + difference_type(n), this->end());
1160       else
1161          this->append(n - this->size(), c);
1162    }
1163 
1164    //! <b>Effects</b>: Inserts or erases elements at the end such that
1165    //!   the size becomes n. New elements are value initialized.
1166    //!
1167    //! <b>Throws</b>: If memory allocation throws
1168    //!
1169    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1170    void resize(size_type n)
1171    { resize(n, CharT()); }
1172 
1173    //! <b>Effects</b>: Inserts or erases elements at the end such that
1174    //!   the size becomes n. New elements are uninitialized.
1175    //!
1176    //! <b>Throws</b>: If memory allocation throws
1177    //!
1178    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1179    //!
1180    //! <b>Note</b>: Non-standard extension
1181    void resize(size_type n, default_init_t)
1182    {
1183       if (n <= this->size())
1184          this->erase(this->begin() + difference_type(n), this->end());
1185       else{
1186          this->priv_reserve_no_null_end(n);
1187          this->priv_size(n);
1188          this->priv_terminate_string();
1189       }
1190    }
1191 
1192    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1193    //!   capacity() is always greater than or equal to size().
1194    //!
1195    //! <b>Throws</b>: Nothing.
1196    //!
1197    //! <b>Complexity</b>: Constant.
1198    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1199       size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1200    { return this->priv_capacity(); }
1201 
1202    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1203    //!   effect. Otherwise, it is a request for allocation of additional memory.
1204    //!   If the request is successful, then capacity() is greater than or equal to
1205    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1206    //!
1207    //! <b>Throws</b>: If memory allocation allocation throws
1208    void reserve(size_type res_arg)
1209    {  this->priv_reserve(res_arg);  }
1210 
1211    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1212    //!   with previous allocations. The size of the string is unchanged
1213    //!
1214    //! <b>Throws</b>: Nothing
1215    //!
1216    //! <b>Complexity</b>: Linear to size().
1217    void shrink_to_fit()
1218    {
1219       //Check if shrinking is possible
1220       if(this->priv_storage() > InternalBufferChars){
1221          //Check if we should pass from dynamically allocated buffer
1222          //to the internal storage
1223          if(this->priv_size() < InternalBufferChars){
1224             //Dynamically allocated buffer attributes
1225             pointer   long_addr    = this->priv_long_addr();
1226             size_type long_storage = this->priv_long_storage();
1227             size_type long_size    = this->priv_long_size();
1228             //Shrink from allocated buffer to the internal one, including trailing null
1229             Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
1230                         , boost::movelib::to_raw_pointer(long_addr)
1231                         , long_size+1);
1232             BOOST_ASSERT(!this->is_short());
1233             this->destroy_long();
1234             this->construct_short();
1235             this->alloc().deallocate(long_addr, long_storage);
1236          }
1237          else{
1238             //Shrinking in dynamic buffer
1239             this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
1240          }
1241       }
1242    }
1243 
1244    //////////////////////////////////////////////
1245    //
1246    //               element access
1247    //
1248    //////////////////////////////////////////////
1249 
1250    //! <b>Requires</b>: !empty()
1251    //!
1252    //! <b>Effects</b>: Returns a reference to the first
1253    //!   element of the container.
1254    //!
1255    //! <b>Throws</b>: Nothing.
1256    //!
1257    //! <b>Complexity</b>: Constant.
1258    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1259       reference         front() BOOST_NOEXCEPT_OR_NOTHROW
1260    {
1261       BOOST_ASSERT(!this->empty());
1262       return *this->priv_addr();
1263    }
1264 
1265    //! <b>Requires</b>: !empty()
1266    //!
1267    //! <b>Effects</b>: Returns a const reference to the first
1268    //!   element of the container.
1269    //!
1270    //! <b>Throws</b>: Nothing.
1271    //!
1272    //! <b>Complexity</b>: Constant.
1273    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1274       const_reference   front() const BOOST_NOEXCEPT_OR_NOTHROW
1275    {
1276       BOOST_ASSERT(!this->empty());
1277       return *this->priv_addr();
1278    }
1279 
1280    //! <b>Requires</b>: !empty()
1281    //!
1282    //! <b>Effects</b>: Returns a reference to the last
1283    //!   element of the container.
1284    //!
1285    //! <b>Throws</b>: Nothing.
1286    //!
1287    //! <b>Complexity</b>: Constant.
1288    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1289       reference         back() BOOST_NOEXCEPT_OR_NOTHROW
1290    {
1291       BOOST_ASSERT(!this->empty());
1292       return *(this->priv_addr() + (this->size() - 1u) );
1293    }
1294 
1295    //! <b>Requires</b>: !empty()
1296    //!
1297    //! <b>Effects</b>: Returns a const reference to the last
1298    //!   element of the container.
1299    //!
1300    //! <b>Throws</b>: Nothing.
1301    //!
1302    //! <b>Complexity</b>: Constant.
1303    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1304       const_reference   back()  const BOOST_NOEXCEPT_OR_NOTHROW
1305    {
1306       BOOST_ASSERT(!this->empty());
1307       return *(this->priv_addr() + (this->size() - 1u) );
1308    }
1309 
1310    //! <b>Requires</b>: size() > n.
1311    //!
1312    //! <b>Effects</b>: Returns a reference to the nth element
1313    //!   from the beginning of the container.
1314    //!
1315    //! <b>Throws</b>: Nothing.
1316    //!
1317    //! <b>Complexity</b>: Constant.
1318    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1319       reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1320    {
1321       BOOST_ASSERT(this->size() > n);
1322       return *(this->priv_addr() + difference_type(n));
1323    }
1324 
1325    //! <b>Requires</b>: size() > n.
1326    //!
1327    //! <b>Effects</b>: Returns a const reference to the nth element
1328    //!   from the beginning of the container.
1329    //!
1330    //! <b>Throws</b>: Nothing.
1331    //!
1332    //! <b>Complexity</b>: Constant.
1333    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1334       const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1335    {
1336       BOOST_ASSERT(this->size() > n);
1337       return *(this->priv_addr() + difference_type(n));
1338    }
1339 
1340    //! <b>Requires</b>: size() > n.
1341    //!
1342    //! <b>Effects</b>: Returns a reference to the nth element
1343    //!   from the beginning of the container.
1344    //!
1345    //! <b>Throws</b>: range_error if n >= size()
1346    //!
1347    //! <b>Complexity</b>: Constant.
1348    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1349       reference at(size_type n)
1350    {
1351       if (n >= this->size())
1352          throw_out_of_range("basic_string::at invalid subscript");
1353       return *(this->priv_addr() + difference_type(n));
1354    }
1355 
1356    //! <b>Requires</b>: size() > n.
1357    //!
1358    //! <b>Effects</b>: Returns a const reference to the nth element
1359    //!   from the beginning of the container.
1360    //!
1361    //! <b>Throws</b>: range_error if n >= size()
1362    //!
1363    //! <b>Complexity</b>: Constant.
1364    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1365       const_reference at(size_type n) const {
1366       if (n >= this->size())
1367          throw_out_of_range("basic_string::at invalid subscript");
1368       return *(this->priv_addr() + difference_type(n));
1369    }
1370 
1371    //////////////////////////////////////////////
1372    //
1373    //                modifiers
1374    //
1375    //////////////////////////////////////////////
1376 
1377    //! <b>Effects</b>: Calls append(str.data, str.size()).
1378    //!
1379    //! <b>Returns</b>: *this
1380    basic_string& operator+=(const basic_string& s)
1381    {  return this->append(s); }
1382 
1383    //! <b>Effects</b>: Same as `return append(sv)`.
1384    //!
1385    template<template<class, class> class BasicStringView>
1386    basic_string& operator+=(BasicStringView<CharT, Traits> sv)
1387    {
1388       return this->append(sv);
1389    }
1390 
1391    //! <b>Effects</b>: Calls append(s).
1392    //!
1393    //! <b>Returns</b>: *this
1394    basic_string& operator+=(const CharT* s)
1395    {  return this->append(s); }
1396 
1397    //! <b>Effects</b>: Calls append(1, c).
1398    //!
1399    //! <b>Returns</b>: *this
1400    basic_string& operator+=(CharT c)
1401    {  this->push_back(c); return *this;   }
1402 
1403    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1404    //! <b>Effects</b>: Returns append(il)
1405    //!
1406    basic_string& operator+=(std::initializer_list<CharT> il)
1407    {
1408       return this->append(il);
1409    }
1410    #endif
1411 
1412    //! <b>Effects</b>: Calls append(str.data(), str.size()).
1413    //!
1414    //! <b>Returns</b>: *this
1415    basic_string& append(const basic_string& s)
1416    {  return this->append(s.begin(), s.end());  }
1417 
1418    //! <b>Effects</b>: Same as return append(sv.data(), sv.size()).
1419    //!
1420    template<template<class, class> class BasicStringView>
1421    basic_string& append(BasicStringView<CharT, Traits> sv)
1422    {  return this->append(sv.data(), sv.size());  }
1423 
1424    //! <b>Requires</b>: pos <= str.size()
1425    //!
1426    //! <b>Effects</b>: Determines the effective length rlen of the string to append
1427    //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen).
1428    //!
1429    //! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
1430    //!
1431    //! <b>Returns</b>: *this
1432    basic_string& append(const basic_string& s, size_type pos, size_type n = npos)
1433    {
1434       if (pos > s.size())
1435          throw_out_of_range("basic_string::append out of range position");
1436       return this->append(s.begin() + pos,
1437                           s.begin() + pos + dtl::min_value(n, s.size() - pos));
1438    }
1439 
1440    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1441    //!
1442    //! <b>Effects</b>: The function replaces the string controlled by *this with
1443    //!   a string of length size() + n whose irst size() elements are a copy of the
1444    //!   original string controlled by *this and whose remaining
1445    //!   elements are a copy of the initial n elements of s.
1446    //!
1447    //! <b>Throws</b>: If memory allocation throws length_error if size() + n > max_size().
1448    //!
1449    //! <b>Returns</b>: *this
1450    basic_string& append(const CharT* s, size_type n)
1451    {  return this->append(s, s + difference_type(n));  }
1452 
1453    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1454    //!
1455    //! <b>Effects</b>: Calls append(s, traits::length(s)).
1456    //!
1457    //! <b>Returns</b>: *this
1458    basic_string& append(const CharT* s)
1459    {  return this->append(s, s + Traits::length(s));  }
1460 
1461    //! <b>Effects</b>: Equivalent to append(basic_string(n, c)).
1462    //!
1463    //! <b>Returns</b>: *this
1464    basic_string& append(size_type n, CharT c)
1465    {  return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
1466 
1467    //! <b>Requires</b>: [first,last) is a valid range.
1468    //!
1469    //! <b>Effects</b>: Equivalent to append(basic_string(first, last)).
1470    //!
1471    //! <b>Returns</b>: *this
1472    template <class InputIter>
1473    basic_string& append(InputIter first, InputIter last)
1474    {  this->insert(this->end(), first, last);   return *this;  }
1475 
1476    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1477    //! <b>Effects</b>: Returns append(il.begin(), il.size()).
1478    //!
1479    basic_string& append(std::initializer_list<CharT> il)
1480    {
1481       return this->append(il.begin(), il.size());
1482    }
1483    #endif
1484 
1485    //! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
1486    //!
1487    void push_back(CharT c)
1488    {
1489       const size_type old_size = this->priv_size();
1490       if (old_size < this->capacity()){
1491          const pointer addr = this->priv_addr();
1492          this->priv_construct_null(addr + difference_type(old_size + 1u));
1493          Traits::assign(addr[difference_type(old_size)], c);
1494          this->priv_size(old_size+1u);
1495       }
1496       else{
1497          //No enough memory, insert a new object at the end
1498          this->append(size_type(1), c);
1499       }
1500    }
1501 
1502    //! <b>Effects</b>: Equivalent to assign(str, 0, npos).
1503    //!
1504    //! <b>Returns</b>: *this
1505    basic_string& assign(const basic_string& s)
1506    {  return this->operator=(s); }
1507 
1508    //! <b>Effects</b>: Equivalent to return assign(sv.data(), sv.size()).
1509    //!
1510    //! <b>Returns</b>: *this
1511    template<template <class, class> class BasicStringView>
1512    basic_string& assign(BasicStringView<CharT, Traits> sv)
1513    {  return this->operator=(sv); }
1514 
1515    //! <b>Effects</b>: The function replaces the string controlled by *this
1516    //!    with a string of length str.size() whose elements are a copy of the string
1517    //!   controlled by str. Leaves str in a valid but unspecified state.
1518    //!
1519    //! <b>Throws</b>: Nothing
1520    //!
1521    //! <b>Returns</b>: *this
1522    basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
1523    {  return this->swap_data(ms), *this;  }
1524 
1525    //! <b>Requires</b>: pos <= str.size()
1526    //!
1527    //! <b>Effects</b>: Determines the effective length rlen of the string to assign as
1528    //!   the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen).
1529    //!
1530    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
1531    //!
1532    //! <b>Returns</b>: *this
1533    basic_string& assign(const basic_string& s, size_type pos, size_type n)
1534    {
1535       if (pos > s.size())
1536          throw_out_of_range("basic_string::assign out of range position");
1537       return this->assign(s.begin() + pos,
1538                           s.begin() + pos + dtl::min_value(n, s.size() - pos));
1539    }
1540 
1541    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
1542    //!
1543    //! <b>Effects</b>: Replaces the string controlled by *this with a string of
1544    //! length n whose elements are a copy of those pointed to by s.
1545    //!
1546    //! <b>Throws</b>: If memory allocation throws or length_error if n > max_size().
1547    //!
1548    //! <b>Returns</b>: *this
1549    basic_string& assign(const CharT* s, size_type n)
1550    {  return this->assign(s, s + difference_type(n));   }
1551 
1552    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
1553    //!
1554    //! <b>Effects</b>: Calls assign(s, traits::length(s)).
1555    //!
1556    //! <b>Returns</b>: *this
1557    basic_string& assign(const CharT* s)
1558    { return this->assign(s, s + Traits::length(s)); }
1559 
1560    //! <b>Effects</b>: Equivalent to assign(basic_string(n, c)).
1561    //!
1562    //! <b>Returns</b>: *this
1563    basic_string& assign(size_type n, CharT c)
1564    {  return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
1565 
1566    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1567     //!
1568     //! <b>Returns</b>: *this
1569     basic_string& assign(const CharT* first, const CharT* last)
1570     {
1571        size_type n = static_cast<size_type>(last - first);
1572        this->reserve(n);
1573        CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr());
1574        Traits::copy(ptr, first, n);
1575        this->priv_construct_null(ptr + difference_type(n));
1576        this->priv_size(n);
1577        return *this;
1578     }
1579 
1580    //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
1581    //!
1582    //! <b>Returns</b>: *this
1583    template <class InputIter>
1584    basic_string& assign(InputIter first, InputIter last
1585       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1586       , typename dtl::disable_if_convertible<InputIter, size_type>::type * = 0
1587       #endif
1588       )
1589    {
1590       size_type cur = 0;
1591       const pointer addr = this->priv_addr();
1592       CharT *ptr = boost::movelib::to_raw_pointer(addr);
1593       const size_type old_size = this->priv_size();
1594       while (first != last && cur != old_size) {
1595          Traits::assign(*ptr, *first);
1596          ++first;
1597          ++cur;
1598          ++ptr;
1599       }
1600       if (first == last)
1601          this->erase(addr + difference_type(cur), addr + difference_type(old_size));
1602       else
1603          this->append(first, last);
1604       return *this;
1605    }
1606 
1607    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1608    //! <b>Effects</b>: Returns assign(il.begin(), il.size()).
1609    //!
1610    basic_string& assign(std::initializer_list<CharT> il)
1611    {
1612       return this->assign(il.begin(), il.size());
1613    }
1614    #endif
1615 
1616    //! <b>Requires</b>: pos <= size().
1617    //!
1618    //! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
1619    //!
1620    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
1621    //!
1622    //! <b>Returns</b>: *this
1623    basic_string& insert(size_type pos, const basic_string& s)
1624    {
1625       const size_type sz = this->size();
1626       if (pos > sz)
1627          throw_out_of_range("basic_string::insert out of range position");
1628       if (sz > this->max_size() - s.size())
1629          throw_length_error("basic_string::insert max_size() exceeded");
1630       this->insert(this->priv_addr() + pos, s.begin(), s.end());
1631       return *this;
1632    }
1633 
1634    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
1635    //!
1636    //! <b>Effects</b>: Determines the effective length rlen of the string to insert as
1637    //!   the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen).
1638    //!
1639    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
1640    //!
1641    //! <b>Returns</b>: *this
1642    basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n = npos)
1643    {
1644       const size_type sz = this->size();
1645       const size_type str_size = s.size();
1646       if (pos1 > sz || pos2 > str_size)
1647          throw_out_of_range("basic_string::insert out of range position");
1648       size_type len = dtl::min_value(n, str_size - pos2);
1649       if (sz > this->max_size() - len)
1650          throw_length_error("basic_string::insert max_size() exceeded");
1651       const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2;
1652       const CharT *end_ptr = beg_ptr + len;
1653       this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
1654       return *this;
1655    }
1656 
1657    //! <b>Requires</b>: s points to an array of at least n elements of CharT and pos <= size().
1658    //!
1659    //! <b>Effects</b>: Replaces the string controlled by *this with a string of length size() + n
1660    //!   whose first pos elements are a copy of the initial elements of the original string
1661    //!   controlled by *this and whose next n elements are a copy of the elements in s and whose
1662    //!   remaining elements are a copy of the remaining elements of the original string controlled by *this.
1663    //!
1664    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size() or
1665    //!   length_error if size() + n > max_size().
1666    //!
1667    //! <b>Returns</b>: *this
1668    basic_string& insert(size_type pos, const CharT* s, size_type n)
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(this->priv_addr() + pos, s, s + difference_type(n));
1675       return *this;
1676    }
1677 
1678    //! <b>Requires</b>: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT
1679    //!
1680    //! <b>Effects</b>: Calls insert(pos, s, traits::length(s)).
1681    //!
1682    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1683    //!   length_error if size() > max_size() - Traits::length(s)
1684    //!
1685    //! <b>Returns</b>: *this
1686    basic_string& insert(size_type pos, const CharT* s)
1687    {
1688       if (pos > this->size())
1689          throw_out_of_range("basic_string::insert out of range position");
1690       size_type len = Traits::length(s);
1691       if (this->size() > this->max_size() - len)
1692          throw_length_error("basic_string::insert max_size() exceeded");
1693       this->insert(this->priv_addr() + pos, s, s + len);
1694       return *this;
1695    }
1696 
1697    //! <b>Effects</b>: Equivalent to insert(pos, basic_string(n, c)).
1698    //!
1699    //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
1700    //!   length_error if size() > max_size() - n
1701    //!
1702    //! <b>Returns</b>: *this
1703    basic_string& insert(size_type pos, size_type n, CharT c)
1704    {
1705       if (pos > this->size())
1706          throw_out_of_range("basic_string::insert out of range position");
1707       if (this->size() > this->max_size() - n)
1708          throw_length_error("basic_string::insert max_size() exceeded");
1709       this->insert(const_iterator(this->priv_addr() + pos), n, c);
1710       return *this;
1711    }
1712 
1713    //! <b>Effects</b>: Same as `return insert(pos, sv.data(), sv.size())`.
1714    //!
1715    template<template<class, class> class BasicStringView>
1716    basic_string& insert(size_type pos, BasicStringView<CharT, Traits> sv)
1717    {  return this->insert(pos, sv.data(), sv.size());  }
1718 
1719    //! <b>Requires</b>: p is a valid iterator on *this.
1720    //!
1721    //! <b>Effects</b>: inserts a copy of c before the character referred to by p.
1722    //!
1723    //! <b>Returns</b>: An iterator which refers to the copy of the inserted character.
1724    iterator insert(const_iterator p, CharT c)
1725    {
1726       size_type new_offset = size_type(p - this->priv_addr());
1727       this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
1728       return this->priv_addr() + new_offset;
1729    }
1730 
1731    //! <b>Requires</b>: p is a valid iterator on *this.
1732    //!
1733    //! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
1734    //!
1735    //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
1736    iterator insert(const_iterator p, size_type n, CharT c)
1737    {  return this->insert(p, cvalue_iterator(c, n), cvalue_iterator());  }
1738 
1739    //! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
1740    //!
1741    //! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
1742    //!
1743    //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
1744    template <class InputIter>
1745    iterator insert(const_iterator p, InputIter first, InputIter last
1746       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1747       , typename dtl::disable_if_or
1748          < void
1749          , dtl::is_convertible<InputIter, size_type>
1750          , dtl::is_not_input_iterator<InputIter>
1751          >::type * = 0
1752       #endif
1753       )
1754    {
1755       const size_type n_pos = p - this->cbegin();
1756       for ( ; first != last; ++first, ++p) {
1757          p = this->insert(p, *first);
1758       }
1759       return this->begin() + difference_type(n_pos);
1760    }
1761 
1762    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1763    template <class ForwardIter>
1764    iterator insert(const_iterator p, ForwardIter first, ForwardIter last
1765       , typename dtl::disable_if_or
1766          < void
1767          , dtl::is_convertible<ForwardIter, size_type>
1768          , dtl::is_input_iterator<ForwardIter>
1769          >::type * = 0
1770       )
1771    {
1772       const size_type n_pos = size_type(p - this->cbegin());
1773       if (first != last) {
1774          const size_type n = boost::container::iterator_udistance(first, last);
1775          const size_type old_size = this->priv_size();
1776          const size_type remaining = this->capacity() - old_size;
1777          const pointer old_start = this->priv_addr();
1778          bool enough_capacity = false;
1779          size_type new_cap = 0;
1780 
1781          //Check if we have enough capacity
1782          pointer hint = pointer();
1783          pointer allocation_ret = pointer();
1784          if (remaining >= n){
1785             enough_capacity = true;
1786          }
1787          else {
1788             //Otherwise expand current buffer or allocate new storage
1789             new_cap  = this->next_capacity(n);
1790             hint = old_start;
1791             allocation_ret = this->allocation_command
1792                   (allocate_new | expand_fwd | expand_bwd, old_size + n + 1u, new_cap, hint);
1793 
1794             //Check forward expansion
1795             if(old_start == allocation_ret){
1796                enough_capacity = true;
1797                this->priv_storage(new_cap);
1798             }
1799          }
1800 
1801          //Reuse same buffer
1802          if(enough_capacity){
1803             const size_type elems_after = old_size - size_type(p - old_start);
1804             const size_type old_length = old_size;
1805             size_type new_size = 0;
1806             if (elems_after >= n) {
1807                const pointer pointer_past_last = old_start + difference_type(old_size + 1u);
1808                priv_uninitialized_copy(old_start + difference_type(old_size - n + 1u),
1809                                        pointer_past_last, pointer_past_last);
1810 
1811                Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + difference_type(n))),
1812                            boost::movelib::to_raw_pointer(p),
1813                            (elems_after - n) + 1u);
1814                (priv_copy)(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1815                new_size = old_size + n;
1816             }
1817             else {
1818                ForwardIter mid = first;
1819                boost::container::iterator_uadvance(mid, elems_after + 1u);
1820 
1821                priv_uninitialized_copy(mid, last, old_start + difference_type(old_size + 1u));
1822                const size_type newer_size = old_size + (n - elems_after);
1823                this->priv_size(newer_size);
1824                priv_uninitialized_copy
1825                   (p, const_iterator(old_start + difference_type(old_length + 1u)),
1826                   old_start + difference_type(newer_size));
1827                (priv_copy)(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
1828                new_size = newer_size + elems_after;
1829             }
1830             this->priv_size(new_size);
1831             this->priv_construct_null(old_start + difference_type(new_size));
1832          }
1833          else{
1834             pointer new_start = allocation_ret;
1835             if(!hint){
1836                //Copy data to new buffer
1837                size_type new_length = 0;
1838                //This can't throw, since characters are POD
1839                new_length += priv_uninitialized_copy
1840                               (const_iterator(old_start), p, new_start);
1841                new_length += priv_uninitialized_copy
1842                               (first, last, new_start + difference_type(new_length));
1843                new_length += priv_uninitialized_copy
1844                               (p, const_iterator(old_start + difference_type(old_size)),
1845                               new_start + difference_type(new_length));
1846                this->priv_construct_null(new_start + difference_type(new_length));
1847 
1848                this->deallocate_block();
1849                this->assure_long();
1850                this->priv_long_addr(new_start);
1851                this->priv_long_size(new_length);
1852                this->priv_long_storage(new_cap);
1853             }
1854             else{
1855                //value_type is POD, so backwards expansion is much easier
1856                //than with vector<T>
1857                value_type * const oldbuf     = boost::movelib::to_raw_pointer(old_start);
1858                value_type * const newbuf     = boost::movelib::to_raw_pointer(new_start);
1859                const value_type *const pos   = boost::movelib::to_raw_pointer(p);
1860                const size_type before  = size_type(pos - oldbuf);
1861 
1862                //First move old data
1863                Traits::move(newbuf, oldbuf, before);
1864                Traits::move(newbuf + difference_type(before + n), pos, old_size - before);
1865                //Now initialize the new data
1866                priv_uninitialized_copy(first, last, new_start + difference_type(before));
1867                this->priv_construct_null(new_start + difference_type(old_size + n));
1868                this->assure_long();
1869                this->priv_long_addr(new_start);
1870                this->priv_long_size(old_size + n);
1871                this->priv_long_storage(new_cap);
1872             }
1873          }
1874       }
1875       return this->begin() + difference_type(n_pos);
1876    }
1877    #endif
1878 
1879    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1880    //! <b>Effects</b>: As if by insert(p, il.begin(), il.end()).
1881    //!
1882    //! <b>Returns</b>: An iterator which refers to the copy of the first inserted
1883    //!   character, or p if i1 is empty.
1884    inline iterator insert(const_iterator p, std::initializer_list<CharT> il)
1885    {
1886       return this->insert(p, il.begin(), il.end());
1887    }
1888    #endif
1889 
1890    //! <b>Effects</b>: Removes the last element from the container.
1891    //!
1892    //! <b>Throws</b>: Nothing.
1893    //!
1894    //! <b>Complexity</b>: Constant time.
1895    void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1896    {
1897       BOOST_ASSERT(!this->empty());
1898       iterator p = this->end();
1899       this->erase(--p);
1900    }
1901 
1902    //! <b>Requires</b>: pos <= size()
1903    //!
1904    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
1905    //!   The function then replaces the string controlled by *this with a string of length size() - xlen
1906    //!   whose first pos elements are a copy of the initial elements of the original string controlled by *this,
1907    //!   and whose remaining elements are a copy of the elements of the original string controlled by *this
1908    //!   beginning at position pos + xlen.
1909    //!
1910    //! <b>Throws</b>: out_of_range if pos > size().
1911    //!
1912    //! <b>Returns</b>: *this
1913    basic_string& erase(size_type pos = 0, size_type n = npos)
1914    {
1915       if (pos > this->size())
1916          throw_out_of_range("basic_string::erase out of range position");
1917       const pointer addr = this->priv_addr();
1918       erase(addr + difference_type(pos), addr + difference_type(pos) + dtl::min_value(n, this->size() - pos));
1919       return *this;
1920    }
1921 
1922    //! <b>Effects</b>: Removes the character referred to by p.
1923    //!
1924    //! <b>Throws</b>: Nothing
1925    //!
1926    //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
1927    //!    erased. If no such element exists, end() is returned.
1928    iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1929    {
1930       // The move includes the terminating null.
1931       CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p));
1932       const size_type old_size = this->priv_size();
1933       Traits::move(ptr,
1934                    boost::movelib::to_raw_pointer(p + 1),
1935                    old_size - size_type(p - this->priv_addr()));
1936       this->priv_size(old_size-1u);
1937       return iterator(ptr);
1938    }
1939 
1940    //! <b>Requires</b>: first and last are valid iterators on *this, defining a range [first,last).
1941    //!
1942    //! <b>Effects</b>: Removes the characters in the range [first,last).
1943    //!
1944    //! <b>Throws</b>: Nothing
1945    //!
1946    //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
1947    //!   the other elements being erased. If no such element exists, end() is returned.
1948    iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1949    {
1950       CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first));
1951       if (first != last) { // The move includes the terminating null.
1952          const size_type num_erased = size_type(last - first);
1953          const size_type old_size = this->priv_size();
1954          Traits::move(f,
1955                       boost::movelib::to_raw_pointer(last),
1956                       old_size + 1u - size_type(last - this->priv_addr()));
1957          const size_type new_length = old_size - num_erased;
1958          this->priv_size(new_length);
1959       }
1960       return iterator(f);
1961    }
1962 
1963    //! <b>Effects</b>: Erases all the elements of the vector.
1964    //!
1965    //! <b>Throws</b>: Nothing.
1966    //!
1967    //! <b>Complexity</b>: Linear to the number of elements in the vector.
1968    void clear() BOOST_NOEXCEPT_OR_NOTHROW
1969    {
1970        if(this->is_short()) {
1971            Traits::assign(*this->priv_short_addr(), CharT(0));
1972            this->priv_short_size(0);
1973        }
1974        else {
1975            Traits::assign(*this->priv_long_addr(), CharT(0));
1976            this->priv_long_size(0);
1977        }
1978    }
1979 
1980    //! <b>Requires</b>: pos1 <= size().
1981    //!
1982    //! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
1983    //!
1984    //! <b>Throws</b>: if memory allocation throws or out_of_range if pos1 > size().
1985    //!
1986    //! <b>Returns</b>: *this
1987    basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
1988    {
1989       if (pos1 > this->size())
1990          throw_out_of_range("basic_string::replace out of range position");
1991       const size_type len = dtl::min_value(n1, this->size() - pos1);
1992       if (this->size() - len >= this->max_size() - str.size())
1993          throw_length_error("basic_string::replace max_size() exceeded");
1994       const pointer addr = this->priv_addr();
1995       return this->replace( const_iterator(addr + difference_type(pos1))
1996                           , const_iterator(addr + difference_type(pos1 + len))
1997                           , str.begin(), str.end());
1998    }
1999 
2000    //! <b>Effects</b>: Calls `return replace(pos1, n1, sv.data(), sv.size());`.
2001    //!
2002    template<template<class, class> class BasicStringView>
2003    inline basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv)
2004    {
2005       return this->replace(pos1, n1, sv.data(), sv.size());
2006    }
2007 
2008    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
2009    //!
2010    //! <b>Effects</b>: Determines the effective length rlen of the string to be
2011    //!   inserted as the smaller of n2 and str.size() - pos2 and calls
2012    //!   replace(pos1, n1, str.data() + pos2, rlen).
2013    //!
2014    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size().
2015    //!
2016    //! <b>Returns</b>: *this
2017    basic_string& replace(size_type pos1, size_type n1,
2018                          const basic_string& str, size_type pos2, size_type n2 = npos)
2019    {
2020       if (pos2 > str.size())
2021          throw_out_of_range("basic_string::replace out of range position");
2022       return this->replace(pos1, n1, str.data()+pos2, dtl::min_value(n2, str.size() - pos2));
2023    }
2024 
2025    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size().
2026    //!
2027    //! <b>Effects</b>: Determines the effective length rlen of the string to be inserted as the
2028    //!   smaller of n2 and sv.size() - pos2 and calls `replace(pos1, n1, sv.data() + pos2, rlen)`.
2029    //!
2030    //! <b>Returns</b>: *this.
2031    template<template<class, class> class BasicStringView>
2032    basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv,
2033                          size_type pos2, size_type n2 = npos)
2034    {
2035       if (pos2 > sv.size())
2036          throw_out_of_range("basic_string::replace out of range position");
2037       return this->replace(pos1, n1, sv.data()+pos2, dtl::min_value(n2, sv.size() - pos2));
2038    }
2039 
2040    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
2041    //!
2042    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the
2043    //!   smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error.
2044    //!   Otherwise, the function replaces the string controlled by *this with a string of
2045    //!   length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements
2046    //!   of the original string controlled by *this, whose next n2 elements are a copy of the
2047    //!   initial n2 elements of s, and whose remaining elements are a copy of the elements of
2048    //!   the original string controlled by *this beginning at position pos + xlen.
2049    //!
2050    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2051    //!   if the length of the resulting string would exceed max_size()
2052    //!
2053    //! <b>Returns</b>: *this
2054    basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
2055    {
2056       if (pos1 > this->size())
2057          throw_out_of_range("basic_string::replace out of range position");
2058       const size_type len = dtl::min_value(n1, this->size() - pos1);
2059       const size_type max_sz = this->max_size();
2060       if (n2 > max_sz || (this->size() - len) >= (max_sz - n2))
2061          throw_length_error("basic_string::replace max_size() exceeded");
2062       const pointer addr = this->priv_addr() + pos1;
2063       return this->replace(addr, addr + difference_type(len), s, s + difference_type(n2));
2064    }
2065 
2066    //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
2067    //!
2068    //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller
2069    //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise,
2070    //! the function replaces the string controlled by *this with a string of length size() - xlen + n2
2071    //! whose first pos1 elements are a copy of the initial elements of the original string controlled
2072    //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose
2073    //! remaining elements are a copy of the elements of the original string controlled by *this
2074    //! beginning at position pos + xlen.
2075    //!
2076    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2077    //!   if the length of the resulting string would exceed max_size()
2078    //!
2079    //! <b>Returns</b>: *this
2080    inline basic_string& replace(size_type pos, size_type n1, const CharT* s)
2081    {
2082       return this->replace(pos, n1, s, Traits::length(s));
2083    }
2084 
2085    //! <b>Requires</b>: pos1 <= size().
2086    //!
2087    //! <b>Effects</b>: Equivalent to replace(pos1, n1, basic_string(n2, c)).
2088    //!
2089    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
2090    //!   if the length of the  resulting string would exceed max_size()
2091    //!
2092    //! <b>Returns</b>: *this
2093    basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
2094    {
2095       if (pos1 > this->size())
2096          throw_out_of_range("basic_string::replace out of range position");
2097       const size_type len = dtl::min_value(n1, this->size() - pos1);
2098       if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
2099          throw_length_error("basic_string::replace max_size() exceeded");
2100       const pointer addr    = this->priv_addr();
2101       return this->replace(addr + difference_type(pos1), addr + difference_type(pos1 + len), n2, c);
2102    }
2103 
2104    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
2105    //!
2106    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, str).
2107    //!
2108    //! <b>Throws</b>: if memory allocation throws
2109    //!
2110    //! <b>Returns</b>: *this
2111    inline basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
2112    { return this->replace(i1, i2, str.data(), str.data()+str.size()); }
2113 
2114    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and
2115    //!   s points to an array of at least n elements
2116    //!
2117    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, n).
2118    //!
2119    //! <b>Throws</b>: if memory allocation throws
2120    //!
2121    //! <b>Returns</b>: *this
2122    inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n)
2123    { return this->replace(i1, i2, s, s + difference_type(n)); }
2124 
2125    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and s points to an
2126    //!   array of at least traits::length(s) + 1 elements of CharT.
2127    //!
2128    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)).
2129    //!
2130    //! <b>Throws</b>: if memory allocation throws
2131    //!
2132    //! <b>Returns</b>: *this
2133    inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s)
2134    {  return this->replace(i1, i2, s, s + Traits::length(s));   }
2135 
2136    //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
2137    //!
2138    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)).
2139    //!
2140    //! <b>Throws</b>: if memory allocation throws
2141    //!
2142    //! <b>Returns</b>: *this
2143    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
2144    {
2145       const size_type len = static_cast<size_type>(i2 - i1);
2146       if (len >= n) {
2147          Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c);
2148          erase(i1 + difference_type(n), i2);
2149       }
2150       else {
2151          Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c);
2152          insert(i2, n - len, c);
2153       }
2154       return *this;
2155    }
2156 
2157    //! <b>Requires</b>: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges.
2158    //!
2159    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)).
2160    //!
2161    //! <b>Throws</b>: if memory allocation throws
2162    //!
2163    //! <b>Returns</b>: *this
2164    template <class InputIter>
2165    basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
2166       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2167       , typename dtl::disable_if_or
2168          < void
2169          , dtl::is_convertible<InputIter, size_type>
2170          , dtl::is_input_iterator<InputIter>
2171          >::type * = 0
2172       #endif
2173       )
2174    {
2175       for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
2176          Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1);
2177       }
2178 
2179       if (j1 == j2)
2180          this->erase(i1, i2);
2181       else
2182          this->insert(i2, j1, j2);
2183       return *this;
2184    }
2185 
2186    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2187    template <class ForwardIter>
2188    basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
2189       , typename dtl::disable_if_or
2190          < void
2191          , dtl::is_convertible<ForwardIter, size_type>
2192          , dtl::is_not_input_iterator<ForwardIter>
2193          >::type * = 0
2194       )
2195    {
2196       difference_type n = boost::container::iterator_distance(j1, j2);
2197       const difference_type len = i2 - i1;
2198       if (len >= n) {
2199          this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2200          this->erase(i1 + difference_type(n), i2);
2201       }
2202       else {
2203          ForwardIter m = j1;
2204          boost::container::iterator_advance(m, len);
2205          this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
2206          this->insert(i2, m, j2);
2207       }
2208       return *this;
2209    }
2210    #endif
2211 
2212    //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
2213    //!
2214    //! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`.
2215    //!
2216    //! <b>Returns</b>: *this.
2217    template<template <class, class> class BasicStringView>
2218    inline basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
2219    {
2220       return this->replace( static_cast<size_type>(i1 - this->cbegin())
2221                           , static_cast<size_type>(i2 - i1), sv);
2222    }
2223 
2224    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2225    //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
2226    //!
2227    //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()).
2228    //!
2229    //! <b>Returns</b>: *this.
2230    inline basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il)
2231    {
2232       return this->replace( static_cast<size_type>(i1 - this->cbegin())
2233                           , static_cast<size_type>(i2 - i1)
2234                           , il.begin(), il.size());
2235    }
2236    #endif
2237 
2238    //! <b>Requires</b>: pos <= size()
2239    //!
2240    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
2241    //!   smaller of n and size() - pos. s shall designate an array of at least rlen elements.
2242    //!   The function then replaces the string designated by s with a string of length rlen
2243    //!   whose elements are a copy of the string controlled by *this beginning at position pos.
2244    //!   The function does not append a null object to the string designated by s.
2245    //!
2246    //! <b>Throws</b>: if memory allocation throws, out_of_range if pos > size().
2247    //!
2248    //! <b>Returns</b>: rlen
2249    size_type copy(CharT* s, size_type n, size_type pos = 0) const
2250    {
2251       if (pos > this->size())
2252          throw_out_of_range("basic_string::copy out of range position");
2253       const size_type len = dtl::min_value(n, this->size() - pos);
2254       Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len);
2255       return len;
2256    }
2257 
2258    //! <b>Effects</b>: *this contains the same sequence of characters that was in s,
2259    //!   s contains the same sequence of characters that was in *this.
2260    //!
2261    //! <b>Throws</b>: Nothing
2262    void swap(basic_string& x)
2263       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
2264                                || allocator_traits_type::is_always_equal::value)
2265    {
2266       this->base_t::swap_data(x);
2267       dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2268       dtl::swap_alloc(this->alloc(), x.alloc(), flag);
2269    }
2270 
2271    //////////////////////////////////////////////
2272    //
2273    //                 data access
2274    //
2275    //////////////////////////////////////////////
2276 
2277    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
2278    //!
2279    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2280    //!
2281    //! <b>Complexity</b>: constant time.
2282    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2283       const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
2284    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2285 
2286    //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
2287    //!
2288    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2289    //!
2290    //! <b>Complexity</b>: constant time.
2291    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2292       const CharT* data()  const BOOST_NOEXCEPT_OR_NOTHROW
2293    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2294 
2295    //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2296    //!
2297    //! <b>Complexity</b>: constant time.
2298    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2299       CharT* data()  BOOST_NOEXCEPT_OR_NOTHROW
2300    {  return boost::movelib::to_raw_pointer(this->priv_addr()); }
2301 
2302    #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
2303    //! <b>Returns</b>: a string_view to the characters in the string.
2304    //!
2305    //! <b>Complexity</b>: constant time.
2306    template<template <class, class> class BasicStringView>
2307    inline operator BasicStringView<CharT, Traits>() const BOOST_NOEXCEPT_OR_NOTHROW
2308    { return this->to_view< BasicStringView<CharT, Traits> >(); }
2309    #endif
2310 
2311    //! <b>Returns</b>: a string_view to the characters in the string.
2312    //!
2313    //! <b>Complexity</b>: constant time.
2314    //!
2315    //! <b>Note</b>: This function is available to write portable code for compilers
2316    //!   that don't support templated conversion operators.
2317    template<class BasicStringView>
2318    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2319       BasicStringView to_view() const BOOST_NOEXCEPT_OR_NOTHROW
2320    { return BasicStringView(this->data(), this->size()); }
2321 
2322    //////////////////////////////////////////////
2323    //
2324    //             string operations
2325    //
2326    //////////////////////////////////////////////
2327 
2328    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
2329    //!   of the following conditions hold:
2330    //!   1) pos <= xpos and xpos + str.size() <= size();
2331    //!   2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
2332    //!
2333    //! <b>Throws</b>: Nothing
2334    //!
2335    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2336    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2337       size_type find(const basic_string& s, size_type pos = 0) const
2338    { return find(s.c_str(), pos, s.size()); }
2339 
2340    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
2341    //!   of the following conditions hold:
2342    //!   1) pos <= xpos and xpos + sv.size() <= size();
2343    //!   2) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
2344    //!
2345    //! <b>Throws</b>: Nothing
2346    //!
2347    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2348    template<template <class, class> class BasicStringView>
2349    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2350       size_type find(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2351    { return this->find(sv.data(), pos, sv.size()); }
2352 
2353    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2354    //!
2355    //! <b>Throws</b>: Nothing
2356    //!
2357    //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(s,n),pos).
2358    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2359       size_type find(const CharT* s, size_type pos, size_type n) const
2360    {
2361       if (pos + n > this->size())
2362          return npos;
2363       else {
2364          const pointer addr = this->priv_addr();
2365          pointer finish = addr + difference_type(this->priv_size());
2366          const const_iterator result =
2367             boost::container::search(boost::movelib::to_raw_pointer(addr + difference_type(pos)),
2368                    boost::movelib::to_raw_pointer(finish),
2369                    s, s + difference_type(n), Eq_traits<Traits>());
2370          return result != finish ? size_type(result - begin()) : npos;
2371       }
2372    }
2373 
2374    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2375    //!
2376    //! <b>Throws</b>: Nothing
2377    //!
2378    //! <b>Returns</b>: find(basic_string(s), pos).
2379    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2380       size_type find(const CharT* s, size_type pos = 0) const
2381    { return this->find(s, pos, Traits::length(s)); }
2382 
2383    //! <b>Throws</b>: Nothing
2384    //!
2385    //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(1,c), pos).
2386    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2387       size_type find(CharT c, size_type pos = 0) const
2388    {
2389       const size_type sz = this->size();
2390       if (pos >= sz)
2391          return npos;
2392       else {
2393          const pointer addr    = this->priv_addr();
2394          pointer finish = addr + difference_type(sz);
2395          const const_iterator result =
2396             boost::container::find_if(addr + difference_type(pos), finish,
2397                   boost::container::bind2nd(Eq_traits<Traits>(), c));
2398          return result != finish ? size_type(result - begin()) : npos;
2399       }
2400    }
2401 
2402    //! <b>Effects</b>: Determines the highest position xpos, if possible, such
2403    //!   that both of the following conditions obtain:
2404    //!   a) xpos <= pos and xpos + str.size() <= size();
2405    //!   b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
2406    //!
2407    //! <b>Throws</b>: Nothing
2408    //!
2409    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2410    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2411       size_type rfind(const basic_string& str, size_type pos = npos) const
2412       { return this->rfind(str.c_str(), pos, str.size()); }
2413 
2414    //! <b>Effects</b>: Determines the highest position xpos, if possible, such
2415    //!   that both of the following conditions obtain:
2416    //!   a) xpos <= pos and xpos + sv.size() <= size();
2417    //!   b) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
2418    //!
2419    //! <b>Throws</b>: Nothing
2420    //!
2421    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2422    template<template <class, class> class BasicStringView>
2423    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2424       size_type rfind(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2425       { return this->rfind(sv.data(), pos, sv.size()); }
2426 
2427    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2428    //!
2429    //! <b>Throws</b>: Nothing
2430    //!
2431    //! <b>Returns</b>: rfind(basic_string(s, n), pos).
2432    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2433       size_type rfind(const CharT* s, size_type pos, size_type n) const
2434    {
2435       const size_type len = this->size();
2436 
2437       if (n > len)
2438          return npos;
2439       else if (n == 0)
2440          return dtl::min_value(len, pos);
2441       else {
2442          const const_iterator last = begin() + difference_type(dtl::min_value(len - n, pos) + n);
2443          const const_iterator result = boost::container::find_end
2444             (begin(), last, s, s + difference_type(n), Eq_traits<Traits>());
2445          return result != last ? size_type(result - begin()) : npos;
2446       }
2447    }
2448 
2449    //! <b>Requires</b>: pos <= size() and s points to an array of at least
2450    //!   traits::length(s) + 1 elements of CharT.
2451    //!
2452    //! <b>Throws</b>: Nothing
2453    //!
2454    //! <b>Returns</b>: rfind(basic_string(s), pos).
2455    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2456       size_type rfind(const CharT* s, size_type pos = npos) const
2457       { return this->rfind(s, pos, Traits::length(s)); }
2458 
2459    //! <b>Throws</b>: Nothing
2460    //!
2461    //! <b>Returns</b>: rfind(basic_string<CharT,traits,allocator_type>(1,c),pos).
2462    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2463       size_type rfind(CharT c, size_type pos = npos) const
2464    {
2465       const size_type len = this->size();
2466 
2467       if (len < 1)
2468          return npos;
2469       else {
2470          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2471          const_reverse_iterator rresult =
2472             boost::container::find_if(const_reverse_iterator(last), rend(),
2473                   boost::container::bind2nd(Eq_traits<Traits>(), c));
2474          return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2475       }
2476    }
2477 
2478    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
2479    //!   following conditions obtain: a) pos <= xpos and xpos < size();
2480    //!   b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2481    //!
2482    //! <b>Throws</b>: Nothing
2483    //!
2484    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2485    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2486       size_type find_first_of(const basic_string& str, size_type pos = 0) const
2487       { return this->find_first_of(str.c_str(), pos, str.size()); }
2488 
2489    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
2490    //!   following conditions obtain: a) pos <= xpos and xpos < size();
2491    //!   b) traits::eq(at(xpos), sv.at(I)) for some element I of the string controlled by sv.
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    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2498       size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2499       { return this->find_first_of(sv.data(), pos, sv.size()); }
2500 
2501    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2502    //!
2503    //! <b>Throws</b>: Nothing
2504    //!
2505    //! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
2506    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2507       size_type find_first_of(const CharT* s, size_type pos, size_type n) const
2508    {
2509       const size_type sz = this->size();
2510       if (pos >= sz)
2511          return npos;
2512       else {
2513          const pointer addr    = this->priv_addr();
2514          pointer finish = addr + difference_type(sz);
2515          const_iterator result = boost::container::find_first_of
2516             (addr + difference_type(pos), finish, s, s + difference_type(n), Eq_traits<Traits>());
2517          return result != finish ? size_type(result - this->begin()) : 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_first_of(basic_string(s), pos).
2526    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2527       size_type find_first_of(const CharT* s, size_type pos = 0) const
2528       { return this->find_first_of(s, pos, Traits::length(s)); }
2529 
2530    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2531    //!
2532    //! <b>Throws</b>: Nothing
2533    //!
2534    //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,allocator_type>(1,c), pos).
2535    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2536       size_type find_first_of(CharT c, size_type pos = 0) const
2537     { return this->find(c, pos); }
2538 
2539    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
2540    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
2541    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2542    //!
2543    //! <b>Throws</b>: Nothing
2544    //!
2545    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2546    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2547       size_type find_last_of(const basic_string& str, size_type pos = npos) const
2548       { return this->find_last_of(str.c_str(), pos, str.size()); }
2549 
2550    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
2551    //!   the following conditions obtain: a) xpos <= pos and xpos < size(); b)
2552    //!   traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
2553    //!
2554    //! <b>Throws</b>: Nothing
2555    //!
2556    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2557    template<template <class, class> class BasicStringView>
2558    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2559       size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2560       { return this->find_last_of(sv.data(), pos, sv.size()); }
2561 
2562    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2563    //!
2564    //! <b>Throws</b>: Nothing
2565    //!
2566    //! <b>Returns</b>: find_last_of(basic_string(s, n), pos).
2567    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2568       size_type find_last_of(const CharT* s, size_type pos, size_type n) const
2569    {
2570       const size_type len = this->size();
2571 
2572       if (len < 1)
2573          return npos;
2574       else {
2575          const pointer addr    = this->priv_addr();
2576          const const_iterator last = addr + difference_type(dtl::min_value(len - 1, pos) + 1);
2577          const const_reverse_iterator rresult =
2578             boost::container::find_first_of(const_reverse_iterator(last), rend(),
2579                                s, s + difference_type(n), Eq_traits<Traits>());
2580          return rresult != rend() ? size_type((rresult.base() - 1) - addr) : npos;
2581       }
2582    }
2583 
2584    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2585    //!
2586    //! <b>Throws</b>: Nothing
2587    //!
2588    //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,allocator_type>(1,c),pos).
2589    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2590       size_type find_last_of(const CharT* s, size_type pos = npos) const
2591       { return this->find_last_of(s, pos, Traits::length(s)); }
2592 
2593    //! <b>Throws</b>: Nothing
2594    //!
2595    //! <b>Returns</b>: find_last_of(basic_string(s), pos).
2596    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2597       size_type find_last_of(CharT c, size_type pos = npos) const
2598       {  return this->rfind(c, pos);   }
2599 
2600    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
2601    //!   both of the following conditions obtain:
2602    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no
2603    //!   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    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2609       size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
2610       { return this->find_first_not_of(str.c_str(), pos, str.size()); }
2611 
2612    //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
2613    //!   both of the following conditions obtain:
2614    //!   a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), sv.at(I)) for no
2615    //!   element I of the string controlled by sv.
2616    //!
2617    //! <b>Throws</b>: Nothing
2618    //!
2619    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2620    template<template <class, class> class BasicStringView>
2621    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2622       size_type find_first_not_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
2623       { return this->find_first_not_of(sv.data(), pos, sv.size()); }
2624 
2625    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2626    //!
2627    //! <b>Throws</b>: Nothing
2628    //!
2629    //! <b>Returns</b>: find_first_not_of(basic_string(s, n), pos).
2630    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2631       size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
2632    {
2633       if (pos > this->size())
2634          return npos;
2635       else {
2636          const pointer addr   = this->priv_addr();
2637          const pointer finish = addr + difference_type(this->priv_size());
2638          const const_iterator result = boost::container::find_if
2639             (addr + difference_type(pos), finish, Not_within_traits<Traits>(s, s + difference_type(n)));
2640          return result != finish ? size_type(result - addr) : npos;
2641       }
2642    }
2643 
2644    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2645    //!
2646    //! <b>Throws</b>: Nothing
2647    //!
2648    //! <b>Returns</b>: find_first_not_of(basic_string(s), pos).
2649    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2650       size_type find_first_not_of(const CharT* s, size_type pos = 0) const
2651       { return this->find_first_not_of(s, pos, Traits::length(s)); }
2652 
2653    //! <b>Throws</b>: Nothing
2654    //!
2655    //! <b>Returns</b>: find_first_not_of(basic_string(1, c), pos).
2656    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2657       size_type find_first_not_of(CharT c, size_type pos = 0) const
2658    {
2659       if (pos > this->size())
2660          return npos;
2661       else {
2662          const pointer addr   = this->priv_addr();
2663          const pointer finish = addr + difference_type(this->priv_size());
2664          const const_iterator result
2665             = boost::container::find_if(addr + difference_type(pos), finish,
2666                      boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2667          return result != finish ? size_type(result - begin()) : npos;
2668       }
2669    }
2670 
2671    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
2672    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size();
2673    //!   b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str.
2674    //!
2675    //! <b>Throws</b>: Nothing
2676    //!
2677    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2678    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2679       size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
2680       { return this->find_last_not_of(str.c_str(), pos, str.size()); }
2681 
2682    //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
2683    //!   both of the following conditions obtain: a) xpos <= pos and xpos < size();
2684    //!   b) traits::eq(at(xpos), sv.at(I)) for no element I of the string controlled by sv.
2685    //!
2686    //! <b>Throws</b>: Nothing
2687    //!
2688    //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
2689    template<template <class, class> class BasicStringView>
2690    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2691       size_type find_last_not_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
2692       { return this->find_last_not_of(sv.data(), pos, sv.size()); }
2693 
2694    //! <b>Requires</b>: s points to an array of at least n elements of CharT.
2695    //!
2696    //! <b>Throws</b>: Nothing
2697    //!
2698    //! <b>Returns</b>: find_last_not_of(basic_string(s, n), pos).
2699    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2700       size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
2701    {
2702       const size_type len = this->size();
2703 
2704       if (len < 1)
2705          return npos;
2706       else {
2707          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2708          const const_reverse_iterator rresult =
2709             boost::container::find_if(const_reverse_iterator(last), rend(),
2710                     Not_within_traits<Traits>(s, s + difference_type(n)));
2711          return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2712       }
2713    }
2714 
2715    //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
2716    //!
2717    //! <b>Throws</b>: Nothing
2718    //!
2719    //! <b>Returns</b>: find_last_not_of(basic_string(s), pos).
2720    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2721       size_type find_last_not_of(const CharT* s, size_type pos = npos) const
2722       { return this->find_last_not_of(s, pos, Traits::length(s)); }
2723 
2724    //! <b>Throws</b>: Nothing
2725    //!
2726    //! <b>Returns</b>: find_last_not_of(basic_string(1, c), pos).
2727    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2728       size_type find_last_not_of(CharT c, size_type pos = npos) const
2729    {
2730       const size_type len = this->size();
2731 
2732       if (len < 1)
2733          return npos;
2734       else {
2735          const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
2736          const const_reverse_iterator rresult =
2737             boost::container::find_if(const_reverse_iterator(last), rend(),
2738                   boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
2739          return rresult != rend() ? size_type((rresult.base() - 1) - begin()) : npos;
2740       }
2741    }
2742 
2743    //! <b>Requires</b>: Requires: pos <= size()
2744    //!
2745    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2746    //!   the smaller of n and size() - pos.
2747    //!
2748    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
2749    //!
2750    //! <b>Returns</b>: basic_string<CharT,traits,allocator_type>(data()+pos,rlen).
2751    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2752       basic_string substr(size_type pos = 0, size_type n = npos) const
2753    {
2754       if (pos > this->size())
2755          throw_out_of_range("basic_string::substr out of range position");
2756       const pointer addr = this->priv_addr();
2757       return basic_string(addr + difference_type(pos),
2758                           addr + difference_type(pos + dtl::min_value(n, size() - pos)), this->alloc());
2759    }
2760 
2761    //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
2762    //!   the smaller of size() and str.size(). The function then compares the two strings by
2763    //!   calling traits::compare(data(), str.data(), rlen).
2764    //!
2765    //! <b>Throws</b>: Nothing
2766    //!
2767    //! <b>Returns</b>: The nonzero result if the result of the comparison is nonzero.
2768    //!   Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(),
2769    //!   and value > 0 if size() > str.size()
2770    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2771       int compare(const basic_string& str) const
2772    {
2773       const pointer addr     = this->priv_addr();
2774       const pointer str_addr = str.priv_addr();
2775       return this->s_compare(addr, addr + difference_type(this->priv_size()), str_addr, str_addr + difference_type(str.priv_size()));
2776    }
2777 
2778    //! <b>Throws</b>: Nothing
2779    //!
2780    //! <b>Returns</b>: compare(basic_string(sv)).
2781    template<template <class, class> class BasicStringView>
2782    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2783       int compare(BasicStringView<CharT,Traits> sv) const
2784    {
2785       const pointer addr = this->priv_addr();
2786       return this->s_compare(addr, addr + difference_type(this->priv_size()), sv.data(), sv.data() + difference_type(sv.size()));
2787    }
2788 
2789    //! <b>Requires</b>: pos1 <= size()
2790    //!
2791    //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
2792    //!   the smaller of (this->size() - pos1), n1 and str.size(). The function then compares the two strings by
2793    //!   calling traits::compare(data()+pos1, str.data(), rlen).
2794    //!
2795    //! <b>Throws</b>: out_of_range if pos1 > size()
2796    //!
2797    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(str).
2798    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2799       int compare(size_type pos1, size_type n1, const basic_string& str) const
2800    {
2801       if (pos1 > this->size())
2802          throw_out_of_range("basic_string::compare out of range position");
2803       const pointer addr    = this->priv_addr();
2804       const pointer str_addr = str.priv_addr();
2805       return this->s_compare(addr + difference_type(pos1),
2806                         addr + difference_type(pos1 + dtl::min_value(n1, this->size() - pos1)),
2807                         str_addr, str_addr + difference_type(str.priv_size()));
2808    }
2809 
2810    //! <b>Requires</b>: pos1 <= size()
2811    //!
2812    //! <b>Throws</b>: out_of_range if pos1 > size()
2813    //!
2814    //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(sv).
2815    template<template <class, class> class BasicStringView>
2816    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2817       int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv) const
2818    {
2819       if (pos1 > this->size())
2820          throw_out_of_range("basic_string::compare out of range position");
2821       const pointer addr    = this->priv_addr() + pos1;
2822       const CharT* str_addr = sv.data();
2823       return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2824                        str_addr, str_addr + sv.size());
2825    }
2826 
2827    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
2828    //!
2829    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2830    //!   the smaller of
2831    //!
2832    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
2833    //!
2834    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
2835    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2836       int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const
2837    {
2838       if (pos1 > this->size() || pos2 > str.size())
2839          throw_out_of_range("basic_string::compare out of range position");
2840       const pointer addr     = this->priv_addr() + pos1;
2841       const pointer str_addr = str.priv_addr() + pos2;
2842       return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2843                              str_addr, str_addr + difference_type(dtl::min_value(n2, str.size() - pos2)));
2844    }
2845 
2846    //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
2847    //!
2848    //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
2849    //!   the smaller of
2850    //!
2851    //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size()
2852    //!
2853    //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(BasicStringView<CharT, Traits>(sv, pos2, n2)).
2854    template<template <class, class> class BasicStringView>
2855    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2856       int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv, size_type pos2, size_type n2) const
2857    {
2858       if (pos1 > this->size() || pos2 > sv.size())
2859          throw_out_of_range("basic_string::compare out of range position");
2860       const pointer addr     = this->priv_addr() + pos1;
2861       const CharT * str_addr = sv.data() + pos2;
2862       return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)),
2863                        str_addr, str_addr + difference_type(dtl::min_value(n2, sv.size() - pos2)));
2864    }
2865 
2866    //! <b>Throws</b>: Nothing
2867    //!
2868    //! <b>Returns</b>: compare(basic_string(s)).
2869    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2870       int compare(const CharT* s) const
2871    {
2872       const pointer addr = this->priv_addr();
2873       return this->s_compare(addr, addr + difference_type(this->priv_size()), s, s + Traits::length(s));
2874    }
2875 
2876    //! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
2877    //!
2878    //! <b>Throws</b>: out_of_range if pos1 > size()
2879    //!
2880    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2881    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2882       int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
2883    {
2884       if (pos1 > this->size())
2885          throw_out_of_range("basic_string::compare out of range position");
2886       const pointer addr = this->priv_addr();
2887       return this->s_compare( addr + difference_type(pos1),
2888                         addr + difference_type(pos1 + dtl::min_value(n1, this->size() - pos1)),
2889                         s, s + difference_type(n2));
2890    }
2891 
2892    //! <b>Requires</b>: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT.
2893    //!
2894    //! <b>Throws</b>: out_of_range if pos1 > size()
2895    //!
2896    //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
2897    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2898       int compare(size_type pos1, size_type n1, const CharT* s) const
2899    {  return this->compare(pos1, n1, s, Traits::length(s)); }
2900 
2901    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2902    private:
2903    void priv_move_assign(BOOST_RV_REF(basic_string) x, dtl::bool_<true> /*steal_resources*/)
2904    {
2905       //Destroy objects but retain memory in case x reuses it in the future
2906       this->clear();
2907       //Move allocator if needed
2908       dtl::bool_<allocator_traits_type::
2909          propagate_on_container_move_assignment::value> flag;
2910       dtl::move_alloc(this->alloc(), x.alloc(), flag);
2911       //Nothrow swap
2912       this->swap_data(x);
2913    }
2914 
2915    void priv_move_assign(BOOST_RV_REF(basic_string) x, dtl::bool_<false> /*steal_resources*/)
2916    {
2917       //We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
2918       //Resources can be transferred if both allocators are equal
2919       if (this->alloc() == x.alloc()) {
2920          this->priv_move_assign(boost::move(x), dtl::true_());
2921       }
2922       else {
2923          this->assign(x.begin(), x.end());
2924       }
2925    }
2926 
2927    bool priv_reserve_no_null_end(size_type res_arg)
2928    {
2929       if (res_arg > this->max_size()){
2930          throw_length_error("basic_string::reserve max_size() exceeded");
2931       }
2932 
2933       const bool do_alloc = this->capacity() < res_arg;
2934       if (do_alloc){
2935          //size_type n = dtl::max_value(res_arg, this->size()) + 1;
2936          size_type n = res_arg + 1;
2937          size_type new_cap = this->next_capacity(n);
2938          pointer reuse = 0;
2939          pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse);
2940 
2941          const pointer addr = this->priv_addr();
2942          size_type new_length = priv_uninitialized_copy
2943             (addr, addr + difference_type(this->priv_size()), new_start);
2944          this->deallocate_block();
2945          this->assure_long();
2946          this->priv_long_addr(new_start);
2947          this->priv_long_size(new_length);
2948          this->priv_storage(new_cap);
2949       }
2950       return do_alloc;
2951    }
2952 
2953    void priv_reserve(size_type res_arg)
2954    {
2955       if(this->priv_reserve_no_null_end(res_arg))
2956          this->priv_terminate_string();
2957    }
2958 
2959    template<class It1, class It2>
2960    static int s_compare(It1 f1, It1 l1, It2 f2, It2 l2)
2961    {
2962       const std::size_t n1 = std::size_t(l1 - f1);
2963       const std::size_t n2 = std::size_t(l2 - f2);
2964       const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1),
2965                                       boost::movelib::to_raw_pointer(f2),
2966                                       dtl::min_value(n1, n2));
2967       return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
2968    }
2969 
2970    template<class AllocVersion>
2971    void priv_shrink_to_fit_dynamic_buffer
2972       ( AllocVersion
2973       , typename dtl::enable_if<dtl::is_same<AllocVersion, version_1> >::type* = 0)
2974    {
2975       //Allocate a new buffer.
2976       size_type real_cap = 0;
2977       const pointer   long_addr    = this->priv_long_addr();
2978       const size_type long_size    = this->priv_long_size();
2979       const size_type long_storage = this->priv_long_storage();
2980       //We can make this nothrow as chars are always NoThrowCopyables
2981       BOOST_CONTAINER_TRY{
2982          pointer reuse = 0;
2983          real_cap = long_size+1;
2984          const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
2985          //Copy and update
2986          Traits::copy( boost::movelib::to_raw_pointer(ret)
2987                      , boost::movelib::to_raw_pointer(this->priv_long_addr())
2988                      , long_size+1);
2989          this->priv_long_addr(ret);
2990          this->priv_storage(real_cap);
2991          //And release old buffer
2992          this->alloc().deallocate(long_addr, long_storage);
2993       }
2994       BOOST_CONTAINER_CATCH(...){
2995          return;
2996       }
2997       BOOST_CONTAINER_CATCH_END
2998    }
2999 
3000    template<class AllocVersion>
3001    void priv_shrink_to_fit_dynamic_buffer
3002       ( AllocVersion
3003       , typename dtl::enable_if<dtl::is_same<AllocVersion, version_2> >::type* = 0)
3004    {
3005       size_type received_size = this->priv_long_size()+1;
3006       pointer hint = this->priv_long_addr();
3007       if(this->alloc().allocation_command
3008          ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){
3009          this->priv_storage(received_size);
3010       }
3011    }
3012 
3013    inline void priv_construct_null(pointer p)
3014    {  traits_type::assign(*p, CharT());  }
3015 
3016    // Helper functions used by constructors.  It is a severe error for
3017    // any of them to be called anywhere except from within constructors.
3018    inline void priv_terminate_string()
3019    {  this->priv_construct_null(this->priv_end_addr());  }
3020 
3021    template<class InpIt, class FwdIt> inline
3022    size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
3023    {
3024       //Save initial destination position
3025       size_type constructed = 0;
3026 
3027       for (; first != last; ++dest, ++first, ++constructed){
3028          traits_type::assign(*dest, *first);
3029       }
3030       return constructed;
3031    }
3032 
3033    template <class InputIterator, class OutIterator>
3034    static void priv_copy(InputIterator first, InputIterator last, OutIterator result)
3035    {
3036       for ( ; first != last; ++first, ++result)
3037          Traits::assign(*result, *first);
3038    }
3039 
3040    static inline void priv_copy(const CharT* first, const CharT* last, CharT* result)
3041    {  Traits::copy(result, first, std::size_t(last - first));  }
3042 
3043    template <class Integer>
3044    inline basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3045                                        Integer n, Integer x,
3046                                        dtl::true_)
3047    {  return this->replace(first, last, (size_type) n, (CharT) x);   }
3048 
3049    template <class InputIter>
3050    inline basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
3051                                        InputIter f, InputIter l,
3052                                        dtl::false_)
3053    {
3054       typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category;
3055       return this->priv_replace(first, last, f, l, Category());
3056    }
3057 
3058    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3059 };
3060 
3061 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3062 
3063 template <typename InputIterator>
3064 basic_string(InputIterator, InputIterator) ->
3065    basic_string<typename iterator_traits<InputIterator>::value_type>;
3066 
3067 template <typename InputIterator, typename Allocator>
3068 basic_string(InputIterator, InputIterator, Allocator const&) ->
3069    basic_string<typename iterator_traits<InputIterator>::value_type, Allocator>;
3070 
3071 #endif
3072 
3073 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
3074 
3075 //!Typedef for a basic_string of
3076 //!narrow characters
3077 typedef basic_string
3078    <char
3079    ,std::char_traits<char>
3080    ,new_allocator<char> >
3081 string;
3082 
3083 //!Typedef for a basic_string of
3084 //!narrow characters
3085 typedef basic_string
3086    <wchar_t
3087    ,std::char_traits<wchar_t>
3088    ,new_allocator<wchar_t> >
3089 wstring;
3090 
3091 #else
3092 
3093 template<class S>
3094 struct is_string
3095 {
3096    BOOST_STATIC_CONSTEXPR bool value = false;
3097 };
3098 
3099 template<class C, class T, class A>
3100 struct is_string< basic_string<C, T, A> >
3101 {
3102    BOOST_STATIC_CONSTEXPR bool value = true;
3103 };
3104 
3105 #endif
3106 
3107 // ------------------------------------------------------------
3108 // Non-member functions.
3109 
3110 // Operator+
3111 
3112 template <class CharT, class Traits, class Allocator> inline
3113    basic_string<CharT,Traits,Allocator>
3114    operator+(const basic_string<CharT,Traits,Allocator>& x
3115             ,const basic_string<CharT,Traits,Allocator>& y)
3116 {
3117    typedef basic_string<CharT,Traits,Allocator> str_t;
3118    typedef typename str_t::reserve_t reserve_t;
3119    reserve_t reserve;
3120    str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
3121    result.append(x);
3122    result.append(y);
3123    return result;
3124 }
3125 
3126 template <class CharT, class Traits, class Allocator> inline
3127    basic_string<CharT, Traits, Allocator> operator+
3128       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3129       , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3130 {
3131    x += y;
3132    return boost::move(x);
3133 }
3134 
3135 template <class CharT, class Traits, class Allocator> inline
3136    basic_string<CharT, Traits, Allocator> operator+
3137       ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
3138       , const basic_string<CharT,Traits,Allocator>& y)
3139 {
3140    x += y;
3141    return boost::move(x);
3142 }
3143 
3144 template <class CharT, class Traits, class Allocator> inline
3145    basic_string<CharT, Traits, Allocator> operator+
3146       (const basic_string<CharT,Traits,Allocator>& x
3147       ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
3148 {
3149    y.insert(y.begin(), x.begin(), x.end());
3150    return boost::move(y);
3151 }
3152 
3153 template <class CharT, class Traits, class Allocator> inline
3154    basic_string<CharT, Traits, Allocator> operator+
3155       (const CharT* s, basic_string<CharT, Traits, Allocator> y)
3156 {
3157    y.insert(y.begin(), s, s + Traits::length(s));
3158    return y;
3159 }
3160 
3161 template <class CharT, class Traits, class Allocator> inline
3162    basic_string<CharT,Traits,Allocator> operator+
3163       (basic_string<CharT,Traits,Allocator> x, const CharT* s)
3164 {
3165    x += s;
3166    return x;
3167 }
3168 
3169 template <class CharT, class Traits, class Allocator> inline
3170    basic_string<CharT,Traits,Allocator> operator+
3171       (CharT c, basic_string<CharT,Traits,Allocator> y)
3172 {
3173    y.insert(y.begin(), c);
3174    return y;
3175 }
3176 
3177 template <class CharT, class Traits, class Allocator> inline
3178    basic_string<CharT,Traits,Allocator> operator+
3179       (basic_string<CharT,Traits,Allocator> x, const CharT c)
3180 {
3181    x += c;
3182    return x;
3183 }
3184 
3185 // Operator== and operator!=
3186 
3187 template <class CharT, class Traits, class Allocator>
3188 inline bool
3189 operator==(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3190 {
3191    return x.size() == y.size() &&
3192           Traits::compare(x.data(), y.data(), x.size()) == 0;
3193 }
3194 
3195 template <class CharT, class Traits, class Allocator>
3196 inline bool
3197 operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3198 {
3199    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3200    return n == y.size() && Traits::compare(s, y.data(), n) == 0;
3201 }
3202 
3203 template <class CharT, class Traits, class Allocator>
3204 inline bool
3205 operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3206 {
3207    typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
3208    return x.size() == n && Traits::compare(x.data(), s, n) == 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 {
3218    return x.size() == y.size() &&
3219           Traits::compare(x.data(), y.data(), x.size()) == 0;
3220 }
3221 
3222 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3223 inline
3224    BOOST_CONTAINER_DOC1ST( bool, 
3225                            typename dtl::disable_if
3226                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3227       operator==( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3228 {
3229    return x.size() == y.size() &&
3230           Traits::compare(x.data(), y.data(), x.size()) == 0;
3231 }
3232 
3233 template <class CharT, class Traits, class Allocator>
3234 inline bool
3235 operator!=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3236    {  return !(x == y);  }
3237 
3238 template <class CharT, class Traits, class Allocator>
3239 inline bool
3240 operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3241    {  return !(s == y); }
3242 
3243 template <class CharT, class Traits, class Allocator>
3244 inline bool
3245 operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3246    {  return !(x == s);   }
3247 
3248 
3249 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3250 inline
3251    BOOST_CONTAINER_DOC1ST( bool, 
3252                            typename dtl::disable_if
3253                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3254 operator!=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3255    {  return !(x == y);  }
3256 
3257 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3258 inline
3259    BOOST_CONTAINER_DOC1ST( bool, 
3260                            typename dtl::disable_if
3261                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3262 operator!=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3263    {  return !(x == y);  }
3264 
3265 // Operator< (and also >, <=, and >=).
3266 template <class CharT, class Traits, class Allocator>
3267 inline bool
3268 operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3269 {
3270    return x.compare(y) < 0;
3271 }
3272 
3273 template <class CharT, class Traits, class Allocator>
3274 inline bool
3275 operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3276 {
3277    return y.compare(s) > 0;
3278 }
3279 
3280 template <class CharT, class Traits, class Allocator>
3281 inline bool
3282 operator<(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3283 {
3284    return x.compare(s) < 0;
3285 }
3286 
3287 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3288 inline
3289    BOOST_CONTAINER_DOC1ST( bool, 
3290                            typename dtl::disable_if
3291                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3292 operator<( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3293    {  return y.compare(x) > 0;  }
3294 
3295 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3296 inline
3297    BOOST_CONTAINER_DOC1ST( bool, 
3298                            typename dtl::disable_if
3299                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3300 operator<(  const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3301    {  return x.compare(y) < 0;  }
3302 
3303 template <class CharT, class Traits, class Allocator>
3304 inline bool
3305 operator>(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y) {
3306    return y < x;
3307 }
3308 
3309 template <class CharT, class Traits, class Allocator>
3310 inline bool
3311 operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
3312    return y < s;
3313 }
3314 
3315 template <class CharT, class Traits, class Allocator>
3316 inline bool
3317 operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3318 {
3319    return s < x;
3320 }
3321 
3322 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3323 inline
3324    BOOST_CONTAINER_DOC1ST( bool, 
3325                            typename dtl::disable_if
3326                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3327 operator>( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3328    {  return y < x;  }
3329 
3330 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3331 inline
3332    BOOST_CONTAINER_DOC1ST( bool, 
3333                            typename dtl::disable_if
3334                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3335 operator>( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3336    {  return y < x;  }
3337 
3338 template <class CharT, class Traits, class Allocator>
3339 inline bool
3340 operator<=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
3341 {
3342   return !(y < x);
3343 }
3344 
3345 template <class CharT, class Traits, class Allocator>
3346 inline bool
3347 operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3348    {  return !(y < s);  }
3349 
3350 template <class CharT, class Traits, class Allocator>
3351 inline bool
3352 operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3353    {  return !(s < x);  }
3354 
3355 
3356 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3357 inline
3358    BOOST_CONTAINER_DOC1ST( bool, 
3359                            typename dtl::disable_if
3360                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3361 operator<=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3362    {  return !(y < x);  }
3363 
3364 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3365 inline
3366    BOOST_CONTAINER_DOC1ST( bool, 
3367                            typename dtl::disable_if
3368                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3369 operator<=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3370    {  return !(y < x);  }
3371 
3372 template <class CharT, class Traits, class Allocator>
3373 inline bool
3374 operator>=(const basic_string<CharT,Traits,Allocator>& x,
3375            const basic_string<CharT,Traits,Allocator>& y)
3376    {  return !(x < y);  }
3377 
3378 template <class CharT, class Traits, class Allocator>
3379 inline bool
3380 operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
3381    {  return !(s < y);  }
3382 
3383 template <class CharT, class Traits, class Allocator>
3384 inline bool
3385 operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
3386    {  return !(x < s);  }
3387 
3388 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3389 inline
3390    BOOST_CONTAINER_DOC1ST( bool, 
3391                            typename dtl::disable_if
3392                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3393 operator>=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
3394    {  return !(x < y);  }
3395 
3396 template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
3397 inline
3398    BOOST_CONTAINER_DOC1ST( bool, 
3399                            typename dtl::disable_if
3400                               <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
3401 operator>=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
3402    {  return !(x < y);  }
3403 
3404 // Swap.
3405 template <class CharT, class Traits, class Allocator>
3406 inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
3407     BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
3408 {  x.swap(y);  }
3409 
3410 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3411 // I/O.
3412 namespace dtl {
3413 
3414 template <class CharT, class Traits>
3415 inline bool
3416 string_fill(std::basic_ostream<CharT, Traits>& os,
3417                   std::basic_streambuf<CharT, Traits>* buf,
3418                   std::size_t n)
3419 {
3420    CharT f = os.fill();
3421    std::size_t i;
3422    bool ok = true;
3423 
3424    for (i = 0; i < n; i++)
3425       ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
3426    return ok;
3427 }
3428 
3429 }  //namespace dtl {
3430 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3431 
3432 template <class CharT, class Traits, class Allocator>
3433 std::basic_ostream<CharT, Traits>&
3434 operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,Allocator>& s)
3435 {
3436    typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
3437    bool ok = false;
3438 
3439    if (sentry) {
3440       ok = true;
3441       typename basic_string<CharT,Traits,Allocator>::size_type n = s.size();
3442       typename basic_string<CharT,Traits,Allocator>::size_type pad_len = 0;
3443       const bool left = (os.flags() & std::ios::left) != 0;
3444       const std::size_t w = os.width(0);
3445       std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
3446 
3447       if (w != 0 && n < w)
3448          pad_len = w - n;
3449 
3450       if (!left)
3451          ok = dtl::string_fill(os, buf, pad_len);
3452 
3453       ok = ok &&
3454             buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
3455 
3456       if (left)
3457          ok = ok && dtl::string_fill(os, buf, pad_len);
3458    }
3459 
3460    if (!ok)
3461       os.setstate(std::ios_base::failbit);
3462 
3463    return os;
3464 }
3465 
3466 
3467 template <class CharT, class Traits, class Allocator>
3468 std::basic_istream<CharT, Traits>&
3469 operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3470 {
3471    typename std::basic_istream<CharT, Traits>::sentry sentry(is);
3472 
3473    if (sentry) {
3474       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3475       const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
3476 
3477       s.clear();
3478       std::size_t n = is.width(0);
3479       if (n == 0)
3480          n = static_cast<std::size_t>(-1);
3481       else
3482          s.reserve(n);
3483 
3484       while (n-- > 0) {
3485          typename Traits::int_type c1 = buf->sbumpc();
3486 
3487          if (Traits::eq_int_type(c1, Traits::eof())) {
3488             is.setstate(std::ios_base::eofbit);
3489             break;
3490          }
3491          else {
3492             CharT c = Traits::to_char_type(c1);
3493 
3494             if (ctype.is(std::ctype<CharT>::space, c)) {
3495                if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
3496                   is.setstate(std::ios_base::failbit);
3497                break;
3498             }
3499             else
3500                s.push_back(c);
3501          }
3502       }
3503 
3504       // If we have read no characters, then set failbit.
3505       if (s.size() == 0)
3506          is.setstate(std::ios_base::failbit);
3507    }
3508    else
3509       is.setstate(std::ios_base::failbit);
3510 
3511    return is;
3512 }
3513 
3514 template <class CharT, class Traits, class Allocator>
3515 std::basic_istream<CharT, Traits>&
3516 getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
3517 {
3518    typename basic_string<CharT,Traits,Allocator>::size_type nread = 0;
3519    typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
3520    if (sentry) {
3521       std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
3522       s.clear();
3523 
3524       while (nread < s.max_size()) {
3525          int c1 = buf->sbumpc();
3526          if (Traits::eq_int_type(c1, Traits::eof())) {
3527             is.setstate(std::ios_base::eofbit);
3528             break;
3529          }
3530          else {
3531             ++nread;
3532             CharT c = Traits::to_char_type(c1);
3533             if (!Traits::eq(c, delim))
3534                s.push_back(c);
3535             else
3536                break;              // Character is extracted but not appended.
3537          }
3538       }
3539    }
3540    if (nread == 0 || nread >= s.max_size())
3541       is.setstate(std::ios_base::failbit);
3542 
3543    return is;
3544 }
3545 
3546 template <class CharT, class Traits, class Allocator>
3547 inline std::basic_istream<CharT, Traits>&
3548 getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
3549 {
3550    return getline(is, s, '\n');
3551 }
3552 
3553 }}
3554 
3555 //GCC 12 has a regression for array-bounds warnings
3556 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
3557 #pragma GCC diagnostic pop
3558 #endif
3559 
3560 
3561 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3562 
3563 namespace boost {
3564 
3565 //!has_trivial_destructor_after_move<> == true_type
3566 //!specialization for optimizations
3567 template <class C, class T, class Allocator>
3568 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
3569 {
3570    typedef typename boost::container::basic_string<C, T, Allocator>::allocator_type allocator_type;
3571    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3572    BOOST_STATIC_CONSTEXPR bool value =
3573       ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3574       ::boost::has_trivial_destructor_after_move<pointer>::value;
3575 };
3576 
3577 }
3578 
3579 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3580 
3581 #include <boost/container/detail/config_end.hpp>
3582 
3583 #endif // BOOST_CONTAINER_STRING_HPP