我们有uniform_int_distribution
和uniform_real_distribution
,如果指定的话,是不是可以拥有一个包含uniform_distribution
,专门用于float / double和int / ...?
答案 0 :(得分:14)
AFAIU,@ user877329和@revolver_ocelot上面的评论正确解释了这一点,另一个答案是完全错误的。
统一uniform_int
和uniform_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值),这使得这是一个特殊的签名。