I'm struggling with the use of the random facility which the language since C++11 provides. Because I don't understand the semantics of the syntax, I'm shying away from using it - also it's hard to memorize its using because I don't understand the syntax there.
At another thread I found a useful example (thanks goes to @tpb :-)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Generate a random input problem in vector<int> form.
// Length is from min_size to max_size; operands are from -99 to 99 (but not 0)
Problem rnd_prob(int min_size, int max_size) {
using UID = std::uniform_int_distribution<>;
staticauto rng = std::mt19937(std::random_device{}());
static UID distSize(min_size, max_size);
static UID distValuesFirst(1, 99);
static UID distValues(-98, 99);
int size = distSize(rng);
Problem prob;
prob.push_back(distValuesFirst(rng)); // first must be positive
for (int i = 1; i < size; i++) {
int n = distValues(rng);
if (n <= 0) --n; // exclude zero
prob.push_back(n);
}
return prob;
}
Especially at these two parts I don't understand the syntax:
using UID = std::uniform_int_distribution<>;
At this above I'm struggling about the empty angled brackets (What does this mean? I know only the use at specifying a type for a templated entity).
And staticauto rng = std::mt19937(std::random_device{}());
Here I'm stumbling over std::random_device{}()
I had never seen this syntax at an other context.
If it's not all too complicated, I would be glad if someone could explain this stuff.
std::random_device is a class. It also happens to provide a function-call operator, so you can call instances of it like a function:
1 2
std::random_device rd{}; // list-initialize a random device named rd
rd(); // okay
So std::random_device{}() calls a temporary random_device object like a function. The result is an unsigned int. For instance:
1 2 3 4 5 6 7 8 9 10 11
struct my_random_device
{
// https://xkcd.com/221/unsignedintoperator()() constnoexcept
{
return 4; // chosen by fair dice roll
// guaranteed to be random
}
};
// ...
std::cout << (my_random_device{}()) << '\n'; // prints 4
Consequentially, Melissa O'Neill's famous article is required reading before you use this line of code in real life: http://www.pcg-random.org/posts/cpp-seeding-surprises.html
The punchline is that this random number generator needs more state than it's given.
I've still a question about the curly braces at random_device{}():
These braces, which mean an empty initializer list, are they necessary for letting the compiler recognizing to instantiating an object rather than calling a plain function?