为什么没有uniform_distribution?

时间:2016-08-14 07:48:41

标签: c++

我们有uniform_int_distributionuniform_real_distribution,如果指定的话,是不是可以拥有一个包含uniform_distribution,专门用于float / double和int / ...?

1 个答案:

答案 0 :(得分:14)

AFAIU,@ user877329和@revolver_ocelot上面的评论正确解释了这一点,另一个答案是完全错误的。

统一uniform_intuniform_real的接口是错误的,不是因为它们的实现方式不同(可以通过模板专业化来解决),而是因为接口意味着不同的东西< / em>的

假设我们统一接口(使用其他答案中的建议的变体),如下所示:

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是完整的,那么你将在大约1/10的时间内输出9。

  • 如果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) convention不能用于统一整数(因为不可能指定一个整数随机数生成器同时生成最大uint值),这使得这是一个特殊的签名。