c++ class members and delayed initialization [duplicate] - c++

This question already has an answer here:
c++ calling non-default constructor as member [duplicate]
(1 answer)
Closed 9 years ago.
I am currently looking into new c++11 random library. For simplification, I created following class
class my_rand {
private:
std::mt19937_64 eng;
public:
my_rand() {
std::array<int, std::mt19937::state_size> seed_data;
std::random_device rd;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
this->eng.seed(seq);
};
unsigned long long operator() () {
return this->eng();
};
};
so that I can just do my_rand rand; once and then repeatedly call rand() to generate random numbers.
However, now I want to use std::uniform_int_distribution to set bound to numbers I get. It seams obvious to specify bounds while creating the object, so that invocations stay the same. The problem is, if I add private member (something like std::uniform_int_distribution<long long> uid;) then later in constructor I will not be able to set bounds because uid will already be initialized. I could not find method of std::uniform_int_distribution which allowed to set limits after it is created.
I may well be missing some point here, so thanks in advance for any help.

Use initializer lists to construct member variables or base classes. (See here for more info)
my_rand(...arguments...) : uid(...arguments...) //<-- Initializer list
{
//...stuff...
} //<-- No semicolon after function definition.
If that doesn't suit your needs, you can always go like this:
myVar = int(27);
For example:
//Initial construction:
std::uniform_int_distribution<> testA(1, 6);
//Re-assignment by copy-construction (move-construction actually)
//and a temporary object.
testA = std::uniform_int_distribution<>(5, 10);

Related

Incorrectly seeding Mersenne Twister via constructor

What is wrong with my constructor? Every time I call a function (about once every five seconds) that is supposed to generate random numbers, it generates the same numbers. Each call instantiates one of these objects below. I thought I was seeding m_gen randomly with the output of m_rd's operator() call.
Could I pass in the result of m_rd() to the constructor? What would the signature be? Shuffler(std::random device& rd)? But then that would be more difficult for the user.
Edit:
Actually, if it's possible, I would prefer a solution where you don't need to pass anything into the constructor.
shuffler.h
#include <random>
class Shuffler
{
private:
std::random_device m_rd;
std::mt19937 m_gen;
public:
//! The default constructor.
Shuffler();
};
shuffler.cpp
#include "shuffler.h"
Shuffler::Shuffler() : m_gen(m_rd())
{
}
std::random_device is usually fine for this sort of thing, but it may not be on every platform. While most platforms' standard libraries implement it in terms of some underlying OS random functionality (i.e. /dev/urandom on Linux or CryptGenRandom on Windows), it is not required to do so by the C++ standard. On some platforms, high-quality random generators simply may not be available, and the standard allows std::random_device to be a simple, statically seeded PRNG. If it is, every std::random_device object will generate the same sequence of numbers.
For those reasons, you may want to go back to simple time-seeding. The standard
provides std::chrono::high_resolution_clock:
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler()
: m_gen{static_cast<std::uint32_t>(
std::chrono::high_resolution_clock::now().time_since_epoch().count()
)}
{}
};
std::chrono::high_resolution_clock usually has a resolution of nanoseconds or hundreds of nanoseconds. This is high enough that two PRNGs seeded by calls to the high_resolution_clock are very unlikely to end up using the same seed. This is also not guaranteed though. For example, std::chrono::high_resolution_clock only has microsecond resolution on macOS, which may or may not be good enough for your purposes.
In the end, neither method is perfect. You may want to combine the two using std::seed_seq:
std::seed_seq make_seeds() {
thread_local std::random_device rd;
return {{
static_cast<std::uint32_t>(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
rd()
}};
}
// Cast away rvalue-ness because the standard random generators need
// an lvalue reference to their seed_seq for some strange reason
template <typename T>
T& identity(T&& t) { return t; }
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler()
: m_gen{identity(make_seeds())}
{}
};
As you can see, this is getting far from simple, and it's still not perfect. See these blog posts for more information about seeding and random number generators then you ever thought you wanted.
As in this example, you have to seed it and random_device doesn't seem to do the trick*:
// do this once somewhere
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler() : m_gen(seed) {}
};
*As stated here, random_device is not a Seed Sequence!

Initializing static default_random_engine [duplicate]

This question already has answers here:
How to initialize private static members in C++?
(18 answers)
Closed 6 years ago.
I have a simple class which will be useful for me with generating random numbers using default_random_engine.
Random.h:
#include <random>
using namespace std;
class Random
{
public:
Random();
~Random() {}
private:
static default_random_engine _engine;
};
Random.cpp:
#include "Random.h"
Random::Random()
{
_engine = default_random_engine{}; //Will this be initialized every time I create an object of type Random?
}
Will _engine be initialized every time I create an object of type Random?
I just want it to stay like it is after the first initialization because I was told I can use the same engine multiple times.
Will _engine be initialized every time I create an object of type Random?
Yes.
I just want it to stay like it is after the first initialization
In which case, you should define it like so:
#include "Random.h"
std::default_random_engine Random::_engine;
Without this, even your original version won't compile (as you've not defined the static member).
The link #NathanOliver provided in my question helped me understand, which is to make a global variable of that type in the source file:
#include "random.h"
default_random_engine Question::_engine = default_random_engine{};
Random::Random() { }

using bind vs using pointers with random number generators

