Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:22

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