I am writing a program that holds a list<T>
where T
is either int
or double
. I want to make a function, using components from the header <random>
, that generates numbers of type T
. I can't find a distribution that takes T
as template argument.
The function is then going to be used in a call to the generate
function:
generate(myList.begin(), myList.end(), RandomGenerator())
How do I go about doing this?
I have tried to create a class called RandomGenerator
and overload the operator()
for it.
When i try to pass an argument to the overloaded operator()
i get an error.
Function call, Random(b)
is a function object with int
argument b
:
generate(rList.begin(), rList.end(), Random(b));
Code for overloading ()
, where n
is sort of a "dummy"-variable for just telling what type it is:
int operator()(int n)
{
std::uniform_int_distribution<int> dist(1000, 2000);
return dist(gen);
}
Error message:
Error 2 error C2440: '<function-style-cast>' : cannot convert from 'int' to 'Random'
Error 3 error C2780: 'void std::generate(_FwdIt,_FwdIt,_Fn0)' : expects 3 arguments - 2 provided
In addition to Joey's answer, the following should play nicely with std::generate
. Disclaimer: I'm terrible at metaprogramming, please do point out any mistakes or possible improvements. This is a C++11 solution, with C++14 it would be a bit shorter.
#include <algorithm>
#include <iostream>
#include <list>
#include <random>
#include <type_traits>
template<typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
class random_generator {
using distribution_type = typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>::type;
std::default_random_engine engine;
distribution_type distribution;
public:
auto operator()() -> decltype(distribution(engine)) {
return distribution(engine);
}
};
template<typename Container, typename T = typename Container::value_type>
auto make_generator(Container const&) -> decltype(random_generator<T>()) {
return random_generator<T>();
}
int main() {
auto l = std::list<double>(10);
std::generate(std::begin(l), std::end(l), make_generator(l));
for (auto i : l) {
std::cout << i << " ";
}
}