/** Interface for MyVector class
**/
#include <cstdlib>
template <typename T> class MyVector {

    private:
        static int const INITIAL_CAPACITY = 10;
        int _size;
        int _capacity;
        T* data;
        void reallocate();

    public:
        MyVector();
        MyVector(int capacity);
        ~MyVector();
        void push_back(T const& entry);
        bool remove(int index);
        T get(int index);
        int size();
        int capacity();
        bool empty();
        void insert(T const& entry, unsigned int index);

        //Overloaded operators
        T& operator[](const unsigned int index);
        const T& operator[](const unsigned int index) const;

};

/** Definition of MyVector class
**/
template <typename T>
MyVector<T>::MyVector()
{
    _capacity = INITIAL_CAPACITY;
    data = (T*)std::malloc(_capacity * sizeof(T));//data = new T[_capacity];
    _size = 0;
}

template <typename T>
MyVector<T>::MyVector(int capacity)
{
    if(capacity <= 0)
    {
        _capacity = INITIAL_CAPACITY;
    }
    else
    {
        _capacity = capacity;
    }
    data = new T[_capacity];
    _size = 0;
}

template <typename T>
MyVector<T>::~MyVector()
{
    std::free(data);//delete[] data;
    data = 0;
}

template <typename T>
int MyVector<T>::size()
{
    return _size;
}

template <typename T>
void MyVector<T>::reallocate()
{
    _capacity = _capacity * 2;
    T* temp = (T*)std::malloc(_capacity * sizeof(T));
    for(int i = 0; i < _size; i++)
    {
        temp[i] = data[i];
    }
    
    std::free(data);//delete[] data;
    data = temp;
    
    //std::cout << "Reallocation successful.\n";
}

template <typename T>
void MyVector<T>::push_back(T const& entry)
{
    if(_size == _capacity)
    {
        reallocate();
    }

    data[_size] = entry;
    _size++;
}

template <typename T>
bool MyVector<T>::remove(int index)
{
    if(index < 0 || index >= _size)
    {
        return false;
    }
    else
    {
        for(int i = index; i < _size; i++)
        {
            data[i] = data[i + 1];
        }
    }
    _size--;
    return true;
}

template <typename T>
T MyVector<T>::get(int index)
{
    return data[index];
}

template <typename T>
T& MyVector<T>::operator[](const unsigned int index)
{
    return data[index];
}

template <typename T>
const T& MyVector<T>::operator[](const unsigned int index) const
{
    return data[index];
}

template <typename T>
int MyVector<T>::capacity()
{
    return _capacity;
}

template <typename T>
bool MyVector<T>::empty()
{
    if(_size > 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

template <typename T>
void MyVector<T>::insert(T const& entry, unsigned int index)
{
    if(_size + 1 > _capacity)
    {
        reallocate();
    }
    for(unsigned int i = _size; i > index; i--)
    {
        data[i] = data[i - 1];
    }

    data[index] = entry;
}

#include <iostream>
#include <vector>

struct pair
{
    int x;
    int y;

    pair(int x, int y) : x(x), y(y) {}
};

int main()
{
    MyVector<pair> v;
    //std::vector<pair> v;
    
    for(int i = 0; i < 10; ++i)
    {
        v.push_back(pair(i,2*i));
    }
    
     for(int i = 0; i < 10; ++i)
     {
         std::cout << v[i].x << "   " << v[i].y << std::endl;
     }
}