Comment passer d’un générateur de nombres aléatoires C ++ 11 à une fonction?

Est-ce qu’ils héritent tous d’une classe de base? Dois-je utiliser des modèles?

(Je me réfère à ces http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c15319/ )

Je fais ça maintenant:

typedef std::mt19937 RNG; 

et alors

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

En d’autres termes, je passe des références à RNG. Comment pourrais-je passer dans un générateur arbitraire?

De plus, je réalise que la question est peut-être différente, mais comment puis-je transmettre le générateur à STL?

 std::random_shuffle(choices_.begin(), choices_.end(), rng); 

ne semble pas fonctionner.


solution pour passer générateur:

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

solution pour passer à STL:

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

Ils n’héritent pas tous d’une base (ce qui est un peu surprenant), mais cela n’a pas d’importance, car ce n’est pas ainsi que fonctionnent les foncteurs C ++.

Pour les RNG arbitraires d’un seul type donné, vous avez tout à fait raison de le signaler (maintenant).

Si vous voulez dire, comment définir une fonction qui accepte n’importe quel générateur de nombres aléatoires en tant qu’argument.

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

Vous n’avez pas besoin d’utiliser plus de modèles que cela, en raison de la déduction de type.


Définir une fonction pour accepter différents GNA est plus délicat car cela nécessite sémantiquement d’avoir un type de base commun. Vous devez définir un type 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 } 

Ce qui a fonctionné pour moi, c’est d’utiliser une std::function

 #include  #include  void exampleFunction(std::function 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); 

Vous ne transmettez pas vraiment l’object aléatoire, vous utilisez simplement une méthode pour appeler l’ operator () l’object, mais le même effet est obtenu.

Notez qu’ici, la précision de la valeur renvoyée par le générateur de nombres aléatoires peut être réduite car std::function est déclaré comme renvoyant un int . Vous pouvez donc utiliser un type de données différent de l’ int fonction de votre besoin de précision.

Enveloppez-le dans une classe ou un foncteur qui répond à vos besoins?

Je suggère deux méthodes: les objects fonction et les pointeurs de fonction. Dans les deux cas, autorisez votre classe à recevoir un object Function ou un pointeur de fonction au générateur de nombres aléatoires.

Avec un object fonction, vous pouvez définir une classe de base et demander à votre classe récepsortingce d’implémenter des fonctions nécessitant un pointeur sur la classe d’objects fonction de base. Cela vous donne plus de liberté pour définir plusieurs objects fonction différents sans modifier l’interface de la classe de réception.