# C++ wrapper around uniform mt19937 SequenceContainer [closed]

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:

1. Is there a way to instantiate EasyRandom without the use of pointers?
2. 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)?
• As @1201ProgramAlarm already pointed out the second part of your question is off-topic and could lead to your entire question being closed. Please revise your question if you want to prevent this. – yuri Jun 18 '19 at 7:57
• Adding a non-working implementation does not make the question on topic for Code Review. We require the code be working. For more information, see the help center. I have rolled back the edit you made to avoid incurring closevotes. – Vogel612 Jun 18 '19 at 10:55
• Some notes on what you've got so far: 1. Keeping the instance of std::random_device that you use only once wastes space. 2. Instantiating one std::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. – Ted Lyngmo Jun 19 '19 at 19:31

gen and dist don't need to be pointers. Just declare them as members, and use the member initializer list in the constructor to initialize them.

std::random_device rd;
std::mt19937 gen;
std::uniform_int_distribution<T> dist;

EasyRandom(T a, T b): gen(rd()), dist(a, b) {
}


In the operator() that returns a vector, you can reserve space for the vector to avoid memory reallocations during the insertions (v.reserve(n)). While not an issue with ints, if you use emplace_back rather than push_back that can avoid potential extra copies of a value for non-simple types.

The second question is off topic (code not implemented).

• Added implementation for second question. Thank you for your feedback so far. – Sparkler Jun 18 '19 at 5:28