std::random_device
is not copyable or movable. So your class also cannot be copied or moved.
However, there isn't really any point to keeping the std::random_device
instance around. You (hopefully) use it only to seed the actual random number generator. So remove it from the struct and instead in the constructor:
gen = std::mt19937(std::random_device{}());
or skip the constructor entirely and use default member initializers, since your default constructor does nothing but initialize the members:
struct RandNormGen {
std::mt19937 gen{std::random_device{}()};
std::normal_distribution<float> normalDist;
float randFloat(float sigma, float mean = 0) {
float r = normalDist(gen) * sigma + mean;
return r;
}
};
(The default constructor of std::normal_distribution
already initializes to distribution parameters to 0
and 1
but std::normal_distribution<float> normalDist{0, 1};
would work as well.)
Be aware however of what you are doing that causes the requirement for the copy constructor in the first place.
If you actually copy rather than move the class object, you will end up with two instances of the class with the same state of the random number generator, meaning that the random numbers generated in the copy will not be different from those generated in the original.
If that is not the behavior you want, you can delete the copy constructor explicitly so that only moves will be allowed:
RandNormGen() = default;
RandNormGen(const RandNormGen&) = delete;
RandNormGen(RandNormGen&&) = default;
RandNormGen& operator=(const RandNormGen&) = delete;
RandNormGen& operator=(RandNormGen&&) = default;
or you can define a copy constructor and assignment operator with the intended semantics (e.g. reseeding the generator).
Even more generally, consider moving the random number generator out of the class. There is usually not really any point in having a random generator for each object. Usually having a generator per thread in the program is sufficient.