#include <algorithm>
#include <iostream>

template<typename T>
class arreglo_dinamico {
   int cap, tam;
   T* p;

public:
   arreglo_dinamico( ) {
      cap = 1;
      tam = 0;
      p = new T[1];
   }

   explicit arreglo_dinamico(int t, T v) {
      cap = t;
      tam = t;
      p = new T[cap];
      for (int i = 0; i < tam; ++i) {
         p[i] = v;
      }
   }

   arreglo_dinamico(std::initializer_list<T> lista) {
      cap = 1;
      tam = 0;
      p = new T[1];
      for (T v : lista) {
         agrega(v);
      }
   }

   arreglo_dinamico(const arreglo_dinamico& v) {
      cap = v.tam;
      tam = v.tam;
      p = new T[cap];
      for (int i = 0; i < tam; ++i) {
         p[i] = v.p[i];
      }
   }

   ~arreglo_dinamico( ) {
      delete[] p;
   }

   void operator=(const arreglo_dinamico& v) {
      if (p == v.p) {
         return;
      }

      delete[] p;
      cap = v.tam;
      tam = v.tam;
      p = new T[cap];
      for (int i = 0; i < tam; ++i) {
         p[i] = v.p[i];
      }
   }

   int size( ) const {
      return tam;
   }

   T& operator[](int i) {
      return p[i];
   }

   const T& operator[](int i) const {
      return p[i];
   }

   void agrega(T v) {
      if (tam == cap) {
         T* q = new T[2 * cap];
         for (int i = 0; i < tam; ++i) {
            q[i] = p[i];
         }
         delete[] p;
         p = q;
         cap *= 2;
      }

      p[tam] = v;
      tam += 1;
   }

   void quita_ultimo( ) {
      tam -= 1;
   }
};

template<typename T>
void imprime(const arreglo_dinamico<T>& a) {
   for (int i = 0; i < a.size( ); ++i) {
      std::cout << a[i] << " ";
   }
   std::cout << "\n";
}

int main( ) {
   arreglo_dinamico<int> a = { 10, 5 };
   arreglo_dinamico<float> b(10, 3.14);
   arreglo_dinamico<char> c;
   c.agrega('@');
   c.agrega('#');

   imprime(a);
   imprime(b);
   imprime(c);
}
