Как передать генератор случайных чисел C ++ 11 в функцию? - PullRequest
17 голосов
/ 11 февраля 2010

Все они наследуются от базового класса? Нужно ли использовать шаблоны?

(я имею в виду эти 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):

Другими словами, я передаю ссылки на ГСЧ. Как мне передать произвольный генератор?

Кроме того, я понимаю, что, возможно, это другой вопрос, но как передать генератор в 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 ]

14 голосов
/ 11 февраля 2010

Они не все наследуются от базы (что немного удивительно), но это не имеет значения, потому что это не так, как работают функторы C ++.

Для произвольных ГСЧ одного заданного типа вы правильно поняли, как (сейчас) опубликовано.

Если вы имеете в виду, как мне определить функцию, которая принимает любой генератор случайных чисел в качестве аргумента.

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

Вам не нужно использовать больше шаблонов, чем это, из-за вывода типа.


Определение одной функции для приема разных ГСЧ сложнее, поскольку семантически это требует наличия общего базового типа. Вам необходимо определить базовый тип.

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
}
6 голосов
/ 12 июня 2016

Для меня сработало использование 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 в зависимости от вашей потребности в точности.

0 голосов
/ 11 февраля 2010

Я предлагаю два метода: функциональные объекты и функциональные указатели. В любом случае, разрешите вашему классу получать объект функции или указатель на генератор случайных чисел.

С помощью Function Object вы можете определить базовый класс, и ваш принимающий класс реализует функции, для которых требуется указатель на класс объекта base function. Это дает вам больше свободы в определении множества различных функциональных объектов без изменения интерфейса принимающего класса.

0 голосов
/ 11 февраля 2010

Оберните это в класс или функтор, которые соответствуют вашим потребностям?

...