简体   繁体   English

如何将C ++ 11随机数生成器传递给函数?

[英]How do I pass a C++11 random number generator to a function?

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/ ) (我指的是这些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. 换句话说,我正在传递对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? 另外,我意识到这可能是一个不同的问题,但是如何将生成器传递给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: 传递给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. 它们都不都是从基类继承的(这有点令人惊讶),但这并不重要,因为那不是C ++函子的工作方式。

For arbitrary RNGs of a single given type, you got it right as (now) posted. 对于单个给定类型的任意RNG,您已经正确地做到了(现在)发布。

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. 定义一个函数以接受不同的RNG比较困难,因为从语义上讲,这需要具有通用的基本类型。 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 : 对我std::function是使用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. 您实际上并没有传递随机对象,而只是调用该对象的operator () ,但是它实现了相同的效果。

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. 请注意,由于std::function被声明为返回int ,因此随机数生成器返回值的精度可能会降低,因此根据精度的需要,您可能希望使用其他数据类型代替int

将它包装在适合您需要的课程或函子中吗?

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. 这使您可以在不更改接收类接口的情况下自由定义许多不同的函数对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM