2

I want to know how to keep a mersenne random number generator as a member variable and use it in the same class.

I wrote the class as below and it works perfectly, but I do not like the that std::mt19937 is initialized. I would like to know whether there is a way to initialize it in the constructor of Test?

#include <iostream>
#include <cmath>
#include <random>
#include <chrono>
#include <ctime>

class Test{
public:
    Test()
    {

    }
    void foo()
    {
        auto randomNum = std::uniform_int_distribution<>(0, threads.size())(rnd);
    }

private:
    std::mt19937 rnd
    {
        std::chrono::high_resolution_clock::now().time_since_epoch().count()
    };
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Tharindu Kumara
  • 4,398
  • 2
  • 28
  • 46

1 Answers1

4

I think you are confused about exactly what a in class initialization does. When you have

struct foo
{
    foo() {}
    int bar = 10;
};

That in class initialization is just syntactic sugar for

struct foo
{
    foo() : bar(10) {}
    int bar;
};

Whenever the compiler would add a member to a member initializer list (this is done when you forget it or when the compiler provides the constructor) it uses what you used in the initialization. So with your code

class Test{
public:
    Test()
    {

    }
    void foo()
    {
        auto randomNum = std::uniform_int_distribution<>(0, threads.size())(rnd);
    }

private:
    std::mt19937 rnd
    {
        std::chrono::high_resolution_clock::now().time_since_epoch().count()};
    };
};

Becomes

class Test{
public:
    Test() : rnd(std::chrono::high_resolution_clock::now().time_since_epoch().count())
    {

    }
    void foo()
    {
        auto randomNum = std::uniform_int_distribution<>(0, threads.size())(rnd);
    }

private:
    std::mt19937 rnd;
};

The nice thing about not actually doing it that way and using how you did it to begin with is you do not have to repeat

rnd(std::chrono::high_resolution_clock::now().time_since_epoch().count())

in every constructor you write but you can always override it if you want something else for a specific constructor.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • One smallthing. How would you use std::random_device in the above style with std::mt19937 – Tharindu Kumara Jan 25 '17 at 16:16
  • @TharinduKumara If you wanted to do that then would write a function that does the initialization and returns the generator. Then you can initialize the generator with that functions return. – NathanOliver Jan 25 '17 at 16:26
  • @Nathanm, it can be used like this. `Test() : rnd(std::random_device{}()) {......}`. – Tharindu Kumara Jan 25 '17 at 16:35
  • @TharinduKumara Oh yes. That way will work. I though you were talking about initializing it like they do [here](http://stackoverflow.com/questions/15509270/does-stdmt19937-require-warmup) – NathanOliver Jan 25 '17 at 16:46