2010-02-11 106 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