C ++-模板化均匀分布?

时间:2019-03-21 04:08:29

标签: c++ templates overloading uniform-distribution

当前,我正在重载此函数以生成一个随机数:

float GetRand(float lower, float upper) {                                                                                                                                                      
    std::random_device rd;                                                                                                                                                                    
    std::mt19937_64 mt(rd());                                                                                                                                                                 
    std::uniform_real_distribution<float> dist(lower,upper);                                                                                                                                  
    return dist(mt);                                                                                                                                                                            
}                                                                                                                                                                                              

int GetRand(int lower, int upper) {                                                                                                                                                            
    std::random_device rd;                                                                                                                                                                    
    std::mt19937_64 mt(rd());                                                                                                                                                                 
    std::uniform_int_distribution<int> dist(lower,upper);                                                                                                                                     
    return dist(mt);                                                                                                                                                                          
}                                                                                                                                                                                             

是否可以使用模板执行此操作?我不知道如何为发行版做模板。

1 个答案:

答案 0 :(得分:4)

我们可以将GetRand的两个重载统一为函数模板。

首先,请注意,如果T不是floatdoublelong double之一,则std::uniform_real_distribution<T>的作用是不确定的。 例如,C ++标准草案n4687中的 29.6.1.1一般要求[rand.req.genl] 指出:

  

在本条 29.6 中,实例化模板的效果:

     

...

     除非对应的模板,否则未定义具有名为 RealType 的模板类型参数的

d)   参数是cv不合格的,并且是 float double long double 之一。

此外, 29.6 .8.2.2类模板Uniform_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_pointstd::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的递归构造,并使函数安全使用this post中接受的答案。

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)