11-5 讓 Vec 可以儲存 int 以外的資料型別

目前我們 Vec 雖然可以動態成長，但是只能存放 int 型別的資料，這讓它變得很沒用。
明明只有型別不同，難道我們要寫一個 Vec_int 給 int 用，寫一個 Vec_double 給 double 用，......。
在這裡我們要使用一個新東西 樣版(template)，class 是用來產生物件的 [模版]，而 template 則是用來產生 class 的 [模版]。
你可以這樣想，在宣告時寫 Vec<int> 這時 template 就會幫我們生成一個可以儲存 int 的 class，宣告時寫 Vec<double> 這時 template 就會幫我們生成一個可以儲存 double 的 class。
在程式碼中插入 template<typename T> 表示接下來這個 類別、函數 裡，看到 T 時，把它替代成指定的型別。
例如：
template<typename T>
class Vec {
private:
 T* m_data;
 int m_size;
 int m_capacity;
};

想像在主程式中，我們宣告一個 Vec<double> a;，會自動產生一個像這樣的 Vec class。
class Vec<double> {
private:
 double* m_data;
 int m_size;
 int m_capacity;
};

如此一來，我們就可以讓 Vec 裡儲存各種型別的元素，甚至是我們自己設計的型別。
修改後的 [vec.h]
#ifndef VEC_H_INCLUDED
#define VEC_H_INCLUDED

template<typename T>
class Vec {
private:
 T *m_data;
 int m_size;
 int m_capacity;
public:
 Vec();
 ~Vec();
 int size();
 int capacity();
 void push_back(T val);
 void pop_back();
 T& operator[] (int index);
};

template<typename T>
Vec<T>::Vec()
{
 m_data = nullptr;
 m_size = 0;
 m_capacity = 0;
}

template<typename T>
Vec<T>::~Vec()
{
 if(m_data!=nullptr)
 {
 delete [] m_data;
 }
}

template<typename T>
int Vec<T>::size()
{
 return m_size;
}

template<typename T>
int Vec<T>::capacity()
{
 return m_capacity;
}

template<typename T>
void Vec<T>::push_back(T val)
{
 // 如果空間不夠用
 if(m_size==m_capacity)
 {
 // 每次成長為原來的 2 倍大小
 int new_capacity = m_capacity*2;

 if(new_capacity==0)
 new_capacity = 1;

 // 配置一塊新的空間
 T *new_data = new T[new_capacity];
 // 把資料搬到新的空間
 for(int i=0; i<m_size; i++)
 {
 new_data[i] = m_data[i];
 }
 // 釋放舊的空間，改用新空間
 if(m_data!=nullptr)
 delete [] m_data;

 m_data = new_data;
 m_capacity = new_capacity;
 }

 m_data[m_size] = val;
 m_size++;
}

template<typename T>
void Vec<T>::pop_back()
{
 m_size--;
}

template<typename T>
T& Vec<T>::operator[] (int index)
{
 return m_data[index];
}

#endif // VEC_H_INCLUDED

