Small fast pseudorandom number generator in C++ I've been away from C++ for some time and I'd like to get back up to speed with modern practices, so I implemented a small random number generator described here. 

Any advice on this piece of code?

    #include &lt;cstdint&gt;
    #include &lt;cstddef&gt;
    #include &lt;limits&gt;
    #include &lt;random&gt;

// implementation of Bob Jenkins' small prng https://burtleburtle.net/bob/rand/smallprng.html
namespace Random {
    namespace detail { 
        using _rand32_underlying = uint32_t;
        using _rand64_underlying = uint64_t;

        template&lt;size_t N&gt; struct rand_type { using type = void; };
        template&lt;&gt; struct rand_type&lt;32&gt; { using type = _rand32_underlying; };
        template&lt;&gt; struct rand_type&lt;64&gt; { using type = _rand64_underlying; };

    }

    // public
    template &lt;size_t N&gt; 
    using rand_t = typename detail::rand_type&lt;N&gt;::type;
    using rand32_t = rand_t&lt;32&gt;;
    using rand64_t = rand_t&lt;64&gt;;

    template &lt;size_t N&gt;
    inline rand_t&lt;N&gt; rot(rand_t&lt;N&gt; x, rand_t&lt;N&gt; k) noexcept { return ((x &lt;&lt; k) | (x &gt;&gt; (N - k))); }

    template&lt;size_t N&gt;
    class SmallPrng
    {
        public:
            using result_type = rand_t&lt;N&gt;;
            inline rand_t&lt;N&gt; min() { return std::numeric_limits&lt;result_type&gt;::min(); }
            inline rand_t&lt;N&gt; max() { return std::numeric_limits&lt;result_type&gt;::max(); }

            rand_t&lt;N&gt; a, b, c, d;

            inline rand32_t prng32() 
            {
                rand32_t e = a - rot&lt;N&gt;(b, 27);
                a = b ^ rot&lt;N&gt;(c, 17);
                b = c + d;
                c = d + e;
                d = e + a;
                return d;        
            }

            inline rand64_t prng64()
            {
                rand64_t e = a - rot&lt;N&gt;(b, 7); 
                a = b ^ rot&lt;N&gt;(c, 13);
                b = c + rot&lt;N&gt;(d, 37);
                c = d + e;
                d = e + a;
                return d;
            }

        public:
            explicit SmallPrng(result_type seed = 0xdeadbeef) noexcept
            {
                static_assert(!(N != 32 &amp;&amp; N != 64), "You can only construct a small prng in 32 or 64 bit mode.");
                a = 0xf1ea5eed;
                b = c = d = seed;
                for(size_t i = 0; i &lt; 20; ++i)
                    (*this)();
            }

            explicit SmallPrng(std::random_device &amp;rd) : SmallPrng(rd()) {}

            inline rand_t&lt;N&gt; operator()() noexcept
            {
                if constexpr(N == 32) 
                    return prng32();
                return prng64();
            }
    };
}
The SmallPrng(std::random_device &amp;rd) constructor seems like an utility method. It spares the client a single call to seed = rd(), but forces an inclusion of (otherwise unnecessary) &lt;random&gt;. IMHO, this constructor is absolutely unnecessary.
The purpose of the

        for(size_t i = 0; i &lt; 20; ++i)
            (*this)();


loop in the constructor is seems useless; it amounts to passing a different seed. In any case, use {} around the loop body.
An asymmetry between

        b = c + d;


in prng32() and

        b = c + rot&lt;N&gt;(d, 37);


in prng64() is striking. Needs a comment, at least.
As mentioned in comments, the static_assert(!(N != 32 &amp;&amp; N != 64), ....) is equivalent to static_assert((N == 32 || N == 64), ....) which is IMHO much cleaner.