У нас есть uniform_int_distribution
и uniform_real_distribution
, не было бы возможно иметь охватывающий uniform_distribution
, который специализируется на float/double и int/..., когда указано?
Почему нет единого_распределения?
Ответ 1
AFAIU, комментарии, приведенные выше @user877329 и @revolver_ocelot, объясняют это правильно, а другой ответ совершенно неверен.
Неправильно унифицировать интерфейсы uniform_int
и uniform_real
, а не потому, что они реализованы по-разному (которые могут быть решены с помощью специализированной специализации), но поскольку интерфейсы означают разные вещи.
Предположим, что мы унифицируем интерфейсы (используя вариацию предложения в другом ответе), например:
template <typename T>
using uniform_distribution =
typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>::type;
Тогда, если мы определим uniform_distribution<some_type> u(0, 9)
, значение будет совсем другим:
-
если
some_type
является интегралом, то u выведет 9 примерно 1/10th времени. -
если
some_type
нет, тогдаu
никогда не выведет 9.
Следующий код (выход которого true
, а затем false
) иллюстрирует это:
#include <random>
#include <iostream>
#include <type_traits>
template <typename T>
using uniform_distribution =
typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>::type;
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
{
uniform_distribution<int> u(0, 9);
bool over_found = false;
for(size_t i = 0; i < 99999; ++i)
over_found = over_found || u(gen) >= 9;
std::cout << std::boolalpha << over_found << std::endl;
}
{
uniform_distribution<float> u(0, 9);
bool over_found = false;
for(size_t i = 0; i < 99999; ++i)
over_found = over_found || u(gen) >= 9;
std::cout << std::boolalpha << over_found << std::endl;
}
}
Этот код иллюстрирует, что писать общий код с использованием этого класса является опасным. Например, если вы напишете общую функцию, вычисляющую гистограмму результатов в поддиапазонах: [0, 1), [1, 2),..., [8, 9), результаты будут несовместимы.
Как отмечает @revolver_ocelot, стандартная библиотека [inclusive-begin, exclusive_end] соглашение не может использоваться для однородных целых чисел (потому что было бы невозможно указать единую целочисленный генератор случайных чисел, генерирующий также максимальное значение uint), что делает его исключительной сигнатурой.