#include <type_traits>

template<class T> class Range {
    class const_iterator {
        using I = typename std::conditional<std::is_enum<T>::value,
              typename std::underlying_type<T>::type, T>::type;
        I i;
        public:
        const_iterator(const T &i) : i(static_cast<I>(i)) {}
        const T operator*() const { return static_cast<T>(i); }
        const_iterator &operator++(){ ++i; return *this; }
        bool operator!=(const const_iterator &o) const { return i != o.i; }
    };
    T b, e;
    public:

    Range(const T &b, const T &e) : b(b), e(e) {}
    const_iterator begin() const { return b; }
    const_iterator end() const { return e; }
};

enum struct Square : std::size_t {
    ZERO, ONE, TWO, THREE, SENTINEL
};

Range<Square> SQ(Square::ZERO, Square::SENTINEL);

#include <iostream>
using namespace std;
int main(){
    for(auto s : SQ) cout << static_cast<size_t>(s) << endl;
    return 0;
}