範囲つきintのガワを適当に書いてみた結果

template<int Min, int Max>
struct ranged_int {
    ranged_int() = default;
    ranged_int(ranged_int const &) = default;
    template<int N, typename = enable_if<(N >= Min) && (N < Max)>::type>
    ranged_int(integral_type<int, N>) : n_(N) {};
    template<int Min1, int Max1, typename = enable_if<(Min1 >= Min) && (Max1 <= Max)>::type>
    ranged_int(ranged_int<Min1, Max1> const & other) : n_(other.n) {}
    ...
    template<typename Min1, typename Max2>
    ranged_int<Min + Min1, Max + Max1> operator+(ranged_int<Min1, Max1> && other) {
        return ranged_int<Min + Min1, Max + Max1>(get() + other.get());
    }

    int get() const { return n_; }
private:
    explicit ranged_int(int n) : n(n_) {}
    int n_;
    ...
};

template<char ...ch>
integral_type<int, /* chから整数作る */> operator ""_i();

ranged_int<0, 100> i = 101_i; // error

int を引数に取るコンストラクタは定義したいんだけど、その前にその変数が本当に[Min, Max)に収まっているかどうかを証明してほしいなぁ…コンパイル時に。現実的にいくならmake_ranged_int<M, N>(int n)みたいな関数で[M, N)かチェックして違っていれば例外、とか。
代入も定義できんなぁ…ranged_int<M, N> x = integral_type<int, M>(); ranged_int<K, L> y = integral_type<int, K>();でx = y;とかやったあとのdecltype(x)の結果はranged_int<K, L>になって欲しいし…まぁ代入とかなくてもいいよね。
あとはもっと型テンプレートの引数に条件とか埋めこみまくれるようにしていく必要がある…