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

时间:2010-02-11 00:09:10

标签: c++ random c++11

它们都是从基类继承的吗?我必须使用模板吗?

(我指的是这些http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c15319/

我现在正在这样做:

typedef std::mt19937 RNG;

然后

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

换句话说,我正在传递对RNG的引用。我如何传入任意一个发生器?

另外,我意识到这可能是一个不同的问题,但我如何将生成器传递给STL?

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

似乎不起作用。


传递生成器的解决方案:

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

传递给STL的解决方案:

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

4 个答案:

答案 0 :(得分:14)

它们并非都从一个基础继承(这有点令人惊讶),但它并不重要,因为这不是C ++仿函数的工作方式。

对于单个给定类型的任意RNG,您可以(现在)发布它。

如果您的意思是,我如何定义一个接受任意随机数生成器作为参数的函数。

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

由于类型扣除,您不需要再使用此模板。


定义一个接受不同RNG的函数比较棘手,因为语义上需要具有公共基类型。您需要定义基本类型。

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
}

答案 1 :(得分:6)

对我有用的是使用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);

你并没有真正绕过随机对象,只是一种调用对象operator ()的方法,但它实现了同样的效果。

请注意,随着std::function被声明为返回int,随机数生成器的返回值的精度可能会降低,因此您可能希望使用不同的数据类型而不是int,取决于您对精度的需求。

答案 2 :(得分:0)

将它包装在符合您需求的课程或仿函数中?

答案 3 :(得分:0)

我建议使用两种方法:函数对象和函数指针。在任何一种情况下,都要使您的类接收函数对象或随机数生成器的函数指针。

使用Function对象,您可以定义基类,并使接收类实现需要指向基函数对象类的指针的函数。这使您可以更自由地定义许多不同的函数对象,而无需更改接收类的接口。