template <class T>
class vec {
public:
	// default constructor
	vec(){
		m_size = 0;
		m_capacity = 2;
		m_data = new T[m_capacity];
		// std::cout << "calling default constructor" << std::endl;
	}

	// other constructor
	vec(int number, const T& value){
		m_size = number;
		m_capacity = m_size * 2;
		m_data = new T[m_capacity];
		for(int i=0; i<m_size; ++i){
			m_data[i] = value;
		}
	}

	// copy constructor
	vec(const vec& other){
		m_size = other.m_size;
		m_capacity = other.m_capacity;
		m_data = new T[m_capacity];
		for(int i=0; i<m_size; ++i){
			m_data[i] = other.m_data[i];
		}
	}

	// assignment operator
	// a = b = c; a = (b = c);
	// a = b;
	vec& operator=(const vec& other){
		m_size = other.m_size;
		m_capacity = other.m_capacity;
		m_data = new T[m_capacity];
		for(int i=0; i<m_size; ++i){
			m_data[i] = other.m_data[i];
		}
		return *this;
	}

	// destructor
	~vec(){
		// std::cout << "calling destructor" << std::endl;
		delete [] m_data;
	}

	int size(){
		return m_size;
	}

	T& operator[](int index){
		return m_data[index];
	}

	void push_back(const T& element){
		// if we have space
		if(m_size < m_capacity){
			m_data[m_size] = element;
		}else{
		// if we don't have space
			m_capacity = m_capacity* 2;
			T* new_data = new T[m_capacity];
			// copy the existing elements to new location
			for(int i=0; i<m_size; ++i){
				new_data[i] = m_data[i];
			}
			new_data[m_size] = element;
			delete [] m_data;
			m_data = new_data;
		}
		m_size++;
	}

	void pop_back(){
		m_size--;
	}
private:
	T* m_data;
	int m_capacity;	// whole capacity
	int m_size;	// current size
};
