Seed std::mt19937 from std::random_device Many people seed their Mersenne Twister engines like this:

std::mt19937 rng(std::random_device{}());


However, this only provides a single unsigned int, i.e. 32 bits on most systems, of seed randomness, which seems quite tiny when compared to the 19937 bit state space we want to seed. Indeed, if I find out the first number generated, my PC (Intel i7-4790K) only needs about 10 minutes to search through all 32 bit numbers and find the used seed. (I know that MT is not a cryptographic RNG, but I just did that to get a feel for how small 32 bit really is in these days.)

I am trying to build a function to properly seed a mt19937 and came up with this:

#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;random&gt;

auto RandomlySeededMersenneTwister () {
    // Magic number 624: The number of unsigned ints the MT uses as state
    std::vector&lt;unsigned int&gt; random_data(624);
    std::random_device source;
    std::generate(begin(random_data), end(random_data), [&amp;](){return source();});
    std::seed_seq seeds(begin(random_data), end(random_data));
    std::mt19937 seededEngine (seeds);
    return seededEngine;
}


int main() {
    auto rng = RandomlySeededMersenneTwister();
    for (int i = 0; i &lt; 10; ++i)
        std::cout &lt;&lt; rng() &lt;&lt; "\n";    
}


This does look like a safe solution to me; however, I have learned that problems with RNG are often times quite subtle.

Provided std::random_device produces good, random data on my system, does the code give me a correctly seeded std::mt19937?
Well, first off, why do you use a std::vector for a comparatively small sequence of known length? A raw array or std::array suffice and avoids any dynamic allocation.

Next, avoid needless magic numbers. Use std::mt19937::state_size instead of manually specifying 624.

Why do you use a lambda? A simple std::ref(source) suffices.


The seeding itself looks perfectly fine and there's no actual error anywhere in your code.
template&lt;class T = std::mt19937, std::size_t N = T::state_size * sizeof(typename T::result_type)&gt;
auto ProperlySeededRandomEngine () -&gt; typename std::enable_if&lt;N, T&gt;::type {
    std::random_device source;
    std::random_device::result_type random_data[(N - 1) / sizeof(source()) + 1];
    std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
    std::seed_seq seeds(std::begin(random_data), std::end(random_data));
    return T(seeds);
}

You could avoid the need for random_data by using counting and transforming iterators as detailed in &quot;Sequence iterator? Isn't there one in boost?&quot;.
This is not simpler, but maybe more efficient:
template&lt;class T = std::mt19937, std::size_t N = T::state_size * sizeof(typename T::result_type)&gt;
T ProperlySeededRandomEngine () {
    std::random_device source;
    auto make_iter = [&amp;](std::size_t n) {
    return boost::make_transform_iterator(
        boost::counting_iterator&lt;std::size_t&gt;(n), [&amp;](size_t){return source();});
    };
    std::seed_seq seeds(make_iter(0), make_iter((N - 1) / sizeof(source()) + 1));
    return T(seeds);
}

On coliru