With the following interface in mind
EasyRandom<unsigned int> prng(a, b);
auto x = prng(); // scalar
auto v = prng(10); // vector
I wrote the following class:
// https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
template <typename T = unsigned int>
class EasyRandom
{
private:
std::random_device rd;
std::unique_ptr<std::mt19937> gen;
std::unique_ptr<std::uniform_int_distribution<T>> dist;
public:
EasyRandom(T a, T b)
{
gen = std::make_unique<std::mt19937>(rd());
dist = std::make_unique<std::uniform_int_distribution<T>>(a, b);
}
T operator()() { return (*dist)(*gen); }
std::vector<T> operator()(size_t n)
{
std::vector<T> v;
for (; n > 0; v.push_back(operator()()), --n);
return v;
}
};
I also have a few specific questions:
- Is there a way to instantiate
EasyRandom
without the use of pointers? - Is it possible to change
operator()(size_t n)
to return any user-specified SequenceContainer (e.g. vector, list, deque) instead of hard-coding it to a particular implementation (e.g.std::vector
)?
std::random_device
that you use only once wastes space. 2. Instantiating onestd::unique_ptr<std::mt19937>
per distribution wastes a lot of space and makes creating distributions really slow. You typically want exactly one generator per thread that is generating random numbers, so make the generator[static] thread_local
. \$\endgroup\$ – Ted Lyngmo Jun 19 '19 at 19:31