#pragma once
#ifndef _DATATYPEPROXY_H_
#define _DATATYPEPROXY_H_
template <typename T>
class DataTypeProxy
{
private:
    T data;
    int cmp, mov;
public:
    DataTypeProxy() : cmp(0), mov(0), data(T()) {}
    DataTypeProxy(const T &value) : cmp(0), mov(1), data(value) {}
    DataTypeProxy<T> &operator=(const T &rhs)
    {
        mov++;
        return data = rhs;
    }
    void reset() { cmp = mov = 0; }
    operator T &() { return data; }
#define _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(op)                           \
    friend bool operator op(DataTypeProxy<T> &lhs, DataTypeProxy<T> &rhs) \
    {                                                                     \
        lhs.cmp++;                                                        \
        return lhs.data op rhs.data;                                      \
    }
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(<)
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(>)
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(<=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(>=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(==)
    _DATATYPEPROXY_H_DEF_OP_BINARY_CMP_(!=)
#define _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(op)                           \
    friend bool operator op(DataTypeProxy<T> &lhs, DataTypeProxy<T> &rhs) \
    {                                                                     \
        lhs.mov++;                                                        \
        return lhs.data op rhs.data;                                      \
    }
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(<<=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(>>=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(^=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(|=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(&=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(+=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(-=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(*=)
    _DATATYPEPROXY_H_DEF_OP_BINARY_MOV_(/=)
};
#endif // !_DATATYPEPROXY_H_
