Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:28:50

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