views:

242

answers:

3

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); }
};
A: 

Wrap it in a class or functor that fit your needs?

Klaim
Is there an automated way to wrap something like that in a functor?
Neil G
+3  A: 

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
}
Potatoswatter
that's really unfortunate, because it means that I have to have all of my random functions in headers.
Neil G
(but thanks for the answer...)
Neil G
@Neil: See my second answer (I only committed the first paragraph at first). I think the intent of the standard is that you pick one generator and stick to it. There is no need for any of this if you only want to use `std::mt19937`… but that's unclear from your question.
Potatoswatter
You're right. Thanks for the rest of your answer. I am happy limiting myself to mt if it makes the code easier to deal with.
Neil G
A: 

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.

Thomas Matthews