// Vector.h // // A class Vector similar to the STL container vector. // Version 1.2 // // New in this version: // copy constructor, assignment operator, destructor // // Included from earlier versions: // Vector(), Vector(n), Vector(init_list) // size(), indexing operator // iterators, constant iterators // begin, end, cbegin, cend // erase, insert (memory but not time efficient) #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) {} explicit Vector(int n); Vector(const std::initializer_list & init_list); Vector(const Vector & v); ~Vector() { delete [] buffer_; } int size() const { return size_; } 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 (and 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_ = init_list.size(); } template inline typename Vector::iterator Vector::erase( Vector::const_iterator const_itr) { T * new_buffer = get_new_buffer(size_ - 1); iterator new_itr = std::copy(cbegin(), const_itr, new_buffer); std::copy(const_itr + 1, cend(), new_itr); delete [] buffer_; buffer_ = new_buffer; --size_; return new_itr; } template inline typename Vector::iterator Vector::insert( Vector::const_iterator const_itr, const T & e) { T * new_buffer = get_new_buffer(size_ + 1); iterator new_itr = std::copy(cbegin(), const_itr, new_buffer); *new_itr = e; std::copy(const_itr, cend(), new_itr + 1); delete [] buffer_; buffer_ = new_buffer; ++size_; return new_itr; } template inline Vector::Vector(const Vector & v) { buffer_ = get_new_buffer(v.size()); std::copy(v.begin(), v.end(), buffer_); size_ = v.size(); } template inline 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 delete [] buffer_; // give new buffer to receiver buffer_ = new_buffer; size_ = v.size(); return *this; } #endif