#include <iostream>
#include <cmath>

// Note: these variables could also be defined as static variables of the class vec3
int nbr_total_vec3 = 0;  // Total number of instanciation of vec3
int nbr_active_vec3 = 0; // Number of currently vec3 that are alive in the program

struct vec3 {
    float x, y, z;

    vec3();
    vec3(float x, float y, float z);

    // Copy constructor
    vec3(vec3 const& v);

    // Destructor
    ~vec3();

    void display() const;
};

std::ostream& operator<<(std::ostream& s, vec3 const& v)
{
    s << "(" << v.x << "," << v.y << "," << v.z << ")";
    return s;
}


vec3::vec3() 
    :x(0), y(0), z(0) 
{
    nbr_total_vec3++;
    nbr_active_vec3++;
}
vec3::vec3(float x_arg, float y_arg, float z_arg)
    :x(x_arg), y(y_arg), z(z_arg) 
{
    nbr_total_vec3++;
    nbr_active_vec3++;
}

vec3::vec3(vec3 const& p)
    :x(p.x), y(p.y), z(p.z)
{
    nbr_total_vec3++;
    nbr_active_vec3++;
}

vec3::~vec3()
{
    // Reduce the number of currently active vec3 by 1
    nbr_active_vec3 --;
}

void display_vec3_status() {
    std::cout << "Number of vec3: (total=" << nbr_total_vec3 << " ; active=" << nbr_active_vec3 << ")" << std::endl;
}



int main()
{
    vec3 a; 
    vec3 b = vec3(4,8,1);
    
    display_vec3_status(); // Expect (total=2, active=2)

    for (int k = 0; k < 3; ++k) {
        vec3 temp = vec3(k, 1, 0); // creation of vec3

        std::cout << "Loop, step=" << k << std::endl;
        display_vec3_status(); // Expect (total=3+k, active=3)
    }// at every new loop, the previous vec3 is destroyed

    display_vec3_status(); // Expect (total=5, active=2)

    {
        vec3 d = a;
        display_vec3_status(); // Expect (total=6, active=3)
    }

    display_vec3_status(); // Expect (total=6, active=2)

    return 0; // destroy a and b
}