2010-02-11 66 views
13

它们是否都从基类继承?我必须使用模板吗?如何将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?

似乎没有工作。


解决方案,通过发电机:

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

根据那篇文章,他们已经是仿函数,所以你应该准备好去。有什么问题? – Potatoswatter 2010-02-11 00:26:02

+0

如果我们知道您的目标,我们可能会提供更具体和有用的信息。 – GManNickG 2010-02-11 00:27:37

+0

具体来说,你希望你的生成器是不同的,你得到的'random_shuffle'编译器错误是什么? – Potatoswatter 2010-02-11 00:44:00

回答

10

它们并不都是从一个基地继承的(这有点令人惊讶),但它并不重要,因为这不是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 
} 
+0

这真的很不幸,因为这意味着我必须在头文件中包含所有的随机函数。 – 2010-02-11 00:35:55

+0

(但感谢您的回答...) – 2010-02-11 00:36:34

+0

@ Neil:看到我的第二个答案(我只承诺第一段)。我认为这个标准的意图是你选择一个发电机并坚持下去。如果你只想使用'std :: mt19937',那么不需要任何这个...但是你的问题还不清楚。 – Potatoswatter 2010-02-11 00:41:27

0

包装在一个类或满足您的需求函子?

+0

有没有一种自动化的方式来包装类似于函子的东西? – 2010-02-11 00:17:38

0

我建议两种方法:函数对象和函数指针。在任何一种情况下,都可以让你的类接收一个函数对象或一个函数指针给随机数生成器。

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

4

什么工作对我来说是使用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