jeudi 28 décembre 2017

How to construct predefined random number generator and seed sequence in constructor?

Background

I'm building a discrete selector, e.g. given a sequence, it picks randomly one element with probability according to given weights. You can think of it as a pair of PredefinedRandomGenerator and std::discrete_distribution. I'd like the selector to be portable, and provide sane entropy. It will not be used in cryptographic context, I just want better randomness (sorry if I messed up terminology here).

Problem

std:random_device on MinGW on Windows always yields the same number. As a workaround, I use

//assume using namespace std::chrono
std::seed_seq seq{std::random_device{}(), 
                  duration_cast<nanoseconds>(system_clock::now()).count(),
                  42};

The problem is that the constructor of PredefinedRandomGenerator expects lvalue-reference, so I cannot initialize it in member initializer list as follows:

template <typename InputIterator>
discrete_selector(InputIterator weights_first,
                  InputIterator weights_last):
        generator(std::seed_seq{/*...*/}),
        distribution(weights_first, weights_last)
{}

So now there is at least one source of more or less random number.

What I tried

//somewhere in namespace details
std::seed_seq& get_new_sequence()
{
    static std::unique_ptr<std::seed_seq> sequence;
    sequence = std::make_unique<std::seed_seq>(std::random_device{}(), 
                                            duration_cast<nanoseconds>(system_clock::now()).count(),
                                            42);
    return *sequence;
}

The above should work, but I believe there should be a better way of doing that.


Side question

Why does constructor take the std::seed_seq by lvalue reference? It could at least use rvalue-reference.




Aucun commentaire:

Enregistrer un commentaire