#include <iostream>

class IdProvider {
 static int count;
private:
  IdProvider(){}
public:
  static IdProvider& Instance() {
    static IdProvider instance;
    return instance;
  }

  int Next() {
    return ++count;
  }
};

int IdProvider::count = 0;

template <typename T> class TracingValue {

private:
  T m_Val;
  int m_Id;

private:
  void LogStackTrace() {}

public:
  int Id() const { return m_Id; }

  TracingValue &operator=(const TracingValue &other) {
    LogStackTrace();
    m_Val = other.m_Val;
    std::cout << "id: " << this->Id() << " new value: " << m_Val
              << " from id: " << other.Id() << std::endl;
    return *this;
  }

  TracingValue &operator=(const T &val) {
    LogStackTrace();
    m_Val = val;
    std::cout << "id: " << this->Id() << " new value: " << m_Val << std::endl;
    return *this;
  }

  TracingValue(const T &val):m_Id(IdProvider::Instance().Next()),m_Val(val) {
    std::cout << "id: " << this->Id() << " constructed with value: " << val << std::endl;
    LogStackTrace();
  }

  TracingValue(const TracingValue &other):TracingValue(other.m_Val) {
    std::cout << "id: " << this->Id() << " constructed from id: " << other.Id() << std::endl;
  }

  TracingValue():TracingValue(T()) { LogStackTrace(); }

  operator T() const { return m_Val; }
};

int main() {
TracingValue<double> d;
d = 3.;
d = 42.;
double x = d - 2.;
std::cout << x << std::endl;
TracingValue<double> other_d(d);

TracingValue<double> another_d;
another_d = other_d;  
}
