I am trying to make a class that has a set of rng distributions as class attributes, with class methods having access to these distributions. Trying to follow the example in the documentation, I've distilled the problem to the following mwe. The code returns the errors member "A::rd" is not a type name
and no instance of overloaded function "std::uniform_real_distribution<_RealType>::operator() [with _RealType=double]" matches the argument list
.
#include <random>
#include <iostream>
using namespace std;
class A{
private:
// Declaration of variables...
// Declare random number generators and distributions
random_device rd;
mt19937 gen(rd());
uniform_real_distribution<> zero_five_real_dist{0,5};
public:
A(){
// Initialization of variables...
// Use distribution, here to print numbers
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
void print_nums(){
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
};
int main(){
A a_obj;
a_obj.print_nums();
return 0;
}
I've found two possible work-arounds, but I'm not sure if they're any good. The first is to just skip the use of the Mersenne twister engine,
class A{
private:
mt19937 gen;
uniform_real_distribution<> zero_five_real_dist{0,5};
public:
A(){
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
void print_nums(){
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
};
and the other one is to seed the rng engine in every function call.
class A{
private:
random_device rd;
uniform_real_distribution<> zero_five_real_dist{0,5};
public:
A(){
mt19937 gen(rd());
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
void print_nums(){
mt19937 gen(rd());
for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
cout << endl;
}
};
I'd greatly appreciate any input on how to make a good working implementation.
CodePudding user response:
Initialize the generator in the constructor initializer list instead.
A() : gen(rd()) {
// ...
}
CodePudding user response:
The code line:
mt19937 gen(rd());
is ambiguous. I get that error message with GNU C v11.3:
q73126760.cpp:14:17: error: 'rd' is not a type
14 | mt19937 gen(rd());
| ^~
q73126760.cpp: In constructor 'A::A()':
q73126760.cpp:22:59: error: invalid use of non-static member function 'std::mt19937 A::gen(int (*)())'
22 | for (int i; i<6; i ) cout << zero_five_real_dist(gen) << " ";
| ^~~
Trouble is, one of the possible interpretations is that gen
could be a member function of class A, returning some mt19937
object. Your code is a new victim of the parsing rule known under the sulfurous name of C Most Vexing Parse: the interpretation as a function declaration takes priority.
And as rd
is not a proper type, the interpretation as a function declaration ultimately fails, and the parser is unable to backtrack.
This can be fixed, for example, by forcing the compiler to take rd()
as an initializer, using curly braces, like this:
mt19937 gen{rd()};