Как передать генератор случайных чисел С++ 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 вы можете определить базовый класс и реализовать свой приемный класс для функций, которым требуется указатель на класс объектов базовой функции. Это дает вам больше свободы в определении множества различных объектов функций без изменения интерфейса получающего класса.