// Afirmaciones de los apuntes sobre std::vector, comprobadas con este g++.
#include <cstddef>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include "tracked.h"

int main() {
    std::vector<int> v;
    for (int i = 0; i < 1000; i++) {
        v.push_back(i);
    }
    std::cout << "1000 push_back: size " << v.size() << ", capacity " << v.capacity() << "\n";
    for (int i = 0; i < 999; i++) {
        v.pop_back();
    }
    std::cout << "999 pop_back: size " << v.size() << ", capacity " << v.capacity() << "\n";
    v.clear();
    std::cout << "clear: size " << v.size() << ", capacity " << v.capacity() << "\n";
    v.reserve(10);
    std::cout << "reserve(10): capacity " << v.capacity() << "\n";
    v.shrink_to_fit();
    std::cout << "shrink_to_fit: capacity " << v.capacity() << "\n";

    std::vector<int> big;
    big.reserve(100);
    big.push_back(1);
    std::vector<int> copy = big;
    std::cout << "copia de size 1 y capacity 100: capacity " << copy.capacity() << "\n";

    // reserve exacto en cada inserción: el vector nunca duplica.
    std::vector<TrackedRiskyMove> slow;
    TrackedRiskyMove::reset();
    for (int i = 0; i < 1000; i++) {
        slow.reserve(slow.size() + 1);
        slow.push_back(TrackedRiskyMove(i));
    }
    std::cout << "reserve(size + 1) antes de 1000 push_back: copias " << TrackedRiskyMove::counts.copies
              << "\n";

    // El argumento apunta dentro del bloque que se va a liberar.
    std::vector<std::string> names = {std::string(40, 'a')};
    names.push_back(names[0]);
    names.push_back(names[0]);
    std::cout << "push_back(names[0]) con el vector lleno: " << names.size() << " nombres, el último de "
              << names.back().size() << " letras\n";
    return 0;
}
