Some prerequisites: the reasons for allowing multiple instances of random number generators are mainly related to thread safety (without burdening the implementation of random number generators with thread synchronization) and repeatability (allowing repeating a sequence of numbers using the same seed).
The first of these is pretty clear - there are good cases of using RNG in performance-critical code. With multiple instances, expensive mutexes are not required, and random numbers can be generated on multiple processor cores in parallel.
The latter is usually useful when creating datasets at random. As a general example, video games can recreate the same (random) game world, managing all the decisions involved in creating a game world from the same RNG (possibly even on different network computers).
So the best area for C ++ RNG depends on what you write:
If you are writing a library that can be used in the context of the above for scripting, it is probably a good idea for the caller to provide RNG to individual methods or classes:
// Can be used on multiple CPU cores in parallel or with seed values template <typename TRandomNumberEngine> Point2 GetRandomPointInRectangle( const Rectangle2 &rect, TRandomNumberEngine &random ) { std::uniform_real_distribution<float> horizontal(rect.Min.X, rect.Max.X); float x = horizontal(random); std::uniform_real_distribution<float> vertical(rect.Min.Y, rect.Max.Y); float y = vertical(random); return Point2(x, y); }
If you are writing an application or library using RNG in a supporting role (for example, geometric fitting algorithms), i.e. you are just interested in random numbers that cannot be reproduced, the best area for a random number generator would be the largest possible area that would not create an undesirable connection between the modules.
It can be a simple private object variable in any class that needs random numbers or even one single thread_local , giving you RNG if it has many short-lived consumers that justify such complexity.
Distributions (e.g. std::uniform_real_distribution ) can be short lived as you want. They are simple functors, where the constructor either has no arguments, or stores only arguments for when the functor will be executed.
Cygon
source share