生成T类型的随机数

时间:2014-10-06 13:58:58

标签: c++ c++11

我正在撰写一个程序,其中包含list<T>,其中Tintdouble。我想创建一个函数,使用标题<random>中的组件生成T类型的数字。我找不到以T作为模板参数的分发。

然后该函数将用于调用generate函数:

generate(myList.begin(), myList.end(), RandomGenerator())

我该怎么做?

我尝试创建一个名为RandomGenerator的类,并为其重载operator()。 当我尝试将参数传递给重载的operator()时,我得到一个错误。

函数调用,Random(b)是一个带有int参数b的函数对象:

generate(rList.begin(), rList.end(), Random(b)); 

重载代码(),其中n是一种“虚拟”变量,只是告诉它是什么类型:

int operator()(int n)
{
    std::uniform_int_distribution<int> dist(1000, 2000);
    return dist(gen);
}

错误讯息:

Error   2   error C2440: '<function-style-cast>' : cannot convert from 'int' to 'Random'    

Error   3   error C2780: 'void std::generate(_FwdIt,_FwdIt,_Fn0)' : expects 3 arguments - 2 provided    

2 个答案:

答案 0 :(得分:3)

不是一个优雅的解决方案,但你做了你想要的:(修改代码,以便它可以与生成一起使用)

template <typename Distribution>
class RandomGenerator
{
    using Type = typename Distribution::result_type;

    const Type getRandom(const Type& lower, const Type& upper) const
    {
        static std::default_random_engine generator;
        static Distribution distribution(lower, upper);

        return distribution(generator);
    }

public:
    RandomGenerator(const Type& lowerBound, const Type& upperBound) : _lowerBound(lowerBound), _upperBound(upperBound) { }

    const Type operator()() const
    {
        return getRandom(_lowerBound, _upperBound);
    }

private:
    Type _lowerBound;
    Type _upperBound;
};

int main()
{
    RandomGenerator<std::uniform_int_distribution<>> randomIntGenerator(1, 10);
    RandomGenerator<std::uniform_real_distribution<>> randomDoubleGenerator(0.0, 10.0);

    std::deque<int> intRandoms(10);
    std::generate(intRandoms.begin(), intRandoms.end(), randomIntGenerator);

    std::deque<double> doubleRandoms(5);
    std::generate(doubleRandoms.begin(), doubleRandoms.end(), randomDoubleGenerator);

    return 0;
}

当然,如果我们想要每次运行都有不同的数字,我们可以将default_random_engine的种子设置为类似于时间(0)的东西,但是我会把它留下来。

答案 1 :(得分:3)

除了Joey的回答,以下内容应与std::generate很好地配合使用。免责声明:我在元编程方面很糟糕,请指出任何错误或可能的改进。这是一个C ++ 11解决方案,使用C ++ 14会有点短。

Live demo on Coliru

#include <algorithm>
#include <iostream>
#include <list>
#include <random>
#include <type_traits>

template<typename T,
         typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
class random_generator {
    using distribution_type = typename std::conditional<
            std::is_integral<T>::value,
            std::uniform_int_distribution<T>,
            std::uniform_real_distribution<T>
        >::type;

    std::default_random_engine engine;
    distribution_type distribution;

public:
    auto operator()() -> decltype(distribution(engine)) {
        return distribution(engine);
    }
};

template<typename Container, typename T = typename Container::value_type>
auto make_generator(Container const&) -> decltype(random_generator<T>()) {
    return random_generator<T>();
}

int main() {
    auto l = std::list<double>(10);

    std::generate(std::begin(l), std::end(l), make_generator(l));    

    for (auto i : l) {
        std::cout << i << " ";    
    }
}