Как передать генератор случайных чисел С++ 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); }
};

Ответы

Ответ 1

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

Для произвольных 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
}

Ответ 2

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

Ответ 3

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

Ответ 4

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

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