我正在尝试创建一个用随机数填充列表的函数,并根据列表项的类型生成整数或浮点数。到目前为止,我已经提出了以下代码,它可以工作:
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;
}
}
但是,我对此解决方案并不满意。只是感觉应该有一些方法可以突破除IF语句中的实际分布之外的所有内容。类似的东西:
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是这里缺少的占位符)
但由于uniform_int_distribution
和uniform_real_distribution
没有共同的基类,这怎么可能呢?我试过玩函数指针和仿函数,但我似乎从来没有超过IF语句,这很烦人。这可以用更优雅的方式解决吗?
注意:这是学校作业的一部分,我们必须使用generate()
和<random>
函数和模板来生成随机数。我认为我的原始解决方案是可以接受的,我只是不喜欢IF语句中那些重复代码行的外观...:)
答案 0 :(得分:2)
您可以创建类似于类型的类:
template<class T>
struct Distribution {};
template<>
struct Distribution<int> {
typedef uniform_int_distribution<int> type;
};
template<>
struct Distribution<double> {
typedef uniform_real_distribution<double> type;
};
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
typename Distribution<T>::type distribution = typename Distribution<T>::type(1000, 2000);
...
另一种选择是创建一个模板助手函数,它将接受所需的分布作为参数:
template<class T, template<class> class Distr>
void generateRandomHelper(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
Distr<T> distribution = Distr<T>(1000, 2000);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
template<class T>
void generateRandom2(list<T>& numberList);
template<>
void generateRandom2<int>(list<int>& numberList) {
generateRandomHelper<int, uniform_int_distribution>(numberList);
}
template<>
void generateRandom2<double>(list<double>& numberList) {
generateRandomHelper<double, uniform_real_distribution>(numberList);
}
答案 1 :(得分:2)
您可以使用:
template <typename T>
using my_distribution = std::conditional_t<std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::conditional_t<std::is_floating_point<T>::value,
std::uniform_real_distribution<T>,
void>
>;
然后
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
my_distribution<T> distribution(1000, 2000);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
答案 2 :(得分:-1)
您正在尝试计算类型。这要求(非常,非常,非常)简单的模板元编程:
template<typename T> class Distribution;
template<> class Distribution<int> {
using distribution = uniform_int_distribution<int>;
};
template<> class Distribution<double> {
using distribution = uniform_real_distribution<int>;
};
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
Distribution<T>::distribution distribution(1000, 2000);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
当T既不是int
也不是double
时,此代码无法编译。编译器会抱怨,Distribution<T>::distribution
没有T
类型。
假设,默默无闻,例如对于float或unsigned int,确实是你需要的:
template<typename T> class Distribution {
public:
// just anything, so that there is a type
// not sure if this is really necessary
using distribution = uniform_int_distribution<int>;
static const bool valid = false;
};
template<> class Distribution<int> {
public:
using distribution = uniform_int_distribution<int>;
static const bool valid = true;
};
template<> class Distribution<double> {
public:
using distribution = uniform_real_distribution<double>;
static const bool valid = true;
};
template <typename T>
void generateRandom(list<T>& numberList){
default_random_engine randomGenerator(random_device{}());
if(!Distribution<T>::valid) return;
Distribution<T>::distribution distribution(1000, 2000);
auto myGenerator = bind(distribution, randomGenerator);
generate(numberList.begin(), numberList.end(), myGenerator);
}
现在默认只是默默无效。要实际生成除int或double之外的随机数,您必须专门为您的类型设置模板,就像我为int和double所做的那样。