I'm trying to make a function that will fill a list with random numbers, and based on the type of the list items it should generate either integer or floating point numbers. So far I've come up with the following code, and it works:
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
if( typeid(T) == typeid(int) ){
uniform_int_distribution<T> distribution(1000, 2000);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
else if( typeid(T) == typeid(double) ){
uniform_real_distribution<T> distribution(1000.0, 2000.0);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
else{
return;
}
}
However, I'm not really satisfied with this solution. It just feels like there should be some way to break out everything but the actual distribution from that IF statement. Something like:
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
X distribution;
if( typeid(T) == typeid(int) )
distribution = uniform_int_distribution<T>(1000, 2000);
else if( typeid(T) == typeid(double) )
distribution = uniform_real_distribution<T>(1000.0, 2000.0);
else
return;
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
(X is a placeholder for what's missing here)
But since uniform_int_distribution
and uniform_real_distribution
don't have a common base class, how would that be possible? I have tried playing around with function pointers and functors, but I never seem to get past that IF-statement, and it's annoying. Can this be solved in a more elegant way?
NOTE: It's part of a school assignment, and we have to use generate()
and the <random>
functions and templates to generate the random numbers. I think my original solution is acceptable, I just don't like the look of those duplicate lines of code in the IF-statement... :)
You can create a typetrait-like class:
Another option is to create a template helper function that will accept the needed distribution as argument:
You are trying to calculate a type. That calls for (very, very, very) simple template meta programming:
This code does not compile, when T is neither
int
nordouble
. The compiler will complain, that there is no typeDistribution<T>::distribution
for yourT
.Assuming, silently doing nothing e.g. for float, or unsigned int, is really what you need:
Now the default just silently does nothing. To actually generate random numbers other than int or double, you have to specialize the template for your type, like I did for int and double.
You may use:
And then