Boost.Random似乎没有提供将生成器与分布绑定在一起的类。您可以创建一个将两者绑定在一起的模板仿函数类。
Boost.Foreach和Boost.Range对于编写在任何容器、数组或迭代器对上运行的通用代码很有用。
一旦你定义了一个绑定生成器和分布的函子,我想出了以下允许你简洁地随机化容器的方法。
#include <iostream>
#include <vector>
#include <boost/random.hpp>
#include <boost/foreach.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/range/algorithm/generate.hpp>
namespace rng // some nice namespace
{
//------------------------------------------------------------------------------
// Binds a generator together with a distribution
template <class D, class G>
struct Functor
{
typedef D Distribution;
typedef G Generator;
typedef typename D::result_type result_type;
Distribution distribution;
Generator generator;
explicit Functor(const D& dist = D(), const G& gen = G())
: distribution(dist), generator(gen) {}
result_type operator()() {return distribution(generator);}
};
//------------------------------------------------------------------------------
// Randomizes a collection (range) with the given functor
template <class Range, class Functor>
void randomize(Range& range, Functor& functor)
{
BOOST_FOREACH(typename boost::range_reference<Range>::type x, range)
{
x = functor();
}
}
} // namespace rng
//------------------------------------------------------------------------------
int main()
{
namespace brnd = boost::random;
typedef rng::Functor<brnd::uniform_int_distribution<>, brnd::mt19937> Dice;
// This object could be made global if desired
Dice dice(Dice::Distribution(1,6));
std::vector<int> rolls(10);
rng::randomize(rolls, dice); // Concise one-liner!
/* Could also use the following one-liner, but dice would be passed by
copy and the resulting RNG state would not be retained. */
// boost::generate(rolls, dice);
std::cout << "Rolls:\n";
BOOST_FOREACH(int roll, rolls)
std::cout << roll << "\n";
}
通过使用模板特化,您可以为各种数字类型提供默认生成器:
//------------------------------------------------------------------------------
template <typename T>
struct DefaultFunctor
{
typedef Functor<boost::random::uniform_int_distribution<T>,
boost::random::mt19937> Type;
static T generate() {static Type fn; return fn();}
};
template <>
struct DefaultFunctor<float>
{
typedef Functor<boost::random::uniform_01<float>,
boost::random::mt19937> Type;
static float generate() {static Type fn; return fn();}
};
template <>
struct DefaultFunctor<double>
{
typedef Functor<boost::random::uniform_01<double>,
boost::random::mt19937> Type;
static double generate() {static Type fn; return fn();}
};
//------------------------------------------------------------------------------
template <class Range>
void randomize(Range& range)
{
typedef typename boost::range_value<Range>::type value_type;
BOOST_FOREACH(typename boost::range_reference<Range>::type x, range)
{
x = DefaultFunctor<value_type>::generate();
}
}
//------------------------------------------------------------------------------
int main()
{
std::vector<float> noise(10);
rng::randomize(noise);
std::cout << "Noise:\n";
BOOST_FOREACH(float sample, noise)
std::cout << sample << "\n";
}