1 // Debugging vector implementation -*- C++ -*-
 
    3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
 
    5 // This file is part of the GNU ISO C++ Library.  This library is free
 
    6 // software; you can redistribute it and/or modify it under the
 
    7 // terms of the GNU General Public License as published by the
 
    8 // Free Software Foundation; either version 3, or (at your option)
 
   11 // This library is distributed in the hope that it will be useful,
 
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14 // GNU General Public License for more details.
 
   16 // Under Section 7 of GPL version 3, you are granted additional
 
   17 // permissions described in the GCC Runtime Library Exception, version
 
   18 // 3.1, as published by the Free Software Foundation.
 
   20 // You should have received a copy of the GNU General Public License and
 
   21 // a copy of the GCC Runtime Library Exception along with this program;
 
   22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23 // <http://www.gnu.org/licenses/>.
 
   25 /** @file debug/vector
 
   26  *  This file is a GNU debug extension to the Standard C++ Library.
 
   29 #ifndef _GLIBCXX_DEBUG_VECTOR
 
   30 #define _GLIBCXX_DEBUG_VECTOR 1
 
   34 #include <debug/safe_sequence.h>
 
   35 #include <debug/safe_iterator.h>
 
   37 namespace std _GLIBCXX_VISIBILITY(default)
 
   41   /// Class std::vector with safety/checking/debug instrumentation.
 
   42   template<typename _Tp,
 
   43       typename _Allocator = std::allocator<_Tp> >
 
   45     : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
 
   46       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
 
   48       typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
 
   50       typedef typename _Base::iterator _Base_iterator;
 
   51       typedef typename _Base::const_iterator _Base_const_iterator;
 
   52       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
   54 #if __cplusplus >= 201103L
 
   55       typedef __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> > _Safe_base;
 
   56       typedef __gnu_cxx::__alloc_traits<_Allocator>  _Alloc_traits;
 
   60       typedef typename _Base::reference             reference;
 
   61       typedef typename _Base::const_reference       const_reference;
 
   63       typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector>
 
   65       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector>
 
   68       typedef typename _Base::size_type             size_type;
 
   69       typedef typename _Base::difference_type       difference_type;
 
   71       typedef _Tp                  value_type;
 
   72       typedef _Allocator               allocator_type;
 
   73       typedef typename _Base::pointer               pointer;
 
   74       typedef typename _Base::const_pointer         const_pointer;
 
   75       typedef std::reverse_iterator<iterator>       reverse_iterator;
 
   76       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
   78       // 23.2.4.1 construct/copy/destroy:
 
   80       vector() _GLIBCXX_NOEXCEPT
 
   81       : _Base(), _M_guaranteed_capacity(0) { }
 
   84       vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
 
   85       : _Base(__a), _M_guaranteed_capacity(0) { }
 
   87 #if __cplusplus >= 201103L
 
   89       vector(size_type __n, const _Allocator& __a = _Allocator())
 
   90       : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
 
   92       vector(size_type __n, const _Tp& __value,
 
   93         const _Allocator& __a = _Allocator())
 
   94       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
 
   97       vector(size_type __n, const _Tp& __value = _Tp(),
 
   98         const _Allocator& __a = _Allocator())
 
   99       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
 
  102 #if __cplusplus >= 201103L
 
  103       template<class _InputIterator,
 
  104           typename = std::_RequireInputIter<_InputIterator>>
 
  106       template<class _InputIterator>
 
  108         vector(_InputIterator __first, _InputIterator __last,
 
  109           const _Allocator& __a = _Allocator())
 
  110         : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
 
  112        __gnu_debug::__base(__last), __a),
 
  113      _M_guaranteed_capacity(0)
 
  114         { _M_update_guaranteed_capacity(); }
 
  116       vector(const vector& __x)
 
  117       : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
 
  119       /// Construction from a normal-mode vector
 
  120       vector(const _Base& __x)
 
  121       : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
 
  123 #if __cplusplus >= 201103L
 
  124       vector(vector&& __x) noexcept
 
  125       : _Base(std::move(__x)),
 
  126    _Safe_base(std::move(__x)),
 
  127    _M_guaranteed_capacity(this->size())
 
  128       { __x._M_guaranteed_capacity = 0; }
 
  130       vector(const vector& __x, const allocator_type& __a)
 
  131       : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { }
 
  133       vector(vector&& __x, const allocator_type& __a)
 
  134       : _Base(std::move(__x), __a),
 
  135         _M_guaranteed_capacity(this->size())
 
  137    if (__x.get_allocator() == __a)
 
  140      __x._M_invalidate_all();
 
  141    __x._M_guaranteed_capacity = 0;
 
  144       vector(initializer_list<value_type> __l,
 
  145         const allocator_type& __a = allocator_type())
 
  147    _M_guaranteed_capacity(__l.size()) { }
 
  150       ~vector() _GLIBCXX_NOEXCEPT { }
 
  153       operator=(const vector& __x)
 
  156    this->_M_invalidate_all();
 
  157    _M_update_guaranteed_capacity();
 
  161 #if __cplusplus >= 201103L
 
  163       operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
 
  165    __glibcxx_check_self_move_assign(__x);
 
  166    bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
 
  167        || __x.get_allocator() == this->get_allocator();
 
  168    _M_base() = std::move(__x._M_base());
 
  172      this->_M_invalidate_all();
 
  173    _M_update_guaranteed_capacity();
 
  174    __x._M_invalidate_all();
 
  175    __x._M_guaranteed_capacity = 0;
 
  180       operator=(initializer_list<value_type> __l)
 
  183    this->_M_invalidate_all();
 
  184    _M_update_guaranteed_capacity();
 
  189 #if __cplusplus >= 201103L
 
  190       template<typename _InputIterator,
 
  191           typename = std::_RequireInputIter<_InputIterator>>
 
  193       template<typename _InputIterator>
 
  196         assign(_InputIterator __first, _InputIterator __last)
 
  198      __glibcxx_check_valid_range(__first, __last);
 
  199      _Base::assign(__gnu_debug::__base(__first),
 
  200            __gnu_debug::__base(__last));
 
  201      this->_M_invalidate_all();
 
  202      _M_update_guaranteed_capacity();
 
  206       assign(size_type __n, const _Tp& __u)
 
  208    _Base::assign(__n, __u);
 
  209    this->_M_invalidate_all();
 
  210    _M_update_guaranteed_capacity();
 
  213 #if __cplusplus >= 201103L
 
  215       assign(initializer_list<value_type> __l)
 
  218    this->_M_invalidate_all();
 
  219    _M_update_guaranteed_capacity();
 
  223       using _Base::get_allocator;
 
  227       begin() _GLIBCXX_NOEXCEPT
 
  228       { return iterator(_Base::begin(), this); }
 
  231       begin() const _GLIBCXX_NOEXCEPT
 
  232       { return const_iterator(_Base::begin(), this); }
 
  235       end() _GLIBCXX_NOEXCEPT
 
  236       { return iterator(_Base::end(), this); }
 
  239       end() const _GLIBCXX_NOEXCEPT
 
  240       { return const_iterator(_Base::end(), this); }
 
  243       rbegin() _GLIBCXX_NOEXCEPT
 
  244       { return reverse_iterator(end()); }
 
  246       const_reverse_iterator
 
  247       rbegin() const _GLIBCXX_NOEXCEPT
 
  248       { return const_reverse_iterator(end()); }
 
  251       rend() _GLIBCXX_NOEXCEPT
 
  252       { return reverse_iterator(begin()); }
 
  254       const_reverse_iterator
 
  255       rend() const _GLIBCXX_NOEXCEPT
 
  256       { return const_reverse_iterator(begin()); }
 
  258 #if __cplusplus >= 201103L
 
  260       cbegin() const noexcept
 
  261       { return const_iterator(_Base::begin(), this); }
 
  264       cend() const noexcept
 
  265       { return const_iterator(_Base::end(), this); }
 
  267       const_reverse_iterator
 
  268       crbegin() const noexcept
 
  269       { return const_reverse_iterator(end()); }
 
  271       const_reverse_iterator
 
  272       crend() const noexcept
 
  273       { return const_reverse_iterator(begin()); }
 
  276       // 23.2.4.2 capacity:
 
  278       using _Base::max_size;
 
  280 #if __cplusplus >= 201103L
 
  282       resize(size_type __sz)
 
  284    bool __realloc = _M_requires_reallocation(__sz);
 
  285    if (__sz < this->size())
 
  286      this->_M_invalidate_after_nth(__sz);
 
  289      this->_M_invalidate_all();
 
  290    _M_update_guaranteed_capacity();
 
  294       resize(size_type __sz, const _Tp& __c)
 
  296    bool __realloc = _M_requires_reallocation(__sz);
 
  297    if (__sz < this->size())
 
  298      this->_M_invalidate_after_nth(__sz);
 
  299    _Base::resize(__sz, __c);
 
  301      this->_M_invalidate_all();
 
  302    _M_update_guaranteed_capacity();
 
  306       resize(size_type __sz, _Tp __c = _Tp())
 
  308    bool __realloc = _M_requires_reallocation(__sz);
 
  309    if (__sz < this->size())
 
  310      this->_M_invalidate_after_nth(__sz);
 
  311    _Base::resize(__sz, __c);
 
  313      this->_M_invalidate_all();
 
  314    _M_update_guaranteed_capacity();
 
  318 #if __cplusplus >= 201103L
 
  322    if (_Base::_M_shrink_to_fit())
 
  324        _M_guaranteed_capacity = _Base::capacity();
 
  325        this->_M_invalidate_all();
 
  331       capacity() const _GLIBCXX_NOEXCEPT
 
  333 #ifdef _GLIBCXX_DEBUG_PEDANTIC
 
  334    return _M_guaranteed_capacity;
 
  336    return _Base::capacity();
 
  343       reserve(size_type __n)
 
  345    bool __realloc = _M_requires_reallocation(__n);
 
  347    if (__n > _M_guaranteed_capacity)
 
  348      _M_guaranteed_capacity = __n;
 
  350      this->_M_invalidate_all();
 
  355       operator[](size_type __n) _GLIBCXX_NOEXCEPT
 
  357    __glibcxx_check_subscript(__n);
 
  358    return _M_base()[__n];
 
  362       operator[](size_type __n) const _GLIBCXX_NOEXCEPT
 
  364    __glibcxx_check_subscript(__n);
 
  365    return _M_base()[__n];
 
  371       front() _GLIBCXX_NOEXCEPT
 
  373    __glibcxx_check_nonempty();
 
  374    return _Base::front();
 
  378       front() const _GLIBCXX_NOEXCEPT
 
  380    __glibcxx_check_nonempty();
 
  381    return _Base::front();
 
  385       back() _GLIBCXX_NOEXCEPT
 
  387    __glibcxx_check_nonempty();
 
  388    return _Base::back();
 
  392       back() const _GLIBCXX_NOEXCEPT
 
  394    __glibcxx_check_nonempty();
 
  395    return _Base::back();
 
  398       // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  399       // DR 464. Suggestion for new member functions in standard containers.
 
  402       // 23.2.4.3 modifiers:
 
  404       push_back(const _Tp& __x)
 
  406    bool __realloc = _M_requires_reallocation(this->size() + 1);
 
  407    _Base::push_back(__x);
 
  409      this->_M_invalidate_all();
 
  410    _M_update_guaranteed_capacity();
 
  413 #if __cplusplus >= 201103L
 
  414       template<typename _Up = _Tp>
 
  415         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
 
  418    { emplace_back(std::move(__x)); }
 
  420       template<typename... _Args>
 
  422         emplace_back(_Args&&... __args)
 
  424      bool __realloc = _M_requires_reallocation(this->size() + 1);
 
  425      _Base::emplace_back(std::forward<_Args>(__args)...);
 
  427        this->_M_invalidate_all();
 
  428      _M_update_guaranteed_capacity();
 
  433       pop_back() _GLIBCXX_NOEXCEPT
 
  435    __glibcxx_check_nonempty();
 
  436    this->_M_invalidate_if(_Equal(--_Base::end()));
 
  440 #if __cplusplus >= 201103L
 
  441       template<typename... _Args>
 
  443         emplace(const_iterator __position, _Args&&... __args)
 
  445      __glibcxx_check_insert(__position);
 
  446      bool __realloc = _M_requires_reallocation(this->size() + 1);
 
  447      difference_type __offset = __position.base() - _Base::begin();
 
  448      _Base_iterator __res = _Base::emplace(__position.base(),
 
  449                        std::forward<_Args>(__args)...);
 
  451        this->_M_invalidate_all();
 
  453        this->_M_invalidate_after_nth(__offset);
 
  454      _M_update_guaranteed_capacity();
 
  455      return iterator(__res, this);
 
  460 #if __cplusplus >= 201103L
 
  461       insert(const_iterator __position, const _Tp& __x)
 
  463       insert(iterator __position, const _Tp& __x)
 
  466    __glibcxx_check_insert(__position);
 
  467    bool __realloc = _M_requires_reallocation(this->size() + 1);
 
  468    difference_type __offset = __position.base() - _Base::begin();
 
  469    _Base_iterator __res = _Base::insert(__position.base(), __x);
 
  471      this->_M_invalidate_all();
 
  473      this->_M_invalidate_after_nth(__offset);
 
  474    _M_update_guaranteed_capacity();
 
  475    return iterator(__res, this);
 
  478 #if __cplusplus >= 201103L
 
  479       template<typename _Up = _Tp>
 
  480         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
 
  482         insert(const_iterator __position, _Tp&& __x)
 
  483         { return emplace(__position, std::move(__x)); }
 
  486       insert(const_iterator __position, initializer_list<value_type> __l)
 
  487       { return this->insert(__position, __l.begin(), __l.end()); }
 
  490 #if __cplusplus >= 201103L
 
  492       insert(const_iterator __position, size_type __n, const _Tp& __x)
 
  494    __glibcxx_check_insert(__position);
 
  495    bool __realloc = _M_requires_reallocation(this->size() + __n);
 
  496    difference_type __offset = __position.base() - _Base::cbegin();
 
  497    _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
 
  499      this->_M_invalidate_all();
 
  501      this->_M_invalidate_after_nth(__offset);
 
  502    _M_update_guaranteed_capacity();
 
  503    return iterator(__res, this);
 
  507       insert(iterator __position, size_type __n, const _Tp& __x)
 
  509    __glibcxx_check_insert(__position);
 
  510    bool __realloc = _M_requires_reallocation(this->size() + __n);
 
  511    difference_type __offset = __position.base() - _Base::begin();
 
  512    _Base::insert(__position.base(), __n, __x);
 
  514      this->_M_invalidate_all();
 
  516      this->_M_invalidate_after_nth(__offset);
 
  517    _M_update_guaranteed_capacity();
 
  521 #if __cplusplus >= 201103L
 
  522       template<class _InputIterator,
 
  523           typename = std::_RequireInputIter<_InputIterator>>
 
  525         insert(const_iterator __position,
 
  526           _InputIterator __first, _InputIterator __last)
 
  528      __glibcxx_check_insert_range(__position, __first, __last);
 
  530      /* Hard to guess if invalidation will occur, because __last
 
  531         - __first can't be calculated in all cases, so we just
 
  532         punt here by checking if it did occur. */
 
  533      _Base_iterator __old_begin = _M_base().begin();
 
  534      difference_type __offset = __position.base() - _Base::cbegin();
 
  535      _Base_iterator __res = _Base::insert(__position.base(),
 
  536                           __gnu_debug::__base(__first),
 
  537                           __gnu_debug::__base(__last));
 
  539      if (_M_base().begin() != __old_begin)
 
  540        this->_M_invalidate_all();
 
  542        this->_M_invalidate_after_nth(__offset);
 
  543      _M_update_guaranteed_capacity();
 
  544      return iterator(__res, this);
 
  547       template<class _InputIterator>
 
  549         insert(iterator __position,
 
  550           _InputIterator __first, _InputIterator __last)
 
  552      __glibcxx_check_insert_range(__position, __first, __last);
 
  554      /* Hard to guess if invalidation will occur, because __last
 
  555         - __first can't be calculated in all cases, so we just
 
  556         punt here by checking if it did occur. */
 
  557      _Base_iterator __old_begin = _M_base().begin();
 
  558      difference_type __offset = __position.base() - _Base::begin();
 
  559      _Base::insert(__position.base(), __gnu_debug::__base(__first),
 
  560                       __gnu_debug::__base(__last));
 
  562      if (_M_base().begin() != __old_begin)
 
  563        this->_M_invalidate_all();
 
  565        this->_M_invalidate_after_nth(__offset);
 
  566      _M_update_guaranteed_capacity();
 
  571 #if __cplusplus >= 201103L
 
  572       erase(const_iterator __position)
 
  574       erase(iterator __position)
 
  577    __glibcxx_check_erase(__position);
 
  578    difference_type __offset = __position.base() - _Base::begin();
 
  579    _Base_iterator __res = _Base::erase(__position.base());
 
  580    this->_M_invalidate_after_nth(__offset);
 
  581    return iterator(__res, this);
 
  585 #if __cplusplus >= 201103L
 
  586       erase(const_iterator __first, const_iterator __last)
 
  588       erase(iterator __first, iterator __last)
 
  591    // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  592    // 151. can't currently clear() empty container
 
  593    __glibcxx_check_erase_range(__first, __last);
 
  595    if (__first.base() != __last.base())
 
  597        difference_type __offset = __first.base() - _Base::begin();
 
  598        _Base_iterator __res = _Base::erase(__first.base(),
 
  600        this->_M_invalidate_after_nth(__offset);
 
  601        return iterator(__res, this);
 
  604 #if __cplusplus >= 201103L
 
  605      return begin() + (__first.base() - cbegin().base());
 
  613 #if __cplusplus >= 201103L
 
  614            noexcept(_Alloc_traits::_S_nothrow_swap())
 
  617 #if __cplusplus >= 201103L
 
  618    if (!_Alloc_traits::_S_propagate_on_swap())
 
  619      __glibcxx_check_equal_allocs(__x);
 
  623         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
 
  627       clear() _GLIBCXX_NOEXCEPT
 
  630    this->_M_invalidate_all();
 
  631         _M_guaranteed_capacity = 0;
 
  635       _M_base() _GLIBCXX_NOEXCEPT { return *this; }
 
  638       _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
 
  641       size_type _M_guaranteed_capacity;
 
  644       _M_requires_reallocation(size_type __elements) _GLIBCXX_NOEXCEPT
 
  645       { return __elements > this->capacity(); }
 
  648       _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
 
  650    if (this->size() > _M_guaranteed_capacity)
 
  651      _M_guaranteed_capacity = this->size();
 
  655       _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
 
  657    typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
 
  658    this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
 
  662   template<typename _Tp, typename _Alloc>
 
  664     operator==(const vector<_Tp, _Alloc>& __lhs,
 
  665           const vector<_Tp, _Alloc>& __rhs)
 
  666     { return __lhs._M_base() == __rhs._M_base(); }
 
  668   template<typename _Tp, typename _Alloc>
 
  670     operator!=(const vector<_Tp, _Alloc>& __lhs,
 
  671           const vector<_Tp, _Alloc>& __rhs)
 
  672     { return __lhs._M_base() != __rhs._M_base(); }
 
  674   template<typename _Tp, typename _Alloc>
 
  676     operator<(const vector<_Tp, _Alloc>& __lhs,
 
  677          const vector<_Tp, _Alloc>& __rhs)
 
  678     { return __lhs._M_base() < __rhs._M_base(); }
 
  680   template<typename _Tp, typename _Alloc>
 
  682     operator<=(const vector<_Tp, _Alloc>& __lhs,
 
  683           const vector<_Tp, _Alloc>& __rhs)
 
  684     { return __lhs._M_base() <= __rhs._M_base(); }
 
  686   template<typename _Tp, typename _Alloc>
 
  688     operator>=(const vector<_Tp, _Alloc>& __lhs,
 
  689           const vector<_Tp, _Alloc>& __rhs)
 
  690     { return __lhs._M_base() >= __rhs._M_base(); }
 
  692   template<typename _Tp, typename _Alloc>
 
  694     operator>(const vector<_Tp, _Alloc>& __lhs,
 
  695          const vector<_Tp, _Alloc>& __rhs)
 
  696     { return __lhs._M_base() > __rhs._M_base(); }
 
  698   template<typename _Tp, typename _Alloc>
 
  700     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
 
  701     { __lhs.swap(__rhs); }
 
  703 } // namespace __debug
 
  705 #if __cplusplus >= 201103L
 
  707   /// std::hash specialization for vector<bool>.
 
  708   template<typename _Alloc>
 
  709     struct hash<__debug::vector<bool, _Alloc>>
 
  710     : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
 
  713       operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
 
  714       { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
 
  721 namespace __gnu_debug
 
  723   template<typename _Tp, typename _Alloc>
 
  724     struct _Is_contiguous_sequence<std::__debug::vector<_Tp, _Alloc> >
 
  728   template<typename _Alloc>
 
  729     struct _Is_contiguous_sequence<std::__debug::vector<bool, _Alloc> >