#include <iostream>
#include <string>
#include <vector>

typedef std::vector<std::vector<double>> matrix_type;

template <typename T> // a handy template to output a vector with <<
std::ostream &operator <<(std::ostream &out, const std::vector<T> &obj)
{
    out << "<";
    const char *sep = "";
    for (auto &item : obj) // for each item in the vector
    {
        out << sep << item;
        sep = ", ";
    }
    return out << ">";
}

int main()
{
    matrix_type identity = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
    std::cout << "identity = " << identity << "\n\n";

    matrix_type copy1(identity); // deep copy using constructor
    copy1[0][2] = 42;
    std::cout << "copy1 = " << copy1 << "\n";
    std::cout << "identity = " << identity << "\n\n";

    matrix_type copy2;
    copy2 = identity;   // deep copy using assignment operator
    copy2[1][0] = 24;
    std::cout << "copy2 = " << copy2 << "\n";
    std::cout << "copy1 = " << copy1 << "\n";
    std::cout << "identity = " << identity << "\n\n";

    return 0;
}
