#pragma once #include template struct StrongTypedef { private: using Self = StrongTypedef; T t; public: template ::type> explicit StrongTypedef(const T & t_) : t(t_) {} template ::type> explicit StrongTypedef(T && t_) : t(std::move(t_)) {} template ::type> StrongTypedef(): t() {} StrongTypedef(const Self &) = default; StrongTypedef(Self &&) = default; Self & operator=(const Self &) = default; Self & operator=(Self &&) = default; template ::type> Self & operator=(const T & rhs) { t = rhs; return *this;} template ::type> Self & operator=(T && rhs) { t = std::move(rhs); return *this;} operator const T & () const { return t; } operator T & () { return t; } bool operator==(const Self & rhs) const { return t == rhs.t; } bool operator<(const Self & rhs) const { return t < rhs.t; } T & toUnderType() { return t; } const T & toUnderType() const { return t; } }; namespace std { template struct hash> { size_t operator()(const StrongTypedef & x) const { return std::hash()(x.toUnderType()); } }; } #define STRONG_TYPEDEF(T, D) \ struct D ## Tag {}; \ using D = StrongTypedef; \