4
\$\begingroup\$

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)?
\$\endgroup\$

closed as off-topic by Snowhawk, Toby Speight, Oh My Goodness, pacmaninbw, t3chb0t Jun 18 at 18:25

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Snowhawk, Toby Speight, Oh My Goodness, pacmaninbw, t3chb0t
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ 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. \$\endgroup\$ – yuri Jun 18 at 7:57
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Vogel612 Jun 18 at 10:55
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Ted Lyngmo Jun 19 at 19:31
3
\$\begingroup\$

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).

\$\endgroup\$
  • \$\begingroup\$ Added implementation for second question. Thank you for your feedback so far. \$\endgroup\$ – Sparkler Jun 18 at 5:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.