#pragma once #include #include template struct phantom : boost::operators>, boost::shiftable> { phantom() = default; phantom(Base y) : x(y) {} phantom(phantom const &) = default; phantom& operator=(phantom const &) = default; phantom(phantom &&) = default; phantom& operator=(phantom &&) = default; explicit operator Base() const { return x; } Base base() const { return x; } Base x; #define IMPL(op) \ phantom & operator op (phantom rh) { \ x op rh.x; \ return *this; \ } IMPL(+=) IMPL(-=) IMPL(*=) IMPL(/=) IMPL(%=) IMPL(|=) IMPL(&=) IMPL(^=) IMPL(<<=) IMPL(>>=) #undef IMPL phantom & operator++() { ++x; return *this; } phantom & operator--() { --x; return *this; } bool operator<(phantom rh) const { return x < rh.x; } bool operator==(phantom rh) const { return x == rh.x; } }; template std::ostream & operator<<(std::ostream & out, phantom p){ return out << p.x; } template std::istream & operator>>(std::istream & in, phantom & p){ return in >> p.x; }