2010-02-11 8 views
13

¿Todos ellos heredan de una clase base? ¿Tengo que usar plantillas?¿Cómo paso un generador de números aleatorios C++ 11 a una función?

(me refiero a estos http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c15319/)

que estoy haciendo esto ahora:

typedef std::mt19937 RNG; 

y luego

class Chooser { 
public: 
    Chooser(RNG& rng, uint n, uint min_choices, uint max_choices): 

En otras palabras, estoy pasando referencias a RNG . ¿Cómo pasaría en un generador arbitrario?

Además, me doy cuenta de que esta es quizás una pregunta diferente, pero ¿cómo paso el generador a STL?

parece que no funciona.


solución al generador de fallecimiento:

typedef std::ranlux64_base_01 RNG; 
typedef std::mt19937 RNGInt; 

solución para pasar a STL:

struct STL_RNG { 
    STL_RNG(RNGInt& rng): gen(rng) {}  
    RNGInt& gen; 
    int operator()(int n) { return std::uniform_int<int>(0, n)(gen); } 
}; 
+0

De acuerdo con ese artículo, ya son funtores, por lo que debe estar listo para funcionar. ¿Cuál es el problema? – Potatoswatter

+0

Probablemente podamos brindarle información más específica y útil si conocemos su objetivo. – GManNickG

+0

Específicamente, ¿cómo desea que sus generadores sean diferentes y cuál es el error del compilador que obtiene para 'random_shuffle'? – Potatoswatter

Respuesta

10

No todos heredan de una base (lo cual es un poco sorprendente), pero no importa porque así no es como funcionan los funtores C++.

Para los RNG arbitrarios de un solo tipo dado, lo tienes justo como (ahora) publicado.

Si quiere decir, ¿cómo puedo definir una función que acepta cualquier generador de números aleatorios como argumento.

template< class RNG > // RNG may be a functor object of any type 
int random_even_number(RNG &gen) { 
    return (int) gen() * 2; 
} 

No necesita utilizar más plantillas que esta, debido a la deducción de tipo.


Definir una función para aceptar diferentes RNG es complicado debido a que semánticamente requiere tener un tipo de base común. Necesita definir un tipo de base.

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 
} 
+0

eso es realmente desafortunado, porque significa que tengo que tener todas mis funciones aleatorias en los encabezados. –

+0

(pero gracias por la respuesta ...) –

+0

@Neil: Vea mi segunda respuesta (al principio solo cometí el primer párrafo). Creo que la intención del estándar es que elijas un generador y te apegues a él. No hay necesidad de nada de esto si solo quieres usar 'std :: mt19937' ... pero eso no está claro a partir de tu pregunta. – Potatoswatter

0

lo envuelve en una clase o funtor que se ajusten a sus necesidades?

+0

¿Hay alguna manera automática de ajustar algo así en un functor? –

0

Sugiero dos métodos: Objetos de función y punteros a función. En cualquier caso, habilite a su clase para recibir un objeto de función o un puntero de función para el generador de números aleatorios.

Con un objeto de función, puede definir una clase base y hacer que la clase receptora implemente funciones que requieren un puntero a la clase de objeto de función base. Esto le da más libertad para definir muchos objetos de función diferentes sin cambiar la interfaz de la clase de recepción.

4

Lo que funcionó para mí fue el uso de un 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); 

usted no está realmente pasando alrededor del objeto al azar, sólo un método para llamar al objeto de operator(), pero consigue el mismo efecto.

Tenga en cuenta que aquí la precisión del valor de retorno del generador de números aleatorios puede reducirse como el std::function se declara como devolver un int, por lo que es posible que desee utilizar un tipo de datos diferente en lugar de int dependiendo de su necesidad de precisión.

Cuestiones relacionadas