makes GetRand a template for which any integral type can be used, where the default behavior is to return a random integral up to the max of the integral unless a max is provided.
This simplifies a lot of code from `GetRand(std::numeric_limits<uint64_t>::max() -> GetRand<uint64_t>()`
This is a backport of core#24925
Depends on D14827