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); }
};
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.
template< class RNG > // RNG may be a functor object of any type
int random_even_number( RNG &gen ) {
return (int) gen() * 2;
}
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.
struct RNGbase {
virtual int operator() = 0;
virtual ~RGNBase() {};
};
template< class RNG >
struct SmartRNG : RNGBase {
RNG gen;
virtual int operator() {
return gen();
}
};
int random_even_number( RNGBase &gen ) { // no template
return (int) gen() * 2; // virtual dispatch
}
What worked for me was using an std::function
:
#include <functional>
#include <random>
void exampleFunction(std::function<int()> rnd) {
auto randomNumber = rnd();
}
std::minstd_rand rnd;
exampleFunction([&rnd](){ return rnd(); });
// This won't work as it passes a copy of the object, so you end up with the same
// sequence of numbers on every call.
exampleFunction(rnd);
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 an int
, so you may want to use a different data type instead of int
depending on your need for precision.
Wrap it in a class or functor that fit your needs?
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.