Do they all inherit from a base class? Do I have to use templates?
(I am referring to these http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c15319/)
I am doing this right now:
typedef std::mt19937 RNG;
and then
class Chooser {
public:
Chooser(RNG& rng, uint n, uint min_choices, uint max_choices):
In other words, I'm passing references to RNG. How would I pass in an arbitrary generator?
Also, I realize this is maybe a different question, but how do I pass the generator to STL?
std::random_shuffle(choices_.begin(), choices_.end(), rng);
doesn't seem to work.
solution to passing generator:
typedef std::ranlux64_base_01 RNG;
typedef std::mt19937 RNGInt;
solution to passing to STL:
struct STL_RNG {
STL_RNG(RNGInt& rng): gen(rng) {}
RNGInt& gen;
int operator()(int n) { return std::uniform_int<int>(0, n)(gen); }
};
I suggest two methods: Function Objects and Function Pointers. In either case, enable your class to receive a Function Object or a Function Pointer to the random number generator.
With a Function Object, you can define a base class, and have your receiving class implement functions that require a pointer to the base function object class. This gives you more freedom in defining many different function objects without changing the interface of the receiving class.
Wrap it in a class or functor that fit your needs?
What worked for me was using an
std::function
:You're not really passing around the random object, just a method to call the object's
operator ()
, but it achieves the same effect.Note that here the precision of the random number generator's return value may be reduced as the
std::function
is declared as returning anint
, so you may want to use a different data type instead ofint
depending on your need for precision.They don't all inherit from a base (which is a little surprising), but it doesn't matter because that's not how C++ functors work.
For arbitrary RNGs of a single given type, you got it right as (now) posted.
If you mean, how do I define a function which accepts any random number generator as an argument.
You don't need to use any more templates than this, because of type deduction.
Defining one function to accept different RNG's is trickier because semantically that requires having a common base type. You need to define a base type.