I had the following implementation in my code:
// first solution
//random.h
class Random{
public:
std::mt19937* gen;
std::uniform_real_distribution<double>* dis;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
gen = new std::mt19937(seed);
dis = new std::uniform_real_distribution<double>(0.0,1.0);
}
double Random::next()
{
double rand = 0;
rand_int = (*dis)(*gen);
return rand;
}
On the other hand someone else in the company did a different implementation, where he used the bind feature from c++11 as follows:
// second solution
//random.h
class Random{
public:
std::function<double()> real_rand;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
real_rand = std::bind(std::uniform_real_distribution<double>(0.0,1.0), mt19937_64(seed))
}
double Random::next()
{
double rand = 0;
rand = real_rand();
return rand;
}
Taking into account that you are supposed to have only one PRNG object, and you are supposed to seed it once, then you call that object every time you need a new random number, as the seed is used to create a series of random numbers in the PRNG. I can clearly see this being the case for the first solution.
The question is, how is bind() working behind the scenes? Is it creating a new object on every call? Is it really calling the (constructor) or the function()? How can it tell which one to call? Are there any differences between the solutions?
std::bind generates a function object which encapsulates the arguments provided to it. In effect your colleague's code generates the following object:
struct random_call
{
random_call(unsigned seed)
: _mt19937_64(seed)
, _uniform_real(0.0, 1.0)
{}
double operator() {
return _uniform_real(_mt19937_64);
}
std::mt19937_64 _mt19937_64;
std::uniform_real_distribution<double> _uniform_real;
};
so it looks ok (and actually pretty clever) to me!
One caveat is that you probably wouldn't want to make any copies of the binder object - even if it turns out to be copyable, copying it and then calling operator() on the original and the copy will yield the same numbers.

Random Number In-Class Initialisation

I am currently making a class for which I'd like one of the private members to be initialised with a random number each time the object is created. The following code causes no problem:
private:
unsigned random = rand() % 10;
I would, however, like to use the C++11 random engines and distributions to do this. I would like to be able to do something along the lines of the following code, which will not compile but will give a general idea of what I'm trying to do:
private:
unsigned random = distribution(mersenne_generator(seed));
static std::random_device seed_generator;
static unsigned seed = seed_generator(); //So that it's not a new seed each time.
static std::mt19937 mersenne_generator;
static std::uniform_int_distribution<unsigned> distribution(0, 10);
This code won't compile because I'm trying to define some of the static members in the class. I'm not sure where to define them, however. I could create a member function that initialises everything, but then I would have to run it in main, which I don't want to. I would like to just sort out all the random definitions in class so that when I create an object in main, it will create the random number implicitly. Any suggestions?
You need to define the static data members outside the class definition. For instance, this will work:
struct foo
{
private:
unsigned random = distribution(mersenne_generator);
static std::random_device seed_generator;
static unsigned seed;
static std::mt19937 mersenne_generator;
static std::uniform_int_distribution<unsigned> distribution;
};
std::random_device foo::seed_generator;
unsigned foo::seed = seed_generator();
std::uniform_int_distribution<unsigned> foo::distribution(0, 10);
std::mt19937 foo::mersenne_generator(foo::seed);
The definitions for the static data members should be placed in a .cpp file, else you run the risk of violating the one definition rule.
Live example

How to std::bind() to create a data member?

I'm generating random values with C++11 nice new generators and distributions. In a function it works like a charm and looks like this:
void foo() {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
auto dice = bind(distribution, generator);
// dice() will now give a random unsigned value
}
But how can I put all three objects in a class as data members? I can simply write generator and distribution as data members, but how do I make dice a data member without knowing (or wanting to know) its exact type? Suprisingly this
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
decltype(bind(distribution, generator)) dice;
};
yields the error error C2660: 'bind' : function does not take 2 arguments in Visual Studio 2013.
You could always gasp write a function instead of using a lambda/bind/etc.:
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
public:
auto dice() -> decltype(distribution(generator)) {
return distribution(generator);
}
// or alternatively
auto operator() () -> decltype(distribution(generator)) {
return distribution(generator);
}
};
Bonus points for parameterizing on the type of the generator and/or distribution, and for holding the generator with a std::shared_ptr so that you can make several objects with differing distributions that share the same engine. You'll eventually want a constructor to seed the generator as well - Ideally with something like std::random_device{}().
Or, the answer I think you are looking for:
class X {
mt19937 generator{std::random_device{}()};
uniform_int_distribution<unsigned> distribution{1,6};
public:
decltype(bind(std::ref(distribution), std::ref(generator))) dice{
bind(std::ref(distribution), std::ref(generator))
};
};
I'm sorry I mocked you for trying to use bind in the first place: it's actually kind of neat that you can write this class with "no code" in C++11. We need to get type-inference for class member declarations in C++17 so this could be:
class X {
auto generator = mt19937{std::random_device{}()};
auto distribution = uniform_int_distribution<unsigned>{1,6};
public:
auto dice = bind(std::ref(distribution), std::ref(generator));
};
Given that the latest Concepts Lite paper proposes using concept names anywhere in the language where auto can appear to mean "infer type, ill-formed if type doesn't model named concept," auto member declarations may not be out of the question.
It works on GCC. I’m pretty sure that’s just a compiler bug. Unfortunately this means that you have to bite the bitter pill and use one of the workarounds described in the other answers.
The result of std::bind is unspecified: this means that you cannot store its raw result without type inference. However, you can use std::function to encapsulate the result of bind:
#include <functional>
std::function<unsigned()> dice(std::bind(distribution, generator));
auto result = dice();
EDIT: As whoever said above, this is most clearly a Visual Studio issue. I can confirm that this compiles with VS2013:
#include <functional>
#include <random>
using namespace std;
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
std::function<unsigned()> dice;
public:
X() : dice(bind(distribution, generator)) {}
unsigned roll() { return dice(); }
};
but changing the type of dice to decltype(bind(distribution, generator)) makes the whole thing fail with flying colors (even though it still works with clang).