#include <string>
#include <iostream>

template <typename T>
class Vec {
public:
    Vec() : sz{0}, cap{1}, a{new T[cap]} {}
    ~Vec() { delete[] a; }

    Vec(const Vec&) = delete;
    Vec& operator=(const Vec&) = delete;

    Vec(Vec&& tmp) : sz{tmp.sz}, cap{tmp.cap}, a{tmp.a} {
        tmp.sz = tmp.cap = 0;
        tmp.a = nullptr;
    }

    Vec& operator=(Vec&& tmp) {
        if (this != &tmp) {
            delete[] a;

            sz = tmp.sz;
            cap = tmp.cap;
            a = tmp.a;

            tmp.sz = tmp.cap = 0;
            tmp.a = nullptr;
        }
        return *this;
    }

    T& operator[](int i) { return a[i]; }
    const T& operator[](int i) const { return a[i]; }
    size_t size() const { return sz; }
    size_t capacity() const { return cap; }

    void push_back(const T& x) {
        if (sz == cap) {
            T* a2 = new T[cap * 2];
            cap *= 2;
            std::copy(a, a+sz, a2);
            delete[] a;
            a = a2;
        }
        a[sz++] = x;
    }
private:
    size_t sz;
    size_t cap;
    T* a;
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Vec<T>& vec) {
    for (size_t i = 0; i < vec.size(); i++) {
        os << vec[i] << " ";
    }
    std::cout << "(cap=" << vec.capacity() << ")" << std::flush;
    return os;
}

Vec<int> createIntVec() {
    Vec<int> tmp;
    for (int i = 0; i < 20; i++) {
        tmp.push_back(i);
        std::cout << tmp << std::endl;
    }
    return tmp;
}

Vec<std::string> createStrVec() {
    Vec<std::string> tmp;
    for (char c = 'A'; c <= 'Z'; c++) {
        std::string s;
        s += c;
        tmp.push_back(s);
        std::cout << tmp << std::endl;
    }
    return tmp;
}

int main() {
    using namespace std;

    Vec<int> v { createIntVec() };

    Vec<string> v2 { createStrVec() };
}
