Ale*_*cks 2 c++ templates overloading uniform-distribution
目前我正在重载这个函数来生成一个随机数:
float GetRand(float lower, float upper) {
std::random_device rd;
std::mt19937_64 mt(rd());
std::uniform_real_distribution<float> dist(lower,upper);
return dist(mt);
}
int GetRand(int lower, int upper) {
std::random_device rd;
std::mt19937_64 mt(rd());
std::uniform_int_distribution<int> dist(lower,upper);
return dist(mt);
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用模板来做到这一点?我不知道如何模板分发。
我们可以将两种重载统一GetRand为一个函数模板。
首先,请注意,std::uniform_real_distribution<T>如果T不是float,double和 中的一个, 的效果是未定义的long double。例如,C++ 标准草案 n4687 中的29.6.1.1 一般要求 [rand.req.genl]指出:
在本子条款29.6 中,实例化模板的效果:
...
d) 具有名为RealType的模板类型参数是未定义的,除非相应的模板参数是 cv-unqualified 并且是float、double或long double 之一。
另外,29.6 .8.2.2 Class template uniform_real_distribution [rand.dist.uni.real]std::uniform_real_distribution用模板类型参数描述RealType,因此std::uniform_real_distribution<int>未定义:
Run Code Online (Sandbox Code Playgroud)template<class RealType = double> class uniform_real_distribution { ... };
此外,对于 存在类似的限制std::uniform_int_distribution<T>。因此,我们需要之间切换的分布类型std::uniform_real_distribution<T>和std::uniform_int_distribution<T>根据T。
我们可以使用std::is_floating_point和检查上述限制std::is_integral并进行以下切换:
#include <random>
#include <type_traits>
template<class T>
using uniform_distribution =
typename std::conditional<
std::is_floating_point<T>::value,
std::uniform_real_distribution<T>,
typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
void
>::type
>::type;
Run Code Online (Sandbox Code Playgroud)
那么GetRand可以将的两个重载统一到下面的函数模板中。在这里,我也避免递归建设std::mt19937_64,使函数线程安全的应用接受的答案在这个职位。
template <class T>
T GetRand(T lower, T upper)
{
static thread_local std::mt19937_64 mt(std::random_device{}());
uniform_distribution<T> dist(lower,upper);
return dist(mt);
}
Run Code Online (Sandbox Code Playgroud)
最后,调用方将如下所示:
auto i = GetRand<int> (0, 1); // 0 or 1
auto f = GetRand<float> (0, 1); // [0, 1)
auto d = GetRand<double>(0, 1); // [0, 1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
630 次 |
| 最近记录: |