If you were going to get a number from random_device at every call, you might as well just use it directly:
int random_in_range(int min, int max) {
std::random_device rd;
std::uniform_int_distribution<int> uni(min, max);
return uni(rd());
}
std::random_device is intended to be a front-end for a truly random bit source. The major shortcoming is that in many cases it has fairly limited bandwidth, so you'd prefer to avoid calling it every time you need a number.
If you do want to use mt19937 (a perfectly fine idea in many cases) I'd personally use a function-object instead of a function:
class random_in_range {
std::mt19937 rng;
public:
random_in_range() : rng(std::random_device()()) {}
int operator()(int low, int high) {
std::uniform_int_distribution<int> uni(low, high);
return uni(rng);
}
};
This does have some shortcoming though: people may use a temporary of this type in a loop:
for (int i=0; i<10; i++)
std::cout << random_in_range()(0, 1);
...which puts you back where you started. You need to do something like:
random_in_range r;
for (int i=0; i<10; i++)
std::cout << r(0, 1);
...to get the results you want (i.e., seed once, call multiple times).