代码之家  ›  专栏  ›  技术社区  ›  Alex Wicks

C++模板化均匀分布?

  •  0
  • Alex Wicks  · 技术社区  · 7 年前

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

    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 回复  |  直到 7 年前
        1
  •  8
  •   Hiroki    7 年前

    我们可以统一 GetRand 作为函数模板。

    首先,请注意 std::uniform_real_distribution<T> 如果 T 不是其中之一 float , double long double . 例如, 29.6.1.1一般要求[rand.req.genl] 在C++标准草案n4687中规定:

    贯穿本款 29.6 ,实例化模板的效果:

    ...

    d) 具有名为 实型 未定义,除非相应的模板 参数是cv不合格的,是其中之一 浮动 , 双重的 长双人 .

    此外 29.6 .8.2.2类模板统一实分布[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> . 因此,我们需要在 标准:均匀实分布<T> 标准:均匀分布<T> 取决于 T .


    我们可以使用 std::is_floating_point std::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;
    

    然后是两个超负荷的 格特兰 可以统一到以下函数模板。 在这里,我还避免递归构造 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)
    
    推荐文章