// Vector.h // // A class Vector similar to the STL container vector. // Version 1.1 // // Included from Version 1.0: // Vector(), Vector(n), Vector(init_list) // size(), indexing operator // iterators, constant iterators // begin, end, cbegin, cend // copy constructor, assignment operator, destructor // // New in Version 1.1: // insert, erase #ifndef _Vector_h_ #define _Vector_h_ #include #include template class Vector { public: typedef T * iterator; typedef const T * const_iterator; Vector() : buffer_(nullptr), size_(0), capacity_(0) {} explicit Vector(int n); Vector(const std::initializer_list & init_list); Vector(const Vector & v); ~Vector() { if (buffer_ != nullptr) delete [] buffer_; } int size() const { return size_; } int capacity() const { return capacity_; } T & operator[](int i) { return buffer_[i]; } const T & operator[](int i) const { return buffer_[i]; } Vector & operator=(const Vector & v); iterator begin() { return buffer_; } const_iterator begin() const { return buffer_; } const_iterator cbegin() const { return buffer_; } iterator end() { return buffer_ + size_; } const_iterator end() const { return buffer_ + size_; } const_iterator cend() const { return buffer_ + size_; } iterator erase(const_iterator itr); iterator insert(const_iterator itr, const T & e); private: T * buffer_; // points to a dynamically allocated array that // contains the vector elements int size_; // the number of elements in the vector int capacity_; // the size of the buffer // Returns pointer to new buffer of size n. Returns // nullptr if n == 0. T * get_new_buffer(int n) const; }; template inline T * Vector::get_new_buffer(int n) const { return (n == 0 ? nullptr : new T[n]()); } template inline Vector::Vector(int n) { buffer_ = get_new_buffer(n); size_ = n; } template inline Vector::Vector(const std::initializer_list & init_list) { buffer_ = get_new_buffer(init_list.size()); std::copy(init_list.begin(), init_list.end(), buffer_); size_ = capacity_ = init_list.size(); } template Vector::Vector(const Vector & v) { buffer_ = get_new_buffer( v.size() ); std::copy(v.begin(), v.end(), buffer_); size_ = capacity_ = v.size(); } template Vector & Vector::operator=(const Vector & v) { // Note: The current buffer of the receiver won't be // deallocated until a new buffer has been successfully // allocated and filled with a copy of v's buffer. This // prevents problems in case the allocation fails or the // calling function did "v = v". T * new_buffer = get_new_buffer(v.size()); std::copy(v.begin(), v.end(), new_buffer); // deallocate old buffer, if there is one if (buffer_ != nullptr) delete [] buffer_; // give new buffer to receiver buffer_ = new_buffer; size_ = capacity_ = v.size(); return *this; } template typename Vector::iterator Vector::erase( Vector::const_iterator const_itr) { iterator itr = iterator(const_itr); std::copy(itr + 1, end(), itr); --size_; return itr; } template typename Vector::iterator Vector::insert( Vector::const_iterator const_itr, const T & e) { iterator itr = iterator(const_itr); if (size_ < capacity_) { std::copy_backward(itr, end(), end() + 1); *itr = e; ++size_; return itr; } else { // size_ == capacity_ int new_capacity_ = capacity_ + std::max(1, size_); T * new_buffer = get_new_buffer(new_capacity_); iterator new_itr = std::copy(begin(), itr, new_buffer); *new_itr = e; std::copy(itr, end(), new_itr + 1); delete [] buffer_; buffer_ = new_buffer; ++size_; capacity_ = new_capacity_; return new_itr; } } #endif