Мы можем объединить обе перегрузки GetRand
как шаблон функции.
Прежде всего, обратите внимание, что эффект std::uniform_real_distribution<T>
не определенесли T
не является одним из float
, double
и long double
.Например, 29.6.1.1 Общие требования [rand.req.genl] в стандартном черновике C ++ n4687 гласит:
На протяжении всего этого подпункта 29,6 , эффектсоздания шаблона:
...
d) с параметром типа шаблона с именем RealType не определен, если только соответствующий аргумент шаблона не cv-unqualified и не равен единице float , double или long double .
Кроме того, 29,6 .8.2.2 Шаблон классаiform_real_distribution [rand.dist.uni.real] описывает std::uniform_real_distribution
с параметром типа шаблона RealType
и, следовательно, std::uniform_real_distribution<int>
не определено:
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;
Тогда две перегрузки 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);
}
Наконец, сторона вызывающего абонента будетследующим образом:
DEMO
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)