|
@@ -0,0 +1,483 @@
|
|
|
|
+#ifndef __GBLIBCPP_VECTOR__
|
|
|
|
+#define __GBLIBCPP_VECTOR__
|
|
|
|
+
|
|
|
|
+#include <functional>
|
|
|
|
+#include <memory>
|
|
|
|
+#include <initializer_list>
|
|
|
|
+#include <cstddef>
|
|
|
|
+
|
|
|
|
+namespace std {
|
|
|
|
+
|
|
|
|
+template <typename T, typename Allocator = std::allocator<T>>
|
|
|
|
+class vector {
|
|
|
|
+public:
|
|
|
|
+ using value_type = T;
|
|
|
|
+ using allocator_type = Allocator;
|
|
|
|
+ using size_type = std::size_t;
|
|
|
|
+ using difference_type = std::ptrdiff_t;
|
|
|
|
+ using reference = T&;
|
|
|
|
+ using const_reference = const T&;
|
|
|
|
+
|
|
|
|
+ template <bool Const>
|
|
|
|
+ class _iterator {
|
|
|
|
+ public:
|
|
|
|
+ // TODO:
|
|
|
|
+ // using iterator_category = std::random_access_iterator_tag;
|
|
|
|
+ using value_type = std::conditional_t<Const, const T, T>;
|
|
|
|
+ using difference_type = std::ptrdiff_t;
|
|
|
|
+ using pointer = std::add_pointer_t<value_type>;
|
|
|
|
+ using reference = std::add_lvalue_reference_t<value_type>;
|
|
|
|
+
|
|
|
|
+ private:
|
|
|
|
+ T* m_ptr;
|
|
|
|
+
|
|
|
|
+ public:
|
|
|
|
+ constexpr _iterator(void) noexcept : m_ptr() {}
|
|
|
|
+ constexpr explicit _iterator(const T* ptr) noexcept
|
|
|
|
+ : m_ptr(const_cast<T*>(ptr)) {}
|
|
|
|
+ constexpr _iterator(const _iterator& other) noexcept = default;
|
|
|
|
+ constexpr _iterator(_iterator&& other) noexcept = default;
|
|
|
|
+ constexpr _iterator& operator=(const _iterator& other) noexcept = default;
|
|
|
|
+ constexpr _iterator& operator=(_iterator&& other) noexcept = default;
|
|
|
|
+ constexpr bool operator==(const _iterator& other) const noexcept = default;
|
|
|
|
+
|
|
|
|
+ constexpr reference operator*() const noexcept { return *m_ptr; }
|
|
|
|
+ constexpr pointer operator&() const noexcept
|
|
|
|
+ { return std::addressof(this->operator*()); }
|
|
|
|
+ constexpr pointer operator->() const noexcept
|
|
|
|
+ { return this->operator&(); }
|
|
|
|
+ constexpr _iterator& operator++() noexcept
|
|
|
|
+ { ++m_ptr; return *this; }
|
|
|
|
+ constexpr _iterator operator++(int) noexcept
|
|
|
|
+ { _iterator ret(m_ptr); (void)this->operator++(); return ret; }
|
|
|
|
+ constexpr _iterator& operator--(void) noexcept
|
|
|
|
+ { --m_ptr; return *this; }
|
|
|
|
+ constexpr _iterator operator--(int) noexcept
|
|
|
|
+ { _iterator ret(m_ptr); (void)this->operator--(); return ret; }
|
|
|
|
+ constexpr operator bool() { return m_ptr; }
|
|
|
|
+ constexpr operator _iterator<true>() { return _iterator<true> { m_ptr }; }
|
|
|
|
+ constexpr operator _iterator<false>() { return _iterator<false> { m_ptr }; }
|
|
|
|
+ constexpr operator const T*() { return m_ptr; }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ using alloc_traits = std::allocator_traits<Allocator>;
|
|
|
|
+
|
|
|
|
+public:
|
|
|
|
+ using pointer = typename alloc_traits::pointer;
|
|
|
|
+ using const_pointer = typename alloc_traits::const_pointer;
|
|
|
|
+ using iterator = _iterator<false>;
|
|
|
|
+ using const_iterator = _iterator<true>;
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ T* m_data;
|
|
|
|
+ size_type m_size;
|
|
|
|
+ size_type m_capacity;
|
|
|
|
+ allocator_type m_alloc;
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ // assert(n >= m_size)
|
|
|
|
+ constexpr void _reallocate_safe(size_type n)
|
|
|
|
+ {
|
|
|
|
+ auto* newptr = alloc_traits::allocate(m_alloc, n);
|
|
|
|
+ for (size_t i = 0; i < m_size; ++i) {
|
|
|
|
+ alloc_traits::construct(m_alloc, newptr + i, std::move(m_data[i]));
|
|
|
|
+ alloc_traits::destroy(m_alloc, m_data + i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ alloc_traits::deallocate(m_alloc, m_data, m_capacity);
|
|
|
|
+ m_data = newptr;
|
|
|
|
+ m_capacity = n;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // make m_capacity >= n >= m_size
|
|
|
|
+ constexpr void _pre_resize(size_type n)
|
|
|
|
+ {
|
|
|
|
+ if (n < m_size) {
|
|
|
|
+ while (n < m_size)
|
|
|
|
+ pop_back();
|
|
|
|
+ }
|
|
|
|
+ else if (n > m_size) {
|
|
|
|
+ reserve(n);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+public:
|
|
|
|
+ constexpr vector(void)
|
|
|
|
+ noexcept(noexcept(Allocator()))
|
|
|
|
+ : m_data(), m_size(), m_capacity(), m_alloc() {}
|
|
|
|
+
|
|
|
|
+ constexpr explicit vector(const Allocator& alloc) noexcept
|
|
|
|
+ : m_data(), m_size(), m_capacity(), m_alloc(alloc) {}
|
|
|
|
+
|
|
|
|
+ constexpr vector(size_type n, const T& val,
|
|
|
|
+ const Allocator& alloc = Allocator())
|
|
|
|
+ : vector(alloc) { resize(n, val); }
|
|
|
|
+
|
|
|
|
+ constexpr explicit vector(size_type n,
|
|
|
|
+ const Allocator& alloc = Allocator())
|
|
|
|
+ : vector(alloc) { resize(n); }
|
|
|
|
+
|
|
|
|
+ // TODO: check whether InputIter satisfies LegacyInputIterator
|
|
|
|
+ template <typename InputIter>
|
|
|
|
+ constexpr vector(InputIter first, InputIter last,
|
|
|
|
+ const Allocator& alloc = Allocator())
|
|
|
|
+ : vector(alloc) { insert(cbegin(), first, last); }
|
|
|
|
+
|
|
|
|
+ constexpr vector(const vector& other)
|
|
|
|
+ : vector(std::allocator_traits<allocator_type>::
|
|
|
|
+ select_on_container_copy_construction(other.m_alloc))
|
|
|
|
+ { insert(cbegin(), other.begin(), other.end()); }
|
|
|
|
+
|
|
|
|
+ constexpr vector(const vector& other, const Allocator& alloc)
|
|
|
|
+ : vector(alloc) { insert(cbegin(), other.begin(), other.end()); }
|
|
|
|
+
|
|
|
|
+ constexpr vector(vector&& other) noexcept
|
|
|
|
+ : m_data(std::exchange(other.m_data, nullptr))
|
|
|
|
+ , m_size(std::exchange(other.m_size, 0))
|
|
|
|
+ , m_capacity(std::exchange(other.m_capacity, 0))
|
|
|
|
+ , m_alloc(std::move(other.m_alloc)) {}
|
|
|
|
+
|
|
|
|
+ constexpr vector(vector&& other, const Allocator& alloc)
|
|
|
|
+ : vector(alloc)
|
|
|
|
+ {
|
|
|
|
+ if (alloc == other.get_allocator()) {
|
|
|
|
+ m_data = std::exchange(other.m_data, nullptr);
|
|
|
|
+ m_size = std::exchange(other.m_size, 0);
|
|
|
|
+ m_capacity = std::exchange(other.m_capacity, 0);
|
|
|
|
+ } else {
|
|
|
|
+ // TODO: std::move_iterator
|
|
|
|
+ // insert(cbegin(), std::make_move_iterator(other.begin()),
|
|
|
|
+ // std::make_move_iterator(other.end()));
|
|
|
|
+ for (auto& item : other)
|
|
|
|
+ emplace_back(std::move(item));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr vector(std::initializer_list<T> init,
|
|
|
|
+ const Allocator& alloc = Allocator())
|
|
|
|
+ : vector(alloc) { insert(cbegin(), init.begin(), init.end()); }
|
|
|
|
+
|
|
|
|
+ constexpr ~vector()
|
|
|
|
+ {
|
|
|
|
+ resize(0);
|
|
|
|
+ shrink_to_fit();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ vector& operator=(const vector& other)
|
|
|
|
+ {
|
|
|
|
+ clear();
|
|
|
|
+
|
|
|
|
+ if constexpr (alloc_traits::
|
|
|
|
+ propagate_on_container_copy_assignment::value) {
|
|
|
|
+ if (m_alloc != other.m_alloc)
|
|
|
|
+ shrink_to_fit();
|
|
|
|
+ m_alloc = other.m_alloc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ insert(cbegin(), other.begin(), other.end());
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ vector& operator=(vector&& other)
|
|
|
|
+ {
|
|
|
|
+ clear();
|
|
|
|
+
|
|
|
|
+ if constexpr (alloc_traits::
|
|
|
|
+ propagate_on_container_move_assignment::value) {
|
|
|
|
+ shrink_to_fit();
|
|
|
|
+ m_alloc = std::move(other.m_alloc);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ if (m_alloc != other.m_alloc) {
|
|
|
|
+ // TODO: std::move_iterator
|
|
|
|
+ for (auto& item : other)
|
|
|
|
+ emplace_back(std::move(item));
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+ shrink_to_fit();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ m_data = std::exchange(other.m_data, nullptr);
|
|
|
|
+ m_size = std::exchange(other.m_size, 0);
|
|
|
|
+ m_capacity = std::exchange(other.m_capacity, 0);
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ vector& operator=(std::initializer_list<T> init)
|
|
|
|
+ {
|
|
|
|
+ assign(init.begin(), init.end());
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr void assign(size_type n, const T& val)
|
|
|
|
+ {
|
|
|
|
+ clear();
|
|
|
|
+ resize(n, val);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: check whether InputIter satisfies LegacyInputIterator
|
|
|
|
+ template <typename InputIter>
|
|
|
|
+ constexpr void assign(InputIter first, InputIter last)
|
|
|
|
+ {
|
|
|
|
+ clear();
|
|
|
|
+ insert(cbegin(), first, last);
|
|
|
|
+ }
|
|
|
|
+ constexpr void assign(std::initializer_list<T> init)
|
|
|
|
+ {
|
|
|
|
+ clear();
|
|
|
|
+ insert(cbegin(), init.begin(), init.end());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr allocator_type get_allocator(void) const noexcept
|
|
|
|
+ { return m_alloc; }
|
|
|
|
+
|
|
|
|
+ constexpr reference at(size_type pos)
|
|
|
|
+ {
|
|
|
|
+ // TODO: exceptions
|
|
|
|
+ // if (pos >= sz)
|
|
|
|
+ // throw std::out_of_range("vector::at");
|
|
|
|
+ return m_data[pos];
|
|
|
|
+ }
|
|
|
|
+ constexpr const_reference at(size_type pos) const
|
|
|
|
+ {
|
|
|
|
+ // TODO: exceptions
|
|
|
|
+ // if (pos >= sz)
|
|
|
|
+ // throw std::out_of_range("vector::at");
|
|
|
|
+ return m_data[pos];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr reference operator[](size_type pos) noexcept
|
|
|
|
+ { return m_data[pos]; }
|
|
|
|
+ constexpr const_reference operator[](size_type pos) const noexcept
|
|
|
|
+ { return m_data[pos]; }
|
|
|
|
+
|
|
|
|
+ constexpr reference front() noexcept
|
|
|
|
+ { return m_data[0]; }
|
|
|
|
+ constexpr const_reference front() const noexcept
|
|
|
|
+ { return m_data[0]; }
|
|
|
|
+ constexpr reference back() noexcept
|
|
|
|
+ { return m_data[m_size - 1]; }
|
|
|
|
+ constexpr const_reference back() const noexcept
|
|
|
|
+ { return m_data[m_size - 1]; }
|
|
|
|
+
|
|
|
|
+ constexpr T* data(void) noexcept
|
|
|
|
+ { return m_data; }
|
|
|
|
+ constexpr const T* data(void) const noexcept
|
|
|
|
+ { return m_data; }
|
|
|
|
+
|
|
|
|
+ // TODO: std::reverse_iterator
|
|
|
|
+ constexpr iterator begin() noexcept
|
|
|
|
+ { return iterator { m_data }; }
|
|
|
|
+ constexpr const_iterator begin() const noexcept
|
|
|
|
+ { return const_iterator { m_data }; }
|
|
|
|
+ constexpr const_iterator cbegin() const noexcept
|
|
|
|
+ { return const_iterator { m_data }; }
|
|
|
|
+ constexpr iterator end() noexcept
|
|
|
|
+ { return iterator { m_data + m_size }; }
|
|
|
|
+ constexpr const_iterator end() const noexcept
|
|
|
|
+ { return const_iterator { m_data + m_size }; }
|
|
|
|
+ constexpr const_iterator cend() const noexcept
|
|
|
|
+ { return const_iterator { m_data + m_size }; }
|
|
|
|
+
|
|
|
|
+ [[nodiscard]] constexpr bool empty() const noexcept
|
|
|
|
+ { return m_size == 0; }
|
|
|
|
+ constexpr size_type size() const noexcept
|
|
|
|
+ { return m_size; }
|
|
|
|
+ constexpr size_type capacity() const noexcept
|
|
|
|
+ { return m_capacity; }
|
|
|
|
+
|
|
|
|
+ constexpr void reserve(size_type new_cap)
|
|
|
|
+ {
|
|
|
|
+ if (new_cap > m_capacity)
|
|
|
|
+ _reallocate_safe(new_cap);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr void resize(size_type n)
|
|
|
|
+ {
|
|
|
|
+ _pre_resize(n);
|
|
|
|
+ while (n > m_size)
|
|
|
|
+ emplace_back();
|
|
|
|
+ }
|
|
|
|
+ constexpr void resize(size_type n, const value_type& value)
|
|
|
|
+ {
|
|
|
|
+ _pre_resize(n);
|
|
|
|
+ while (n > m_size)
|
|
|
|
+ emplace_back(value);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr void shrink_to_fit()
|
|
|
|
+ {
|
|
|
|
+ if (m_size != m_capacity)
|
|
|
|
+ _reallocate_safe(m_size);
|
|
|
|
+ }
|
|
|
|
+ constexpr void clear() noexcept
|
|
|
|
+ { resize(0); }
|
|
|
|
+
|
|
|
|
+ template <typename... Args>
|
|
|
|
+ constexpr iterator emplace(const_iterator pos, Args&&... args)
|
|
|
|
+ {
|
|
|
|
+ size_type idx = pos - m_data;
|
|
|
|
+
|
|
|
|
+ if (!pos)
|
|
|
|
+ reserve(1);
|
|
|
|
+
|
|
|
|
+ if (m_size == m_capacity)
|
|
|
|
+ reserve(m_capacity * 2);
|
|
|
|
+
|
|
|
|
+ for (size_type i = m_size; i > idx; --i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-1]));
|
|
|
|
+
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + idx,
|
|
|
|
+ std::forward<Args>(args)...);
|
|
|
|
+
|
|
|
|
+ ++m_size;
|
|
|
|
+ return iterator { m_data + idx };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr iterator insert(const_iterator pos, T&& val)
|
|
|
|
+ { return emplace(pos, std::move(val)); }
|
|
|
|
+ constexpr iterator insert(const_iterator pos, const T& val)
|
|
|
|
+ { return emplace(pos, val); }
|
|
|
|
+
|
|
|
|
+ constexpr iterator insert(const_iterator pos, size_type n, const T& val)
|
|
|
|
+ {
|
|
|
|
+ if (!n)
|
|
|
|
+ return pos;
|
|
|
|
+
|
|
|
|
+ size_type idx = pos - m_data;
|
|
|
|
+ if (!pos)
|
|
|
|
+ reserve(n);
|
|
|
|
+
|
|
|
|
+ if (m_size + n > m_capacity)
|
|
|
|
+ reserve(m_capacity * 2);
|
|
|
|
+ for (size_type i = m_size + n - 1; i >= idx + n; --i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
|
|
|
|
+ for (size_type i = idx; i < idx + n; ++i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, val);
|
|
|
|
+ m_size += n;
|
|
|
|
+ return iterator { m_data + idx };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: LegacyInputIterator version of this
|
|
|
|
+ template <typename ForwardIter>
|
|
|
|
+ constexpr iterator insert(const_iterator pos,
|
|
|
|
+ ForwardIter first, ForwardIter last)
|
|
|
|
+ {
|
|
|
|
+ size_type idx = pos - m_data;
|
|
|
|
+ size_type n = 0;
|
|
|
|
+
|
|
|
|
+ ForwardIter tmp = first;
|
|
|
|
+ while (tmp != last)
|
|
|
|
+ ++n, ++tmp;
|
|
|
|
+
|
|
|
|
+ if (!n)
|
|
|
|
+ return pos;
|
|
|
|
+
|
|
|
|
+ if (!pos)
|
|
|
|
+ reserve(n);
|
|
|
|
+
|
|
|
|
+ if (m_size + n > m_capacity)
|
|
|
|
+ reserve(m_capacity * 2);
|
|
|
|
+ for (size_type i = m_size + n - 1; i >= idx + n; --i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
|
|
|
|
+ for (size_type i = idx; i < idx + n; ++i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, *first++);
|
|
|
|
+ m_size += n;
|
|
|
|
+ return iterator { m_data + idx };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr iterator insert(const_iterator pos, std::initializer_list<T> init)
|
|
|
|
+ { return insert(pos, init.begin(), init.end()); }
|
|
|
|
+
|
|
|
|
+ constexpr iterator erase(const_iterator pos)
|
|
|
|
+ {
|
|
|
|
+ size_type idx = pos - m_data;
|
|
|
|
+ alloc_traits::destroy(m_alloc, m_data + idx);
|
|
|
|
+ for (size_type i = idx; i < m_size - 1; ++i)
|
|
|
|
+ alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i+1]));
|
|
|
|
+ --m_size;
|
|
|
|
+ return iterator { m_data + idx };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr iterator erase(const_iterator first, const_iterator last)
|
|
|
|
+ {
|
|
|
|
+ size_type n = last - first;
|
|
|
|
+ if (!n)
|
|
|
|
+ return last;
|
|
|
|
+
|
|
|
|
+ size_type idx = first - m_data;
|
|
|
|
+ for (size_type i = idx; i < idx + n; ++i)
|
|
|
|
+ alloc_traits::destroy(m_alloc, m_data + i);
|
|
|
|
+
|
|
|
|
+ for (size_type i = idx; i < m_size - n; ++i)
|
|
|
|
+ m_alloc.construct(m_data + i, std::move(m_data[i+n]));
|
|
|
|
+
|
|
|
|
+ m_size -= n;
|
|
|
|
+ return iterator { m_data + idx };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ constexpr void push_back(const T& val) { insert(cend(), val); }
|
|
|
|
+ constexpr void push_back(T&& val) { insert(cend(), std::move(val)); }
|
|
|
|
+
|
|
|
|
+ template <typename... Args>
|
|
|
|
+ constexpr void emplace_back(Args&&... args)
|
|
|
|
+ { emplace(cend(), std::forward<Args>(args)...); }
|
|
|
|
+
|
|
|
|
+ constexpr void pop_back() { erase(--cend()); }
|
|
|
|
+
|
|
|
|
+ constexpr void swap(vector& other) noexcept(
|
|
|
|
+ alloc_traits::propagate_on_container_swap::value
|
|
|
|
+ || alloc_traits::is_always_equal::value)
|
|
|
|
+ {
|
|
|
|
+ if (alloc_traits::propagate_on_container_swap::value)
|
|
|
|
+ std::swap(m_alloc, other.m_alloc);
|
|
|
|
+ std::swap(m_data, other.m_data);
|
|
|
|
+ std::swap(m_size, other.m_size);
|
|
|
|
+ std::swap(m_capacity, other.m_capacity);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+template <typename T, typename Allocator>
|
|
|
|
+constexpr void swap(
|
|
|
|
+ std::vector<T, Allocator>& lhs,
|
|
|
|
+ std::vector<T, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)))
|
|
|
|
+{ lhs.swap(rhs); }
|
|
|
|
+
|
|
|
|
+template <typename T, typename Allocator, typename U>
|
|
|
|
+constexpr typename std::vector<T, Allocator>::size_type
|
|
|
|
+erase(std::vector<T, Allocator>& vec, const U& value)
|
|
|
|
+{
|
|
|
|
+ typename std::vector<T, Allocator>::size_type n = 0;
|
|
|
|
+
|
|
|
|
+ for (auto iter = vec.begin(); iter != vec.end(); ) {
|
|
|
|
+ if (*iter == value) {
|
|
|
|
+ iter = vec.erase(iter);
|
|
|
|
+ ++n;
|
|
|
|
+ } else {
|
|
|
|
+ ++iter;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return n;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <typename T, typename Allocator, typename Pred>
|
|
|
|
+constexpr typename std::vector<T, Allocator>::size_type
|
|
|
|
+erase_if(std::vector<T, Allocator>& vec, Pred pred)
|
|
|
|
+{
|
|
|
|
+ typename std::vector<T, Allocator>::size_type n = 0;
|
|
|
|
+
|
|
|
|
+ for (auto iter = vec.begin(); iter != vec.end(); ) {
|
|
|
|
+ if (pred(*iter)) {
|
|
|
|
+ iter = vec.erase(iter);
|
|
|
|
+ ++n;
|
|
|
|
+ } else {
|
|
|
|
+ ++iter;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return n;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+} // namespace std
|
|
|
|
+
|
|
|
|
+#endif
|