Подтвердить что ты не робот

Почему нет единого_распределения?

У нас есть uniform_int_distribution и uniform_real_distribution, не было бы возможно иметь охватывающий uniform_distribution, который специализируется на float/double и int/..., когда указано?

4b9b3361

Ответ 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), что делает его исключительной сигнатурой.