// -*- c++ -*- #pragma once #include #include #include #include #include #include #include #include namespace std { template class vector { T *data_; std::size_t size_, cap_; public: typedef T value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef T* iterator; typedef const T* const_iterator; typedef std::size_t size_type; typedef std::size_t difference_type; vector() : data_(), size_(0), cap_(0) { } template vector(InputIterator first, InputIterator last) : vector() { for (; first != last; ++first) push_back(*first); } vector(const vector &x) : vector() { *this = x; } vector(vector &&x) : data_(x.data_), size_(x.size_), cap_(x.cap_) { x.data_ = nullptr; x.size_ = x.cap_ = 0; } vector(std::initializer_list elts) : vector() { reserve(elts.size()); for (auto it = elts.begin(), last = elts.end(); it != last; ++it) push_back(*it); } ~vector() { clear(); if (data_) delete[] reinterpret_cast(data_); } vector& operator=(const vector &x) { if (&x != this) { reserve(x.size()); for (auto &elt : x) push_back(elt); } return *this; } vector& operator=(vector &&x) { clear(); x.swap(*this); return *this; } iterator begin() noexcept { return data(); } const_iterator begin() const noexcept { return data(); } iterator end() noexcept { return data() + size_; } const_iterator end() const noexcept { return data() + size_; } const_iterator cbegin() const noexcept { return data(); } const_iterator cend() const noexcept { return data() + size_; } size_type size() const { return size_; } size_type max_size() const noexcept { return (size_type)-1; } size_type capacity() const noexcept { return cap_; } bool empty() const noexcept { return size_ == 0; } void reserve(size_type n) { if (n <= cap_) return; size_type ncap = cap_ == 0 ? 1 : cap_; while (ncap < n) ncap *= 2; auto ndata = reinterpret_cast(new char[sizeof(T) * ncap]); for (size_type i = 0; i < size_; ++i) new (&ndata[i]) T(std::move(data()[i])); data_ = ndata; cap_ = ncap; } reference operator[](size_type n) { return *(data() + n); } const_reference operator[](size_type n) const { return *(data() + n); } const_reference at(size_type n) const { if (n >= size_) throw std::out_of_range("index exceeds size"); return *(data() + n); } reference at(size_type n) { if (n >= size_) throw std::out_of_range("index exceeds size"); return *(data() + n); } reference front() { return *data(); } const_reference front() const { return *data(); } reference back() { return *(data() + size_ - 1); } const_reference back() const { return *(data() + size_ - 1); } T* data() noexcept { return data_; } const T* data() const noexcept { return data_; } template void emplace_back(Args&&... args) { reserve(size_ + 1); new (end()) T(std::forward(args)...); ++size_; } void push_back(const T& x) { emplace_back(x); } void push_back(T&& x) { emplace_back(std::move(x)); } void pop_back() { if (!empty()) { back().~T(); --size_; } } template iterator emplace(const_iterator position, Args&&... args) { iterator it = end(); if (it == position) { // The general logic is wrong for end emplacement emplace_back(std::forward(args)...); } else { size_type pos = position - front(); reserve(size_ + 1); position = front() + pos; // Construct a new last element it = end(); new (it) T(std::move(*(it - 1))); ++size_; // Shift all of the elements between position and end for (--it; it > position; --it) *it = std::move(*(it - 1)); // Construct and move-assign new element. *it = T(std::forward(args)...); } return it; } iterator erase(const_iterator position) { // Shift everything between position and end down auto pos = begin() + (position - begin()); auto nend = std::move(pos + 1, end(), pos); // Destruct last element nend->~T(); --size_; return pos; } iterator erase(const_iterator first, const_iterator last) { // Shift everything down auto pos = begin() + (first - begin()), dst = pos, src = begin() + (last - begin()); if (src != dst) { auto nend = std::move(src, end(), dst); // Destruct remaining elements size_t n = 0; for (; nend != end(); ++nend, ++n) nend->~T(); size_ -= n; } return pos; } void swap(vector &x) { std::swap(data_, x.data_); std::swap(size_, x.size_); std::swap(cap_, x.cap_); } void clear() noexcept { for (std::size_t i = 0; i < size_; ++i) (*this)[i].~T(); size_ = 0; } }; }